Files
oembed-graphics/README.md
Aiden Wilson 959f6590c3
Some checks failed
Build & Push Docker (latest) / build (push) Has been cancelled
Build & Push Docker (latest) / verify (push) Has been cancelled
conversion to type script
2026-05-29 23:55:31 +10:00

4.9 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 run build
npm start

Open http://localhost:3000.

For development, use npm run dev to run the TypeScript server in watch mode.

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, 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:

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 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:

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, 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.