Run locally, in Docker or across workers with a serializable transcode plan.
Your own machine or server
The library and CLI run on the current machine. The autoencoder tests supported hardware encoders and falls back to libx264. A worker can run in a VM or Docker; short-lived serverless functions need ffmpeg and enough execution time.
await transcode({ input: "film.mp4", output: "out/film", encoder: "auto" });One worker per rendition
The plan is plain JSON. Send it through a queue and have each worker encode one named rendition, then collect results and finish. Use shared storage and an input key; local input paths must exist on every machine.
import { planTranscode, encodeRendition, finishTranscode } from "seamtranscode";
const plan = await planTranscode({ storage, input: { key: "uploads/film.mp4" }, output: "videos/film" });
const results = await Promise.all(plan.renditions.map((r) => encodeRendition(plan, r.name, { storage })));
const result = await finishTranscode(plan, results, { storage });Modal recipe
recipes/modal/app.py builds the local Node package into an image. Configure the seamtranscode-storage secret with S3/R2 credentials, then run one container per rendition with previews in parallel. No Python encoding fork or published npm release is required. The recipe is not deployed by repository checks.
modal run recipes/modal/app.py --key uploads/film.mp4 --output videos/filmDocker worker
The image includes ffmpeg, sharp and the S3 SDK. Its HTTP worker uses environment variables and never serves media files directly. A local output mount must be writable by the node user.
docker build -t seamtranscode packages/seamtranscode
docker run --rm -p 8100:8100 -e SEAMTRANSCODE_SECRET=your-secret -e SEAMTRANSCODE_ROOT=/media -v "$PWD/media:/media" seamtranscode