Aiden Wilson bba1ab5cee
All checks were successful
Build & Push Docker (latest) / verify (push) Successful in 9m29s
Build & Push Docker (latest) / build (push) Successful in 8s
Caspar Template
2026-05-29 22:51:32 +10:00
2026-05-29 22:24:09 +10:00
2026-05-29 22:51:32 +10:00
2026-05-29 22:51:32 +10:00
2026-05-29 22:51:32 +10:00
2026-05-29 22:24:09 +10:00
2026-05-29 12:11:17 +00:00
2026-05-29 22:24:09 +10:00
2026-05-29 22:24:09 +10:00
2026-05-29 12:11:17 +00:00
2026-05-29 22:24:09 +10:00
2026-05-29 22:51:32 +10:00
2026-05-29 22:51:32 +10:00

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

API

  • GET /api/oembed?url=... returns the matched provider and raw oEmbed data.
  • GET /caspar returns the CasparCG update-driven HTML template.
  • 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.

Description
Embed social media posts using Oembed in a format that's callable from Caspar/OGraf
Readme AGPL-3.0 134 KiB
Languages
TypeScript 74.6%
JavaScript 17%
CSS 8%
Dockerfile 0.4%