Aiden Wilson 4b488913e4 collage
2026-05-29 23:19:20 +10:00
2026-05-29 22:24:09 +10:00
2026-05-29 23:19:20 +10:00
2026-05-29 23:19:20 +10:00
2026-05-29 23:19:20 +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 23:19:20 +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.

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, 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.
  • duration: seconds per scroll loop, default 360.
  • repeat: number of times to repeat the post list in each half of the loop, default 4.
  • shuffle: 1 to randomize post order on each page load, default 1.

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

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%