# Turn any video into context for AI agents

Paste a link or drop a file. Get the transcript, chapters and metadata as Markdown, a .zip, or straight into your agent over MCP.

Open a video in the app: https://vid2context.com/app/?url=<encoded link>. Examples:

- [G-Wagon buyer’s guide](https://vid2context.com/app/?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcCPsdFdlshc)
- [Me at the zoo](https://vid2context.com/app/?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DjNQXAC9IVRw)
- [NASA podcast episode](https://vid2context.com/app/?url=https%3A%2F%2Ftraffic.megaphone.fm%2FNATIONALAERONAUTICSANDSPACEADMINISTRATION1369565567.mp3)
- [Vimeo video](https://vid2context.com/app/?url=https%3A%2F%2Fvimeo.com%2F76979871)

- Free and open source
- No key needed
- Runs locally

## A real result

The bundle vid2context produces for "Me at the zoo" (https://www.youtube.com/watch?v=jNQXAC9IVRw), rendered from a recorded run. Files in me-at-the-zoo.zip: `README.md`, `context.md`, `transcript.txt`, `context.json`, `transcript.md`, `transcript.srt`, `transcript.vtt`, `metadata.json`, `chapters.md`, `manifest.json`. This is `context.md`:

```markdown
# Video context pack

This document holds the transcripts and metadata of one video (0:19 in total), prepared by vid2context for an AI model to read. Each transcript paragraph starts with the time it begins in the video, in brackets; linked times open the video at that moment.

Citation rule: when you use something from a video, cite it as [Title @ m:ss](link), using the time and link of the paragraph you drew on (or [Title @ m:ss] when the video has no link).

## Me at the zoo

- Channel: [jawed](https://www.youtube.com/channel/UC4QobU6STFB0P71PMvOGN5A)
- Duration: 0:19
- Source: https://www.youtube.com/watch?v=jNQXAC9IVRw
- Language: en
- Transcript: creator captions from youtube-captions

### Description

> Microplastics are accumulating in human brains at an alarming rate
> https://www.youtube.com/watch?v=0PT5c1z3LL8
>
> “Nanoplastics and Human Health” with Matthew J Campen, PhD, MSPH
> https://www.youtube.com/watch?v=RRBN_4L09Mg
>
> 00:00 Intro
> 00:05 The cool thing
> 00:17 End

### Chapters

- [0:00](https://www.youtube.com/watch?v=jNQXAC9IVRw&t=0s) Intro
- [0:05](https://www.youtube.com/watch?v=jNQXAC9IVRw&t=5s) The cool thing
- [0:17](https://www.youtube.com/watch?v=jNQXAC9IVRw&t=17s) End

### Transcript

#### Intro (0:00)

[0:01](https://www.youtube.com/watch?v=jNQXAC9IVRw&t=1s) All right, so here we are, in front of the elephants

#### The cool thing (0:05)

[0:05](https://www.youtube.com/watch?v=jNQXAC9IVRw&t=5s) the cool thing about these guys is that they have really... really really long trunks and that's cool (baaaaaaaaaaahhh!!) and that's pretty much all there is to say
```

Try the live API: `curl "https://vid2context.com/api/v1/transcript?url=https://www.youtube.com/watch?v=jNQXAC9IVRw&timestamps=1"`. YouTube often blocks cloud servers, so run it locally when that fails.

## How it works

1. **Paste a link or upload a file.** A video page from YouTube, Vimeo, Podcasts, Google Drive, Dropbox and OneDrive links or any site yt-dlp supports, or an audio or video file from your machine.
2. **Captions first, then free speech-to-text.** Existing captions are used when the video has them. Otherwise the audio goes through a chain of speech-to-text rungs, local first, then free tiers, then keyless hosts. Every attempt is recorded, so you can see what ran and why.
3. **Copy it, download it, or hand it to your agent.** Copy Markdown with timestamps, download a .zip with every format, or let Claude, Cursor, VS Code and other agents fetch it themselves over MCP.

The transcript chain, tried in order:

1. **Creator captions:** Uploaded by the creator, when the video has them.
2. **Auto-captions:** The platform’s automatic captions, in your language.
3. **Speech-to-text:** Download the audio and transcribe it through 13 Whisper-class rungs.

## Works where your videos are

Platform providers handle the big sites directly. Everything else goes through yt-dlp, which knows 1,619 sites.

- YouTube: YouTube provider
- Vimeo: Vimeo provider
- TikTok: with the yt-dlp provider
- X: with the yt-dlp provider
- Instagram: with the yt-dlp provider
- Twitch: with the yt-dlp provider
- Podcasts: Direct media URL provider
- Google Drive, Dropbox and OneDrive links: Direct media URL provider
- Local files: Local media file provider

## Bring any model

67 rungs across 33 services, tried in free-first order. A rung is one provider, one model and one credential. When one fails, rate-limits or is down, the chain moves to the next.

### Local (16 rungs)

Runs on your machine. Free, private, nothing leaves it.

- Embeddings: ollama `OLLAMA_EMBED_MODEL` (needs OLLAMA_EMBED_MODEL)
- Embeddings: lmstudio `LMSTUDIO_EMBED_MODEL` (needs LMSTUDIO_EMBED_MODEL)
- Embeddings: local `LOCAL_EMBED_MODEL` (needs LOCAL_EMBED_MODEL, LOCAL_EMBED_BASE_URL)
- Embeddings: transformers `Xenova/multilingual-e5-small` (needs TRANSFORMERS_EMBED_MODEL)
- LLM: ollama `OLLAMA_MODEL` (needs OLLAMA_MODEL)
- LLM: lmstudio `LMSTUDIO_MODEL` (needs LMSTUDIO_MODEL)
- LLM: llamacpp `LLAMACPP_MODEL` (needs LLAMACPP_MODEL)
- LLM: vllm `VLLM_MODEL` (needs VLLM_MODEL)
- LLM: jan `JAN_MODEL` (needs JAN_MODEL)
- LLM: localai `LOCALAI_MODEL` (needs LOCALAI_MODEL)
- LLM: local `LOCAL_LLM_MODEL` (needs LOCAL_LLM_MODEL, LOCAL_LLM_BASE_URL)
- Speech-to-text: local `LOCAL_STT_BASE_URL` (needs LOCAL_STT_BASE_URL, LOCAL_STT_MODEL)
- Speech-to-text: transformers `onnx-community/whisper-base` (needs TRANSFORMERS_STT_MODEL)
- Speech-to-text: whisper-cpp `WHISPER_CPP_MODEL` (needs WHISPER_CPP_MODEL)
- Vision: ollama `OLLAMA_VISION_MODEL` (needs OLLAMA_VISION_MODEL)
- Vision: tesseract `eng`

### Free tier (32 rungs)

Hosted free tiers that use your own key.

- Speech-to-text: cloudflare-binding `@cf/openai/whisper-large-v3-turbo` (needs CLOUDFLARE_AI_BINDING)
- Speech-to-text: cloudflare-binding `@cf/openai/whisper` (needs CLOUDFLARE_AI_BINDING)
- Speech-to-text: cloudflare `@cf/openai/whisper-large-v3-turbo` (needs CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN)
- Speech-to-text: cloudflare `@cf/openai/whisper` (needs CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN)
- LLM: cloudflare-binding `@cf/meta/llama-3.3-70b-instruct-fp8-fast` (needs CLOUDFLARE_AI_BINDING)
- LLM: cloudflare-binding `@cf/openai/gpt-oss-120b` (needs CLOUDFLARE_AI_BINDING)
- LLM: cloudflare-binding `@cf/meta/llama-4-scout-17b-16e-instruct` (needs CLOUDFLARE_AI_BINDING)
- LLM: cloudflare-binding `@cf/mistralai/mistral-small-3.1-24b-instruct` (needs CLOUDFLARE_AI_BINDING)
- Embeddings: cloudflare-binding `@cf/baai/bge-m3` (needs CLOUDFLARE_AI_BINDING)
- Embeddings: gemini `gemini-embedding-2` (needs GEMINI_API_KEY)
- Embeddings: jina `jina-embeddings-v3` (needs JINA_API_KEY)
- Embeddings: cloudflare `@cf/baai/bge-m3` (needs CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID)
- Embeddings: mistral `mistral-embed` (needs MISTRAL_API_KEY)
- LLM: nvidia `nvidia/nemotron-3-super-120b-a12b` (needs NVIDIA_API_KEY)
- LLM: sambanova `Meta-Llama-3.3-70B-Instruct` (needs SAMBANOVA_API_KEY)
- LLM: cloudflare `@cf/meta/llama-3.3-70b-instruct-fp8-fast` (needs CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN)
- LLM: zhipu `glm-4.7-flash` (needs ZHIPU_API_KEY)
- LLM: siliconflow `Qwen/Qwen3-8B` (needs SILICONFLOW_API_KEY)
- LLM: gemini-native `gemini-3.8-flash` (needs GEMINI_API_KEY)
- LLM: gemini-native `gemini-3.5-flash-lite` (needs GEMINI_API_KEY)
- LLM: groq `qwen/qwen3.8-27b` (needs GROQ_API_KEY)
- LLM: groq `openai/gpt-oss-120b` (needs GROQ_API_KEY)
- LLM: groq `openai/gpt-oss-20b` (needs GROQ_API_KEY)
- LLM: cerebras `gpt-oss-120b` (needs CEREBRAS_API_KEY)
- LLM: cerebras `llama-3.3-70b` (needs CEREBRAS_API_KEY)
- LLM: mistral `mistral-small-latest` (needs MISTRAL_API_KEY)
- LLM: github `meta/Llama-3.3-70B-Instruct` (needs GITHUB_TOKEN)
- LLM: gemini `gemini-2.5-flash-lite` (needs GEMINI_API_KEY)
- LLM: openrouter `free-auto` (needs OPENROUTER_API_KEY)
- Speech-to-text: groq `whisper-large-v3-turbo` (needs GROQ_API_KEY)
- Speech-to-text: mistral `voxtral-mini-transcribe-3` (needs MISTRAL_API_KEY)
- Vision: gemini `gemini-2.5-flash-lite` (needs GEMINI_API_KEY)

### Keyless (10 rungs)

Hosted and free with no account at all.

- Embeddings: ovh `bge-m3`
- Embeddings: ovh `Qwen3-Embedding-8B`
- LLM: kilo `nvidia/nemotron-3-ultra-550b-a55b:free`
- LLM: kilo `nvidia/nemotron-3.5-super-vl:free`
- LLM: kilo `nvidia/nemotron-3.5-lightning:free`
- LLM: ovh `Meta-Llama-3_3-70B-Instruct`
- LLM: ovh `gpt-oss-120b`
- LLM: pollinations `openai-fast`
- Speech-to-text: ovh `whisper-large-v3-turbo`
- Vision: ovh `Qwen2.5-VL-72B-Instruct`

### Paid (9 rungs)

Last backstop, used only when you set its key.

- Embeddings: openai `text-embedding-3-small` (needs OPENAI_API_KEY)
- LLM: anthropic `claude-haiku-5-5` (needs ANTHROPIC_API_KEY)
- LLM: anthropic `claude-sonnet-5-5` (needs ANTHROPIC_API_KEY)
- LLM: vertex-gemini `gemini-3.8-flash` (needs GOOGLE_CLOUD_PROJECT, GOOGLE_ACCESS_TOKEN)
- LLM: vertex-anthropic `claude-haiku-5-5` (needs GOOGLE_CLOUD_PROJECT, GOOGLE_ACCESS_TOKEN)
- LLM: openai `gpt-5.4-nano` (needs OPENAI_API_KEY)
- Speech-to-text: deepinfra `openai/whisper-large-v3-turbo` (needs DEEPINFRA_API_KEY)
- Speech-to-text: together `openai/whisper-large-v3` (needs TOGETHER_API_KEY)
- Speech-to-text: openai `whisper-1` (needs OPENAI_API_KEY)

Details: https://vid2context.com/docs/providers.md

## Agents and MCP

Add the MCP server and ask about any video. No key needed. Until the npm package is published, run it from a clone: `git clone https://github.com/nirholas/vid2context.git && cd vid2context && npm install`.

### Claude Code

One command, user scope, every project. Guide: https://vid2context.com/docs/clients/claude-code.md

```sh
claude mcp add vid2context -- "$PWD/node_modules/.bin/tsx" "$PWD/packages/mcp/src/bin.ts"
```

### Claude Desktop

Add one block to claude_desktop_config.json. Guide: https://vid2context.com/docs/clients/claude-desktop.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### Cursor

One-click install, or ~/.cursor/mcp.json. Guide: https://vid2context.com/docs/clients/cursor.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### VS Code

One-click install for GitHub Copilot agent mode. Guide: https://vid2context.com/docs/clients/vscode.md

```sh
code --add-mcp "{\"name\":\"vid2context\",\"command\":\"$PWD/node_modules/.bin/tsx\",\"args\":[\"$PWD/packages/mcp/src/bin.ts\"]}"
```

### Codex

codex mcp add, stored in ~/.codex/config.toml. Guide: https://vid2context.com/docs/clients/codex.md

```sh
codex mcp add vid2context -- "$PWD/node_modules/.bin/tsx" "$PWD/packages/mcp/src/bin.ts"
```

### Gemini CLI

Install as an extension straight from GitHub. Guide: https://vid2context.com/docs/clients/gemini-cli.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### Windsurf

Add one block to mcp_config.json. Guide: https://vid2context.com/docs/clients/windsurf.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### Cline

Add one block to cline_mcp_settings.json. Guide: https://vid2context.com/docs/clients/cline.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### LM Studio

One-click deeplink, or mcp.json. Guide: https://vid2context.com/docs/clients/lm-studio.md

```sh
printf '{"mcpServers":{"vid2context":{"command":"%s/node_modules/.bin/tsx","args":["%s/packages/mcp/src/bin.ts"]}}}\n' "$PWD" "$PWD"
```

### Goose

One-click deeplink, or goose configure. Guide: https://vid2context.com/docs/clients/goose.md

```sh
echo "$PWD/node_modules/.bin/tsx" "$PWD/packages/mcp/src/bin.ts"
```

### ChatGPT

Upload a context pack to a Project or custom GPT. ChatGPT connects only to remote MCP servers over HTTPS.

```sh
npm run cli -- "https://www.youtube.com/watch?v=jNQXAC9IVRw" --format pack > context.md
```

Tools (28):

- `add_to_collection`: Ingest videos into a collection now: each URL is a video or a list (playlist, channel, feed), and lists are expanded.
- `ask`: Answer a question from the transcripts of one or more videos, or a saved collection, with server-side retrieval and the free-first LLM chain.
- `build_brief`: Build a cited brief across videos on the server with a free LLM (map-reduce for large collections).
- `choose_caption_track`: List a video's caption tracks (languages, creator or auto-generated) and ask the user to pick one, then return that transcript with [m:ss] timestamps.
- `create_collection`: Create a research collection.
- `digest_videos`: Build one cited digest of several videos (a playlist, a collection, or a list of URLs) using MCP sampling: the server asks the client's model to take notes on each part of each transcript, then combine them.
- `export_context_pack`: One Markdown document for many videos (the pack format): a header per video with title, channel, URL and chapters, then each transcript in timestamped paragraphs.
- `export_notion`: Create one Notion page per video under a parent page (chapters as headings, paragraphs with timestamp links, a bookmark to the video).
- `export_obsidian`: Write one Markdown note per video into a folder of an Obsidian vault on this machine: frontmatter properties, chapters as headings, paragraphs prefixed with [m:ss] timestamp links, plus an index note with [[wikilinks]] when a collection is exported.
- `extract`: Extract structured JSON from videos with a template (buyer-guide, tutorial-steps, comparison, summary, brief) or your own JSON Schema.
- `find_duplicates`: Compare the transcripts of several videos and group reuploads (the same video uploaded again) and clips (an excerpt of a longer video, with the [m:ss] where it starts in the original and the range it covers).
- `get_collection`: A collection with a summary of each video (id, title, channel, duration, URL, transcript origin), the sources it follows, inputs waiting for the next refresh and its watch list.
- `get_comments`: Top comments of a video, with creator replies and pinned comments flagged.
- `get_key_moments`: The moments of a video worth jumping to, picked by the free-first LLM chain from the timestamped transcript.
- `get_metadata`: Title, channel, description, duration, publish date, chapters, tags and language for a video URL or local file, without fetching the transcript.
- `get_outline`: Start here for any video longer than about 20 minutes.
- `get_section`: One chapter or time range of a video's transcript, with the same header as get_transcript.
- `get_skip_segments`: Community-marked SponsorBlock segments of a YouTube video: sponsor reads, self-promotion, subscribe reminders, intros, outros, previews and filler, each with its [m:ss] range, a timestamp URL and how much of the transcript it covers (lines, word share and the first words).
- `get_transcript`: The full transcript of one video or local media file, with a header (title, channel, URL, duration, how the transcript was made, chapters).
- `list_caption_languages`: List the caption tracks a video has (language, name, creator or auto-generated) and, for YouTube, the languages YouTube can machine-translate them into.
- `list_collections`: List research collections with how many videos and sources each has.
- `list_formats`: The output formats get_transcript and get_section accept (text, json, markdown, srt, vtt, pack, ...), with what each is for.
- `list_items`: Expand a playlist, channel, podcast feed or page into its videos (a single video URL returns itself).
- `list_models`: The models (rungs) this server can use for speech-to-text, LLM, embedding, video and visual work, in free-first order: tier (local, free, keyless, paid), quality 1 to 5, capabilities (json, tools, vision, stream, ...), context window, whether it is enabled, and the names of the env vars that would enable it.
- `open_transcript_viewer`: Show a video transcript in an interactive viewer (chapters, search, clickable [m:ss] timestamps, one-click citations, send selected lines to the chat) in clients that support MCP Apps, such as ChatGPT and Claude.
- `research_videos`: Search 1 to 10 videos (or a playlist, capped at 10) for a question and get only the relevant excerpts: ranked by BM25, each with the surrounding context, [m:ss] and a timestamp link, under a token cap.
- `search_transcript`: Find where something is said across saved video transcripts, instead of reading whole transcripts (about 12k tokens per hour).
- `watch_live`: Transcribe a live stream (a live YouTube video or an HLS .m3u8 URL) while it runs.

## Use cases

### Research a buying decision across a playlist

A buyer’s series on the Mercedes G-Wagon runs for hours. Load the episodes into your agent and ask which model, year and mileage to buy. Every transcript line carries its timestamp, so each claim in the answer can cite the episode and the moment that said it.

The first lines of "Best & Worst G-Wagon Years: Reliability, Interiors & Engines Ranked!" (18:04, 521 caption lines), as the agent receives them

```text
Title: Best & Worst G-Wagon Years: Reliability, Interiors & Engines Ranked!
Channel: Alliance Motorworks
URL: https://www.youtube.com/watch?v=cCPsdFdlshc
Duration: 18:04
Transcript: auto-captions, en (youtube-captions)

[0:00] so you're going to buy G wagon which
[0:02] year is best for you well in this video
[0:03] we're going to do a year-by-year
[0:04] breakdown of the legendary
[0:08] w463 platform so you can check out the
[0:10] model year ranges the engine options and
[0:13] the interior because if you buy the
[0:16] wrong one I don't want you getting
[0:18] buyers remorse or ending up with a bad
[0:21] specimen my name is Adam welcome to the
[0:23] U uh gwh and YouTube channel I do
[0:25] everything here for the love of G I'm
```

### Learn from tutorials

Chapters become sections. For a long course video, your agent reads the outline first and pulls only the section it needs, instead of the whole transcript.

### Notes from podcasts

Podcast episodes have no captions, so the audio goes through speech-to-text. You get Markdown notes with a timestamp on every paragraph, ready for Obsidian, Notion or your agent.

## Self-host

- **Docker:** Compose file for the full server (HTTP API, yt-dlp, ffmpeg), plus a small stdio MCP image at the repo root. `docker compose -f deploy/containers/compose.yaml up -d --build` Guide: https://vid2context.com/docs/deploy/docker.md

- **Cloudflare:** One Worker serves the site, the apps and the API, with Workers AI as an optional free rung. `npm run deploy` Guide: https://vid2context.com/docs/deploy/cloudflare.md

- **Vercel:** A prebuilt Build Output tree: the same layout with the API as a function. `npm run build:vercel` Guide: https://vid2context.com/docs/deploy/vercel.md

- **Railway:** Deploy the server container on Railway. Guide: https://vid2context.com/docs/deploy/railway.md

- **GitHub Pages:** A client-only build: the apps run in the browser with your own keys or local models. `npm run deploy:pages` Guide: https://vid2context.com/docs/deploy/github-pages.md

## FAQ

### What does it cost?

Nothing. vid2context is free and open source under the Apache-2.0 license. With no keys it uses captions and keyless hosts. Paid services run only when you set their key, and VID2CONTEXT_ALLOW_PAID=0 turns them off entirely.

### Do I need an API key?

No. Captions need no key, and speech-to-text falls back to keyless Whisper hosts. Free keys (Groq, Gemini, Mistral and others) unlock 32 more free-tier rungs that are faster and have higher limits.

### Where does my data go?

When you run vid2context yourself, captions are fetched straight from the platform and your files stay on your machine unless a hosted rung transcribes them. Keyless rungs send audio to third-party hosts without an account. Set VID2CONTEXT_POLICY=local-only to keep everything on your machine, or VID2CONTEXT_KEYLESS=0 to skip keyless hosts.

### Which sites work?

YouTube, Vimeo, TikTok, X, Instagram, Twitch, Podcasts, Google Drive, Dropbox and OneDrive links, Local files. Anything else that yt-dlp supports (1,619 sites) works through the yt-dlp provider.

### Why does a YouTube video fail on the hosted demo?

YouTube often blocks requests from cloud servers, so the demo on this site can fail for videos that work fine on your own machine. Run the CLI or the MCP server locally, where requests come from your own connection.

### Which agents does it work with?

Any MCP client: Claude Code, Claude Desktop, Cursor, VS Code, Codex, Gemini CLI, Windsurf, Cline, LM Studio and Goose. ChatGPT gets a context pack file you upload to a Project.

## Links

- Docs: https://vid2context.com/docs.md
- Source: https://github.com/nirholas/vid2context
- llms.txt: https://vid2context.com/llms.txt
- License: Apache-2.0
