# oembed-graphics Docker-hosted oEmbed graphics for broadcast workflows. It is inspired by [webrecorder/oembed.link](https://github.com/webrecorder/oembed.link), but runs as a normal container and exposes graphic URLs that can be loaded by CasparCG, OBS Browser Source, OGraf, or any HTML-capable character generator. ## Run locally ```sh npm install npm start ``` Open `http://localhost:3000`. ## Run with Docker ```sh docker compose up --build ``` The service listens on `http://localhost:3000`. ## Broadcast URL Use `/graphic` with a source URL: ```txt http://localhost:3000/graphic?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ&width=1920&height=1080&transparent=1 ``` Useful query parameters: - `url`: required source URL to resolve through oEmbed. - `width`: stage width, default `1920`. - `height`: stage height, default `1080`. - `transparent`: `1` for transparent output, default `1`. - `chroma`: background color when transparent output is disabled, default `#00ff00`. - `fit`: `contain` or `cover`, default `contain`. - `scale`: graphic scale multiplier, default `1`. - `wait`: `1` to keep the graphic hidden until embed media loads, default `1`. - `readyDelay`: extra milliseconds to wait after media load before reveal, default `1000`. - `maxWait`: safety timeout before reveal, default `10000`. - `autoplay`: `1` to request autoplay for iframe and video embeds, default `1`. - `muted`: `1` to mute embeds, default `1`. Most browsers require this for autoplay. - `maxwidth`: sent to the oEmbed provider and capped at `500`, default `500`. - `maxheight`: sent to the oEmbed provider, default `480`. Autoplay is best-effort for social embeds. The graphic page keeps the original social post HTML, adds provider autoplay parameters where possible, and runs a small assist script that calls `play()` on any video element it can access. Browsers still block scripts from controlling video inside cross-origin iframes, which includes Twitter/X widget frames. For broadcast runtimes based on Chromium or CEF, also allow autoplay at the browser layer when possible, for example with `--autoplay-policy=no-user-gesture-required`. The renderer caps every social card at `500px` wide so different providers line up more consistently on a broadcast canvas. It still uses the oEmbed response's height when present. The service also supports the oembed.link-style form: ```txt http://localhost:3000/https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ ``` ## CasparCG template Load `/caspar` as the browser template URL. It starts transparent and blank, then renders when CasparCG sends `UPDATE` data. Example template URL: ```txt http://localhost:3000/caspar ``` Example JSON update payload: ```json { "url": "https://bsky.app/profile/bsky.app/post/3k...", "width": 1920, "height": 1080, "scale": 1, "transparent": true } ``` The template also accepts a raw URL string or standard CasparCG XML `templateData` with component ids such as `url`, `scale`, `fit`, `autoplay`, `muted`, `readyDelay`, and `maxWait`. ## Collage Use `/collage` to render multiple social posts as independently scrolling columns. The browser keeps only a small window of live posts per column, removes cards after they scroll off the top, and fills new random cards at the bottom. Repeated `url` parameters: ```txt http://localhost:3000/collage?url=https%3A%2F%2Fbsky.app%2F...&url=https%3A%2F%2Fx.com%2F... ``` Or a JSON array: ```txt http://localhost:3000/collage?urls=%5B%22https%3A%2F%2Fbsky.app%2F...%22%2C%22https%3A%2F%2Fx.com%2F...%22%5D ``` Useful collage parameters: - `spacing`: pixels between a post and anything else, including screen edges and other posts, default `48`. - `fade`: optional pixels used to fade posts in/out at the top and bottom edges, default `0`. - `columns`: number of post columns, default `3`. - `repeatDistance`: minimum pixel distance before the same post can be reused near another live copy, default `900`. - `hydrateDelay`: milliseconds between hydrating newly inserted provider embeds, default `180`. - `duration`: seconds per scroll loop, default `360`. - `repeat`: virtual scroll buffer multiplier, default `2`. - `shuffle`: `1` to randomize post order on each page load, default `1`. Collage card width is calculated from `width`, `spacing`, and `columns` so the columns fill the configured screen width with only the chosen spacing at the edges. ## API - `GET /api/oembed?url=...` returns the matched provider and raw oEmbed data. - `GET /caspar` returns the CasparCG update-driven HTML template. - `GET /collage?url=...&url=...` returns a scrolling social post collage. - `GET /providers` returns the loaded provider patterns. - `GET /healthz` returns a health check response. Provider data is loaded from `https://oembed.com/providers.json` and cached in memory. Override with `PROVIDERS_URL`, `PROVIDERS_TTL_MS`, and `OEMBED_TIMEOUT_MS` environment variables.