arm
  • Home
  • Work
  • About
  • Writing
  • Resume
  • Contact
Open to work
❡Case study · Deep dive · 8 min read

PIPE — an FFmpeg-powered HLS pipeline for a working video creator.

Upload once, get back an Instagram Reel, a YouTube Short, HLS segments, a blur-shot thumbnail, and a cover — all queued, all on R2.

clientshippedclient workvideoshipped
One upload, every format
PIPE is a transcoding pipeline built for a client who shoots and edits video professionally. The problem was simple and painful: every platform wants a different format, aspect ratio, and codec. PIPE takes a single source upload and fans out — Instagram Reels, YouTube Shorts, HLS adaptive streaming, a blurred-background thumbnail, and a cover image — all without the creator touching FFmpeg.
4+
Output formats
0
FFmpeg commands typed by client
1
Real client
R2
Storage
Upload → processing → output grid

§01The problem

A professional video creator publishing across Instagram and YouTube re-exports the same footage multiple times — different resolutions, aspect ratios, and codec settings per platform. That is twenty minutes of manual FFmpeg or Premiere work per video, before any editing happens. For someone who publishes daily, it compounds into hours a week.

The real requirement was not a transcoder — it was disappearing the decision. Upload a source, get back every derivative you need, stored and ready, with no flags to remember and no export queue to babysit.

§02The pipeline

The same core pattern as AmarV4 — signed upload, queue, transcode, R2 — but the fan-out step is more complex: one source becomes five distinct outputs, each with different FFmpeg filter chains and path conventions.

Upload
Signed URL → R2Direct from clientServer bypassed
Queue
BullMQHono backendRedis
Transcode
FFmpegInstagram 9:16 ReelYouTube ShortHLS segments + master
Derive
Blur-shot thumbnailCover frame extractStructured R2 paths
Playback
React Video PlayerHLS adaptiveOutput grid UI

§03Three decisions worth defending

Decision 01

Fan-out as named jobs, not one mega-job

Each output format is a separate BullMQ job. If the Instagram render fails, the HLS segments still complete. The client sees per-format progress and only broken outputs need retrying — not the whole upload.

Decision 02

Structured R2 paths as the delivery contract

Every output lands at a deterministic path: uploads/{id}/hls/master.m3u8, uploads/{id}/reel.mp4, and so on. The frontend never asks the backend “where did the files go?” — it constructs the URL from the job ID. No extra database round-trip.

Decision 03

Blur-shot thumbnail from FFmpeg, not a design tool

The blurred-background thumbnail — source frame centred on a blurred full-bleed version of itself — is a single FFmpeg filtergraph. It saves the client from opening any image editor and produces a consistent look across every video automatically.

§04Hardest problems, plainly

Challenge 01

FFmpeg filtergraphs for the blur-shot

The blurred background + centred source composite sounds simple and is not. The filtergraph has to scale the source to two different sizes, blur one, overlay the other with correct gravity and padding — and do all of it in a single pass to keep encode time reasonable.

Challenge 02

Aspect ratio maths for platform crops

Instagram and YouTube Shorts both want 9:16, but a landscape source cropped naively loses the subject. A centre-crop is the safe default, but getting the crop coordinates right across arbitrary source resolutions without distortion took more geometry than expected.

Challenge 03

Progress visibility across five parallel jobs

Five jobs per upload means five status states the UI has to reflect simultaneously. BullMQ has per-job event emitters; wiring them into a coherent “this upload is 3/5 done” view over SSE was the most fiddly part of the frontend.

“The client's job is to make good video. PIPE's job is to make sure the format question never enters the room.”— Parm, on PIPE
Talk about this project →
Open to work

Have something in mind? Let's make it.

iamparmjeetmishra@gmail.com→
GithubMailLinkedInX/Twitter
arm© 2026 — Made with ♡ by Parm
HomeWorkAboutWritingResumeContact