Back to blog

Building an HLS video pipeline with FFmpeg and BullMQ

TutorialNov 28, 2024· 12 min read

Introduction

When building a video platform, one of the first challenges is converting uploaded video files into adaptive bitrate HLS streams. This tutorial walks through building a production-ready encoding pipeline using FFmpeg and BullMQ.

Architecture overview

The pipeline consists of three main components:

1. Upload handler — accepts video files and stores them temporarily

2. Job queue — BullMQ manages encoding jobs with retry logic

3. Encoding worker — FFmpeg processes videos into multi-quality HLS

Upload → Queue Job → FFmpeg Worker → HLS Output → CDN

Setting up the queue

BullMQ provides a robust job queue built on Redis. It handles retries, concurrency, and job prioritization out of the box.

import { Queue, Worker } from 'bullmq';

const encodingQueue = new Queue('video-encoding', {

connection: { host: 'localhost', port: 6379 },

defaultJobOptions: {

attempts: 3,

backoff: { type: 'exponential', delay: 5000 },

},

});

FFmpeg encoding profiles

We encode each video into three quality levels for adaptive streaming. Each profile targets a specific bandwidth range.

const profiles = [

{ name: '360p', width: 640, height: 360, bitrate: '800k' },

{ name: '720p', width: 1280, height: 720, bitrate: '2500k' },

{ name: '1080p', width: 1920, height: 1080, bitrate: '5000k' },

];

The encoding worker

The worker picks up jobs from the queue and runs FFmpeg to produce HLS segments. Each quality level gets its own playlist, and a master playlist references all of them.

This approach ensures that players can switch between quality levels seamlessly based on the viewer's bandwidth — which is the whole point of adaptive bitrate streaming.

Error handling and retries

Video encoding can fail for many reasons: corrupt input files, out-of-memory errors, or FFmpeg crashes. BullMQ's retry mechanism handles transient failures automatically, while permanent failures are logged and flagged for review.

Conclusion

Building a reliable encoding pipeline is one of the most critical parts of any video platform. With FFmpeg for encoding and BullMQ for job management, you get a production-ready system that handles failures gracefully and scales horizontally.