> For a complete page index of the Captain API documentation, fetch https://docs.captain.dev/llms.txt?excludeSpec=true

# Video

> How Captain indexes video files. Clips of up to 120 seconds, each with a transcript and a written description of what is on screen, so a query lands on a time offset.

## Agent Quick Reference - Video

* Extensions: `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.flv`, `.wmv`. Normalised to a standard 720p MP4 before processing.
* Segmented into contiguous clips of up to 120 s (fixed windows). Each clip gets one native embedding from the clip itself, a transcript slice, and a written description: category line, then subjects, actions, setting, on-screen text transcribed verbatim (slides, captions, UI), charts and diagrams. The description never paraphrases speech; that is the transcript's job.
* Transcript: one speech-to-text pass over the whole file, language detected automatically; force it with `transcription_language` (for example `es-US`, `pt-BR`). Word timings are used to slice the transcript per clip. No speaker labels.
* Query hit: `modality: "video"`, content `[Video: name]` + description + `Transcript: …`; time range at `location.start_seconds` / `location.end_seconds` (v3) or `metadata.startSec` / `endSec` (v2).
* A file whose audio track cannot be decoded is indexed video-only; speech is still captured from the source file.
* YouTube: `POST /v2/collections/{c}/index/youtube` with `mode` `transcript` (default), `audio` or `video`, `on_missing_transcript`, `languages`, up to 20 URLs.
* Billing: 20 credits per minute of video. Upload limits by route on File Size Limits.
* `mask_pii`: video is not masked. A request with `mask_pii: true` skips video files: they are not indexed, and the job lists them as skipped.

Captain indexes video as clips of up to 120 seconds. Each clip has a time range, a native
embedding of the clip, a transcript slice and a written description of what is on screen.
This page covers how a video is cut, what each clip contains, what a result contains, YouTube
options, and the limits.

## This is useful for

* Product demos and webinars, where the reader wants the moment rather than the file
* Training and onboarding video, found by what is on the slide as well as what is said
* Screen recordings of bugs and walkthroughs, found by the text in the UI
* Site and inspection footage filmed on a phone, with or without narration

## What one video becomes

The file is normalised to a standard 720p MP4 and cut into contiguous clips of up to 120
seconds. Each clip gets a native embedding of the clip itself, a transcript slice and a
written description, stored together on one record.

## How a video is chunked

#### Clips with a time range

Clips are contiguous 120-second windows; the last one is shorter. Every clip carries
`location.start_seconds` and `location.end_seconds` on the v3 query, or
`metadata.startSec` and `metadata.endSec` on v2.

#### Transcript

Speech-to-text runs once over the whole file, so a sentence that crosses a clip boundary
is transcribed correctly. Word timings are then used to give each clip the words spoken
inside its window. Language is detected automatically; set `transcription_language` (for
example `es-US` or `pt-BR`) to force one. There are no speaker labels.

#### Description

Each clip's description has a category line and three to five sentences covering
subjects, actions, objects and setting, with on-screen text transcribed verbatim (slide
titles, captions, UI labels) and charts or diagrams read out. The description does not
repeat the speech; spoken words are in the transcript.

#### Three signals on one record

The native embedding, the transcript slice and the description are stored on the same
record. A query matches the picture by vector similarity and the words by text. The
result text is `[Video: file name]`, then the description, then `Transcript: …`.

#### Audio problems

A video whose audio track cannot be decoded is indexed video-only. Its speech is still
transcribed, because the speech-to-text pass reads the source file rather than the
normalised copy. A silent video has no transcript.

## YouTube

`POST /v2/collections/{collection}/index/youtube` accepts up to 20 URLs. `mode: "transcript"`
(the default) indexes the captions as text and bills as text. `mode: "audio"` or
`mode: "video"` runs the media pipeline and bills per minute. `on_missing_transcript`
(`fail`, `audio` or `video`) sets what happens to a video with no captions, and `languages`
sets the caption language preference.

## Limits and billing

Video is billed at 20 credits per minute, summed per job. Size limits depend on the route:
100 MB through the direct upload endpoint, 500 MB from the dashboard, and no upload limit
from a cloud storage connector. Collections that contain media rerank by default; see
[Multimodal Search](/guides/multimodal-search) and [File Size Limits](/guides/file-size-limits).

## Examples

#### Jump to a moment in a product demo

Goal: return the clip where the presenter filters a report by region, with the offset to
play from.

**`request`**

```json title="request"
{
  "query": "filtering the report by region",
  "limit": 3
}
```

**`result (one item)`**

```json title="result (one item)"
{
  "modality": "video",
  "text": "[Video: q3-demo.mp4]\nCategory: software demo, dashboard. A presenter opens a filter panel on the left of an analytics dashboard and selects 'EMEA'...\nTranscript: let's narrow this down to EMEA so you can see the regional split",
  "location": {
    "start_seconds": 480.0,
    "end_seconds": 600.0
  }
}
```

The description records the filter panel and the transcript records "EMEA". Both are on
the clip that starts at 480 seconds.

#### Training video, found by the slide title

Goal: find the clip that shows a procedure's slide, even though the presenter does not
read the title aloud.

**`request`**

```json title="request"
{
  "query": "lockout tagout procedure",
  "limit": 3,
  "filter": {
    "course": {
      "$eq": "site-induction"
    }
  }
}
```

On-screen text is transcribed into the description, so the slide title is searchable.

#### A screen recording with no narration

Goal: find a silent bug reproduction by the text of the error dialog.

**`request`**

```json title="request"
{
  "query": "\"payment method declined\" dialog",
  "limit": 3
}
```

The description transcribes UI text. A silent clip has no transcript line.

See [Supported File Types](/guides/supported-file-types#video) for the extension table and
[Audio](/guides/file-types/audio) for audio-only files.