---
name: og-video
description: "Add animated og:video link previews to any page with og.video: pick a scenario (kinetic type, title card, architecture diagram, metric, bar chart, release notes), build the .mp4/.png/share-page URLs from params, paste the og meta tags, shorten long params with ?s= packing or POST short ids, or call the og.video MCP server. Use when a user wants a video link preview, an og:video or og:image card, or an animated social card for a link."
license: MIT
compatibility: "Needs HTTP access to https://og.video. The MCP server (https://og.video/mcp) is optional."
metadata:
  homepage: "https://og.video"
  mcp: "https://og.video/mcp"
  library: "https://github.com/runtypelabs/og-video"
---

# og.video

https://og.video turns URL params into a 7-second animated link preview: an MP4 for `og:video` (1200x630, 30 fps), a PNG poster for `og:image`, and a share page that carries both tags. There is no account or API key. The first request for a set of params renders it at the edge, and every later request is served from cache.

Use this skill to put an animated preview on a link. To write a new kind of video (a custom scenario) or self-host the Worker, use the library's own skill instead: https://github.com/runtypelabs/og-video/tree/main/skills/streaming-og-video.

## 1. Pick a scenario

| Scenario | What it is | Use for |
|---|---|---|
| `kinetic` | Kinetic typography: a headline rises word by word; *starred words* land in the accent colour with a highlight block. | One bold statement, quote or tagline: a manifesto line, a pull quote, a hot take, an opinion post. |
| `title-card` | An announcement card: a grid reveal, a pixel wordmark that flips into the header, a typed kicker, then the title words blur in. | Launches, blog posts, announcements, events: anything with a title and a brand. |
| `falling-words` | Dozens of words rain down, tumble and pile up with real physics around a labelled pill; then the floor drops and the loop starts again. | A big vocabulary in one image: a design system's components, a product's features, integrations, a list of skills or topics. |
| `dot-matrix` | A split card: a headline on the left, and on the right icons that form out of a dot grid, hold with a pixel-font label, then dissolve into the next. | A product with a handful of capabilities: an API, a platform, a developer tool. |
| `gallery` | A title block beside a two-column wall of thumbnails that scrolls without end. | Portfolios, showcases, galleries, playgrounds, template or theme collections. |
| `diagram` | An architecture card: a side panel with the brand, title and counting stats; lanes of nodes unfold, edges draw and packets travel between them. | How a system, pipeline, integration or agent is wired: inputs -> processing -> outputs. |
| `metric` | A big number rolls up like an odometer over a trend line that draws itself, with a delta pill. | One headline number: revenue, users, uptime, latency, downloads, a milestone. |
| `bars` | A bar chart grows in a staggered wave, values count up on the bar tops, the highlighted bar lands in the accent, and an average line sweeps across. | Comparing 2-12 categories or periods: by region, by month, by plan, benchmark results. |
| `release` | Release notes: a huge version number rises behind the title, and each item slides in with an icon. | Changelogs, version releases, weekly updates, "what's new" posts. |

Every param has a default, but the defaults are og.video's own demo copy, so always set the text fields. The full param reference with types, limits and defaults is in [references/params.md](references/params.md). It is generated from the scenario schemas, as is `GET https://og.video/v1/<scenario>.json`, which returns the resolved params for any URL.

## 2. Build the URLs

All three URLs take the same query string:

| URL | Returns |
|---|---|
| `https://og.video/v1/<scenario>.mp4?<params>` | the video, for `og:video` |
| `https://og.video/v1/<scenario>.png?<params>` | the poster frame, for `og:image` |
| `https://og.video/v1/<scenario>?<params>` | a share page with the og tags and a player |
| `https://og.video/v1/<scenario>.json?<params>` | the resolved params, the content id and a packed URL |

- Scalars go in the query string as they are: `?title=We%20shipped%20it&brand=ACME&accent=%23f97316`. URL-encode them, including `#` in colours as `%23` (or drop the `#`).
- Arrays and objects go in as JSON: `?data=[3,5,8]&labels=["Q1","Q2","Q3"]`.
- Only pass params you want to change from the defaults.
- Unknown params (utm_source and the like) are ignored and do not change the cache key.
- An invalid param returns HTTP 400 with `{"error": "<path>: <reason>"}`, e.g. `title: at most 140 characters`.

Examples:

```
https://og.video/v1/kinetic.mp4?text=Ship%20*faster*%20with%20less&by=acme.dev
https://og.video/v1/title-card?title=Acme%20Pages%20is%20live&kicker=Launch&badge=Beta&brand=ACME
https://og.video/v1/metric.png?label=Monthly%20active%20users&value=1.2&decimals=1&suffix=M&delta=%2B18%25
https://og.video/v1/diagram?title=How%20support%20works&graph=Inputs:%20Email@mail,%20Slack@chat%20%7C%20Agents:%20Triage@bot
```

Copy that fits the 1200x630 canvas:
- kinetic: 3-10 words. Wrap the 1-3 key words in `*asterisks*` to emphasise them.
- title-card: a title of 3-9 words. `brand` is a 3-10 character wordmark using letters, digits, space and `. ! + / -`.
- diagram: a title under ~45 characters, 2-3 lanes of 1-4 short nodes, using the `graph` shorthand `"Lane: Node@icon, Node@icon | Lane: Node@icon"`.
- metric, bars and release take `theme=light`; title-card and diagram are dark only.
- Accents need contrast. On dark, use the 400-500 shades. On light, use the 600-700 shades.

## 3. Add the preview to a page

The simplest way is to share the share-page URL itself (`https://og.video/v1/<scenario>?…`). It already has the tags.

To preview your own page, put these in its `<head>`, using the same params in all three URLs:

```html
<meta property="og:type" content="video.other">
<meta property="og:title" content="Your title">
<meta property="og:image" content="https://og.video/v1/title-card.png?title=…">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:video" content="https://og.video/v1/title-card.mp4?title=…">
<meta property="og:video:secure_url" content="https://og.video/v1/title-card.mp4?title=…">
<meta property="og:video:type" content="video/mp4">
<meta property="og:video:width" content="1200">
<meta property="og:video:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://og.video/v1/title-card.png?title=…">
```

The MCP tools below return the complete tag block for any params. Apps that support og:video play the video. Apps that don't show the og:image poster.

Escape `&` as `&amp;` inside HTML attributes.

## 4. Shorten long params

- **Packed `?s=`:** the canonical JSON of the params, deflated and base64url-encoded, is about 3x shorter than JSON in the query string. `GET https://og.video/v1/<scenario>.json?<params>` returns it as `packed`. `s=` and plain params can be mixed: plain keys override packed ones.
- **Short ids:** `POST https://og.video/v1/<scenario>` with the params as a JSON body (64 KB at most) stores them. The response is `{"id", "cid", "video", "image", "page"}`, with URLs like `https://og.video/v1/<scenario>/<id>.mp4`. The id is the content hash, so the same params always give the same id, and the URLs never change. Add `?warm` to render the video before the first viewer arrives. Public POSTs are rate limited per IP.

```sh
curl -s -X POST 'https://og.video/v1/bars?warm' -H 'content-type: application/json' \
  -d '{"title":"Signups by month","data":[120,180,260],"labels":["Jan","Feb","Mar"],"highlight":"last"}'
```

## 5. Use the MCP server

`https://og.video/mcp` is a stateless Streamable HTTP MCP server with no auth. Add it to a client as a remote server with that URL. It allows 60 requests per minute per IP; over that it answers HTTP 429 with a JSON-RPC error and a `retry-after` header. Tools:

- **`og_video_url`** takes `{scenario, params, short?}`. It validates the params exactly as the HTTP routes do and returns the video, poster and share-page URLs, a packed variant when it is shorter, and the og tags. With `short: true` it also stores the params and returns short id URLs. It is deterministic and uses no AI. Invalid params come back as a tool error naming the path and the reason.
- **`og_video_from_prompt`** takes `{prompt, brand?, accent?, scenario?, short?}`. A Workers AI model picks the scenario and writes the copy, and the result is validated the same way as `og_video_url` and returned with a one-line rationale. Give it the facts: it is told not to invent numbers or claims. It is limited to 2 calls per minute per IP (over that, the tool returns an error saying when to retry), and prompts are capped at 2,000 characters.

Use `og_video_url` when you already know what the card should say: the result is exact. Use `og_video_from_prompt` for a quick first design, then refine it with `og_video_url`.

## Checking the result

- Fetch the `.png` and look at it. It is the frame link previews show before the video plays.
- `curl -sI '<video url>'` should return `200` with `content-type: video/mp4`. On a first render, `x-sogv-cache` is `miss`. After that it is `edge` or `r2`.
- Previews are cached by the platforms too. To see a change, change a param, or ask the platform to re-scrape.
