---
title: "Pixeltable for media and entertainment"
description: "Index a clip library: sample frames, transcribe speech, search by sentence. A worked trailer-and-archive pipeline with TableModel code."
url: "https://www.pixeltable.com/industries/media-and-entertainment"
updated: "2026-10-28"
doc: "https://docs.pixeltable.com/howto/cookbooks/video/video-extract-frames"
---

# Pixeltable for media and entertainment

Media teams need a moment in a library, not a filename. Sample stills, transcribe speech, index both, and serve search. Twelve Labs and Mixpeek are managed video APIs. Pixeltable is the table, the timestamps, and HTTP in a file you own.

Updated: 2026-10-28
Docs: https://docs.pixeltable.com/howto/cookbooks/video/video-extract-frames

A streaming catalog, a sports archive, or a trailer bay is thousands of hours. Editorial asks for "the shot where the product hits the table." Legal asks for every time a competitor logo is on screen. Post asks for spoken-word search over interviews. The files already live on S3. The missing piece is stills with timestamps, a transcript, and an index that updates when a new master lands.
Managed video APIs (Twelve Labs, Mixpeek) return JSON. That is the right product when you do not want a table. This page is the table: a Video column, frame_iterator, Whisper, CLIP, and FastAPIRouter. The reference architecture is /reference-architecture/video-search.

## Trailer and archive search pipeline {#pipeline}

1. Insert title, show, and the mezzanine or trailer file.
2. Extract audio and transcribe with Whisper (or a hosted STT API on the same column).
3. Sample one still per second. Keep frame_attrs.
4. Index stills with CLIP and the transcript with a sentence embedding.
5. Serve /trailers insert, /search over stills, and /search-speech over transcripts. A still hit is a title plus a presentation timestamp; a transcript hit is the trailer.

## Worked example: search trailers by what is shown or said {#worked-example}

This is the video-search architecture with a show column for editorial filters. Keep S3 as the archive. Keep Twelve Labs when a hosted video model is the product. WhisperX is a separate cookbook if you need speakers.

```python
import pixeltable as pxt
from pixeltable.functions.huggingface import clip, sentence_transformer
from pixeltable.functions.video import extract_audio, frame_iterator
from pixeltable.functions.whisper import transcribe
from pixeltable.serving import FastAPIRouter

TableModel = pxt.model_base()
clip_embed = clip.using(model_id='openai/clip-vit-base-patch32')
text_embed = sentence_transformer.using(model_id='all-MiniLM-L6-v2')

class Trailers(TableModel, name='trailers'):
    title: pxt.String
    show: pxt.String
    video: pxt.Video
    audio = extract_audio(video)
    transcript = transcribe(audio, model='base').text.astype(pxt.String)
    __indexes__ = [
        pxt.EmbeddingIndex(transcript, string_embed=text_embed),
    ]

class Frames(
    TableModel,
    name='frames',
    base=Trailers,
    iterator=frame_iterator(video=Trailers.video, fps=1),
):
    __indexes__ = [
        pxt.EmbeddingIndex(frame, embedding=clip_embed),
    ]

@pxt.query
def search_shots(query: str, limit: int = 5):
    sim = Frames.frame.similarity(string=query)
    return (
        Frames.order_by(sim, asc=False)
        .limit(limit)
        .select(title=Trailers.title, show=Trailers.show, frame_attrs=Frames.frame_attrs, score=sim)
    )

@pxt.query
def search_speech(query: str, limit: int = 5):
    sim = Trailers.transcript.similarity(string=query)
    return (
        Trailers.order_by(sim, asc=False)
        .limit(limit)
        .select(Trailers.title, Trailers.show, score=sim)
    )

api = FastAPIRouter(name='trailers')
api.add_insert_route(
    Trailers,
    path='/trailers',
    inputs=[Trailers.title, Trailers.show],
    uploadfile_inputs=[Trailers.video],
)
api.add_query_route(path='/search', query=search_shots)
api.add_query_route(path='/search-speech', query=search_speech)

# pxt init
# pxt schema update app.py trailers -f
# pxt service update app.py trailers -f
```

To run a sketch, install pixeltable[serve] and the packages its model functions import (such as sentence-transformers, openai, or openai-whisper), export the provider key a model call reads (such as OPENAI_API_KEY), save the file as app.py, and run the commands in its last lines. The tables start empty: insert a row, or POST to an insert route, then select the computed columns. [Get started](https://www.pixeltable.com/get-started) covers the CLI.

## Honest alternatives per slot {#alternatives}

| Slot | Role | Pixeltable | Named alternatives |
| --- | --- | --- | --- |
| Managed video API | Hosted embed and caption | CLIP and Whisper as columns on your table | Twelve Labs: You want Marengo / Pegasus and no GPU of your own; Mixpeek: A managed multimodal retrieval API is the product |
| Object store | Mezzanines and trailers | Video column, or insert the S3 URL | Amazon S3: The archive already lives there; Cloudflare R2: S3-compatible storage with no egress fee on that vendor |
| Speech-to-text | Spoken-word search | whisper.transcribe or openai.transcriptions on extract_audio | Deepgram, AssemblyAI: A hosted STT API is the model choice; WhisperX: You need speakers; that is a separate cookbook |

## Where Pixeltable fits {#where-pixeltable-fits}

Pixeltable is the library table: trailers, frames, transcripts, CLIP, and HTTP. Keep S3 as the archive. Keep Twelve Labs or Mixpeek when their API is the product. Pixeltable vs Twelve Labs and Pixeltable vs Mixpeek are that split. The how-to is How do I index a video library and search it by text. The gallery app is /recipes/video-search.

## Questions {#questions}

### Can I filter by show after CLIP ranks stills? {#faq-1}

Yes. Add .where(Trailers.show == name) on the query. That is hybrid search in the sense of similarity plus metadata, not BM25 fusion. BM25 fusion is Weaviate.

### Do I need to reindex the archive when a trailer is replaced? {#faq-2}

Insert or update that row. Computed columns and indexes recompute the affected episode. Unchanged titles stay cached. A managed API has its own reindex contract; read theirs.

## Related

- [Video search architecture](https://www.pixeltable.com/reference-architecture/video-search)
- [Search a video library by text](https://www.pixeltable.com/learn/how-to/search-a-video-library-by-text)
- [Video search engine use case](https://www.pixeltable.com/use-cases/video-search-engine)
- [Video search example app](https://www.pixeltable.com/recipes/video-search)
- [Pixeltable vs Twelve Labs](https://www.pixeltable.com/compare/pixeltable-vs-twelve-labs)
- [Examples hub: video search](https://www.pixeltable.com/examples)
- [Extract frames (docs)](https://docs.pixeltable.com/howto/cookbooks/video/video-extract-frames)

Architectures: [reference architectures](https://www.pixeltable.com/reference-architecture). Task-grouped examples: [examples](https://www.pixeltable.com/examples).
