142 lines
4.9 KiB
Markdown
142 lines
4.9 KiB
Markdown
# 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 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
|
|
|
|
```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.
|