Pixeltable and Mixpeek

Updated

Which is better, Pixeltable or Mixpeek?

It depends. Mixpeek belongs when you want a managed multimodal retrieval API: connect a bucket, extract scenes, speech and OCR, and search over HTTP without running models. Pixeltable belongs when the clip, the timestamp, the index and HTTP should live in one app.py you own. Keep Mixpeek if the hosted retriever is the product. Pixeltable Cloud is Limited Beta. As of 2026-10-23.

Mixpeek is a managed retrieval API: connect a bucket, extract scenes, speech and OCR, and search over HTTP. Pixeltable is the application schema those results can live on. Often complementary, not exclusive: call Mixpeek when the hosted retriever is the product, and keep the clip in a Video column you own when the table is the product.

pip install 'pixeltable[serve]'
See how it works

Managed retrieval API vs the table

SidePixeltableMixpeek
At a glance
  • Video column plus a frame_iterator view; insert indexes new clips
  • CLIP EmbeddingIndex on frames; optional Whisper on the soundtrack
  • column.similarity(string=) is the score; the query returns a title, timestamp, and score
  • Same file can serve FastAPIRouter; Cloud is Limited Beta
  • Managed indexing: point at video, audio, or documents in your bucket
  • Retrievers.execute over HTTP; Python SDK pip install mixpeek
  • BYO vectors (MVS) or managed extractors (features such as video_search)
  • BYO-Cloud self-host option; Build plan from $25/mo plus usage (mixpeek.com, 2026-10-23)

What each actually owns

Mixpeek wins a hosted multimodal extraction and retrieval API with no models to run. Pixeltable wins the owned catalog, incremental insert, and HTTP beside the clip. Last reviewed: Oct 2026. Sources: mixpeek.com, mixpeek.com/video-search, docs.mixpeek.com/docs/overview/quickstart (accessed 2026-10-23).

FeaturePixeltableMixpeek
What it is
Application schema: store, transform, index, serve
Managed multimodal retrieval API
Where the clip lives
A Video column you query, version, and attach other columns to
An existing bucket Mixpeek can read in place, or a Mixpeek bucket you upload into
Who runs the models
You, locally or on Cloud (Limited Beta)
Mixpeek, unless you bring your own vectors or deploy BYO-Cloud
Insert a new file
Insert a row; frames and the index run for that clip
Upload or connect the object, trigger the collection, poll the task
Search API
column.similarity(...) on the frame view you own
retrievers.execute against a hosted retriever
Images, PDFs, HTTP you own
Same schema: Image, Document, FastAPIRouter
Same API family for video, image, audio, documents; not an application table
Self-host
pip install pixeltable; Cloud is Limited Beta
Your own cloud (BYO-Cloud) (mixpeek.com FAQ, accessed 2026-10-23)

Index a folder of videos and search by text

Pixeltable: frame_iterator view and CLIP EmbeddingIndex. Apply with pxt schema update app.py video_lib. Mixpeek: the quickstart creates a Mixpeek bucket, uploads into it, triggers the collection once, polls tasks.get, creates a retriever, then retrievers.execute with inputs query_text. Connecting an existing bucket is a separate FAQ path. Snippets from docs.mixpeek.com/docs/overview/quickstart (accessed 2026-10-23); not executed here (needs a Mixpeek API key and plan).

Pixeltable

import pixeltable as pxt
from pixeltable.functions.huggingface import clip
from pixeltable.functions.video import frame_iterator
from pixeltable.serving import FastAPIRouter
TableModel = pxt.model_base()
clip_embed = clip.using(model_id='openai/clip-vit-base-patch32')
class Videos(TableModel, name='videos'):
title: pxt.String
video: pxt.Video
class Frames(
TableModel,
name='frames',
base=Videos,
iterator=frame_iterator(video=Videos.video, fps=1),
):
__indexes__ = [pxt.EmbeddingIndex(frame, embedding=clip_embed)]
@pxt.query
def search_video(query: str, limit: int = 5):
sim = Frames.frame.similarity(string=query)
return (
Frames.order_by(sim, asc=False)
.limit(limit)
.select(title=Videos.title, frame_attrs=Frames.frame_attrs, score=sim)
)
api = FastAPIRouter(name='video_lib')
api.add_insert_route(
Videos, path='/videos', inputs=[Videos.title], uploadfile_inputs=[Videos.video]
)
api.add_query_route(path='/search', query=search_video)

Mixpeek

import os
from mixpeek import Mixpeek
client = Mixpeek(api_key=os.environ['MIXPEEK_API_KEY'])
ns = client.namespaces.create(namespace_name='video-demo')
client.namespace = ns['namespace_id']
bucket = client.buckets.create(
bucket_name='demo-videos',
bucket_schema={'properties': {'video': {'type': 'video'}}},
)
# This quickstart creates a Mixpeek bucket and uploads into it.
# An existing S3, GCS, or Azure bucket is the separate FAQ path.
col = client.collections.create(
collection_name='video-scenes',
source={'type': 'bucket', 'bucket_ids': [bucket['bucket_id']]},
features=['video_search'],
)
client.buckets.upload(
bucket['bucket_id'],
blobs=[{
'property': 'video',
'type': 'video',
'data': 'https://example.com/lecture.mp4',
}],
)
result = client.collections.trigger(col['collection_id'])
task = client.tasks.get(task_id=result['task_id'])
# Repeat tasks.get until task['status'] is COMPLETED or COMPLETED_WITH_ERRORS.
# Do not call collections.trigger again to poll.
ret = client.retrievers.create(
retriever_name='video-search',
input_schema={'query_text': {'type': 'text', 'required': True}},
collection_identifiers=[col['collection_id']],
stages=[{
'stage_name': 'search',
'stage_type': 'filter',
'config': {
'stage_id': 'feature_search',
'parameters': {
'searches': [{
'feature_uri': 'mixpeek://universal_extractor@v1/gemini-embedding-2',
'query': {'input_mode': 'text', 'value': '{{INPUT.query_text}}'},
'top_k': 50,
}],
'final_top_k': 20,
},
},
}],
)
results = client.retrievers.execute(
ret['retriever_id'],
inputs={'query_text': 'person at a whiteboard'},
)
for doc in results['documents']:
print(doc['document_id'], doc.get('start_time'), doc['score'])

When each belongs

Use Pixeltable when

  • You need the clip next to other columns

    Transcripts, detections, documents, and HTTP in one file. Mixpeek can still be the retriever you call from a computed column or a route.

  • A coding agent writes the app

    One app.py to review. pip install pixeltable. Pixeltable Cloud is Limited Beta, not GA.

Use Mixpeek when

  • A managed video search API is the product

    You want extraction and retrieval over HTTP without running CLIP or Whisper. Pixeltable is extra if the API response is enough.

  • You already pay for Mixpeek

    Keep it. Point Pixeltable at the same bucket when you also need an owned table; otherwise stay on their SDK. Docs: https://www.mixpeek.com/docs/overview/quickstart

Making the right choice

  • And, not or

    • Do not migrate off Mixpeek just to complete the stack. Keep it if the hosted retriever is the contract.
    • The homepage FAQ says Mixpeek can read an existing S3, GCS, Azure, or S3-compatible bucket in place (accessed 2026-10-23). The code sample uses the quickstart: a Mixpeek bucket you upload into.
    • Managed path: namespaces.create, buckets.create, collections.create with features, upload, trigger, retrievers.execute (quickstart, accessed 2026-10-23).
    • Build starts at $25/mo plus usage for both MVS and Managed (mixpeek.com pricing, accessed 2026-10-23). Confirm current rates on their site.

Frequently asked questions

Keep the clip. Call a retriever if you need one.

Declare a Video table and a frame view. Apply with pxt schema update. Use Mixpeek when a managed video search API is the product.

pip install 'pixeltable[serve]'
See how it worksGet expert guidance