Building a Video Transcoding Pipeline with FFmpeg and BullMQ
Presigned uploads, queue-isolated FFmpeg workers and HLS ladders — without putting video bytes or FFmpeg on the API path.
By Rahul Gupta · RahulX Labs
Do not put FFmpeg on the request path
Most upload demos stream video through the API and call FFmpeg inline. Concurrent uploads pin the CPU the HTTP server needs. Production systems separate ingest from transcoding.
StreamHub issues a presigned MinIO/S3 URL so the client PUTs directly to object storage. The API only records intent and enqueues work.
Queue-isolated transcoder
A BullMQ consumer builds an HLS rendition ladder (up to 1080p) plus thumbnail with exponential backoff. The transcoder does not call the API — communication is queues and object storage.
Completion and failure events flow back on a second queue so status updates in Postgres retry independently of the HTTP path.
Playback without exposing the bucket
The API proxies master.m3u8 and segments after ownership checks. Raw bucket URLs never reach the browser, and cascading deletes remove raw files plus all renditions.