ProjectsEncoding

FFmpeg encoding on Cloudflare Containers

Your own ladder and packaging, started by an upload, served from R2

Example design

  1. 01Object createdA mezzanine file lands in the uploads bucket. An R2 event notification, filtered by prefix and suffix, puts a message on a queue.
  2. 02Job picked upA Worker consumes the message and works out the ladder for this title.
  3. 03Start encodeThe Worker starts a container through a Durable Object, one per job, and passes it the source location and the ladder.
  4. 04Read sourceFFmpeg reads the source from R2 and encodes each rung.
  5. 05Write renditionsCMAF segments are written back to R2 with HLS and DASH manifests that share them.
  6. 06ReportThe container reports the result, including a VMAF score for each rung, and stops.
  7. 07PublishThe Worker marks the title ready. Players fetch segments from R2 through a custom domain, cached at the edge.
  8. ifAn encode failsThe Worker does not acknowledge the message, so the queue retries the job. After the last retry it goes to a dead letter queue and someone is alerted with the FFmpeg log.

The problem

Managed encoding gives you its own ladder, codecs and packaging. Some catalogues need more control: a ladder per title, AV1 next to H.264, a CMAF layout an existing player expects, or slates burned in at the start. Running FFmpeg yourself used to mean a fleet of encode servers sized for the busiest day. Here the encode runs in a container that starts when a file arrives and stops when the job is done.

What it uses

R2
Source files, renditions and manifests
Queues
Upload events, retries and a dead letter queue
Workers and Durable Objects
Job control, one object per encode
Containers
FFmpeg, in an image you build and version

The decisions, and why

Instance typestandard-4: 4 vCPU, 12 GiB
Encoding is CPU bound and this is the largest type available. Long titles are split into chunks and encoded in parallel containers.
TriggerR2 event notification to a queue
The queue retries failed jobs, and its consumer concurrency stops a burst of uploads from starting more encodes than you want to pay for at once.
OutputCMAF, with HLS and DASH manifests
One set of segments serves both manifest types, so storage is not doubled.
LadderPer title, from measured quality
Each title gets the rungs its content needs. Stream Ladder covers how the ladder is built.
DeliveryFrom R2
R2 does not charge for egress, which matters more for video than for most content.

Limits to plan around

  • The largest container has 4 vCPU and 12 GiB of memory, so long or high-resolution sources have to be split into chunks.
  • Local disk is 20 GB on the largest instance, so sources are read from R2 in pieces and not copied whole.
  • Containers run on the Workers Paid plan.

What you get

  • FFmpeg container image with a pinned build
  • Worker, queue and Durable Object job control
  • Ladder definitions and the chunking logic
  • VMAF reporting for every rung
  • Dead letter handling and alerts
  • Runbook for codec and preset changes

Related product

Stream Ladder: per-title encoding ladder design and validation.

Read about Stream Ladder

Talk about your video project

Tell us what you are building, or what is not working in the platform you have.

Registered office
VI Data Services Ltd
128 City Road, London, EC1V 2NX, United Kingdom
Telephone

020 8058 7616

Company number

17420568
Registered in England and Wales