4.6 KiB
oembed-graphics
Docker-hosted oEmbed graphics for broadcast workflows. It is inspired by 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
npm install
npm start
Open http://localhost:3000.
Run with Docker
docker compose up --build
The service listens on http://localhost:3000.
Broadcast URL
Use /graphic with a source URL:
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, default1920.height: stage height, default1080.transparent:1for transparent output, default1.chroma: background color when transparent output is disabled, default#00ff00.fit:containorcover, defaultcontain.scale: graphic scale multiplier, default1.wait:1to keep the graphic hidden until embed media loads, default1.readyDelay: extra milliseconds to wait after media load before reveal, default1000.maxWait: safety timeout before reveal, default10000.autoplay:1to request autoplay for iframe and video embeds, default1.muted:1to mute embeds, default1. Most browsers require this for autoplay.maxwidth: sent to the oEmbed provider and capped at500, default500.maxheight: sent to the oEmbed provider, default480.
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:
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:
http://localhost:3000/caspar
Example JSON update payload:
{
"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 a vertically scrolling strip.
Posts are repeated in the track so the motion keeps filling gaps.
Repeated url parameters:
http://localhost:3000/collage?url=https%3A%2F%2Fbsky.app%2F...&url=https%3A%2F%2Fx.com%2F...
Or a JSON array:
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, default48.fade: optional pixels used to fade posts in/out at the top and bottom edges, default0.columns: number of post columns, default3.duration: seconds per scroll loop, default360.repeat: number of times to repeat the post list in each half of the loop, default4.shuffle:1to randomize post order on each page load, default1.
Collage card width is calculated from width, spacing, and columns,
then capped at 500px, so all columns fit within the configured screen width.
API
GET /api/oembed?url=...returns the matched provider and raw oEmbed data.GET /casparreturns the CasparCG update-driven HTML template.GET /collage?url=...&url=...returns a scrolling social post collage.GET /providersreturns the loaded provider patterns.GET /healthzreturns 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.