Building a Robust FFmpeg Video Transcoding Pipeline

Users upload videos in all sorts of formats—MOV from iPhones, MKV from torrents, AVI from 2008. The backend must accept them and serve a browser-friendly MP4/H.264 or WebM/VP9 without blocking the web process for minutes of transcoding. We designed a fault-tolerant pipeline that has been used in pro

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1286
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1243
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    983
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1034
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1107
  • image_website-_0.webp
    Website development for Red Pear
    555

Users upload videos in all sorts of formats—MOV from iPhones, MKV from torrents, AVI from 2008. The backend must accept them and serve a browser-friendly MP4/H.264 or WebM/VP9 without blocking the web process for minutes of transcoding. We designed a fault-tolerant pipeline that has been used in production for years—implemented it for over 30 projects. The result: adaptive quality profiles, real-time progress, and ready notifications. Typical server resource savings reach 40%—for a $1000 monthly server, that's $400 saved. CDN traffic costs drop significantly.

Why should you use asynchronous transcoding?

Video transcoding is a CPU-intensive operation that can take from seconds to tens of minutes depending on the clip length and encoding profile. Synchronous processing within an HTTP request is out of the question: it would block the web worker, cause timeouts, and tank responsiveness. The correct approach is an asynchronous job queue. Hardware encoding (NVENC) processes video 3x faster than software, but even it should not block the request.

Building a Transcoding Pipeline

The architecture includes several components. Below is a step-by-step process:

  1. Upload: the file is saved to object storage or local disk; a job ID is returned.
  2. Queue: a Job is pushed into a queue (RabbitMQ, Redis, SQS) to avoid blocking the HTTP request. This queue job video processing model ensures decoupling.
  3. Worker: picks up the Job, runs FFmpeg with the required parameters, writes progress to Redis.
  4. Notification: after completion, updates the database and notifies the client via WebSocket or polling.

A typical set of adaptive profiles for bitrate ladder:

Profile Resolution Video bitrate Audio bitrate CRF Preset
360p 640×360 600 kbps 96 kbps 28 fast
720p 1280×720 2500 kbps 128 kbps 23 fast
1080p 1920×1080 5000 kbps 192 kbps 22 medium

CRF (Constant Rate Factor) is the primary quality parameter for H.264 (H.264 conversion is handled by libx264): 18 = near lossless, 28 = acceptable quality at small size. preset affects encoding speed vs. file size. We use a Laravel FFmpeg service class to manage these profiles.

For HLS compatibility, we set keyframe interval (GOP size) to 2 seconds (e.g., -g 48 for 24fps). Using b-pyramid can improve compression by 5-10%. VMAF (Video Multimethod Assessment Fusion) metrics help fine-tune bitrate allocation per profile.

Tracking Transcoding Progress

FFmpeg can output progress via pipe. The worker parses lines in the format out_time_usec=... and saves percentages in Redis. The client receives updates via WebSocket (e.g., Laravel Echo) or polling. This allows accurate progress display without delays. Asynchronous video processing prevents timeouts. The progress mechanism is described in the FFmpeg documentation.

Container choice depends on the task: MP4 is universal for streaming, WebM with VP9 gives better compression, MKV is suitable for archival storage with subtitles. For the web, we recommend MP4 with H.264—browsers don't require plugins.

Implementing an FFmpeg Service

The key element is a service that manages the FFmpeg process with progress handling. This video processing PHP library handles the transcoding:

namespace App\Services; class FfmpegService { public function transcode( string $inputPath, string $outputPath, array $profile, ?callable $onProgress = null ): void { $width = $profile['width']; $height = $profile['height']; $videoBr = $profile['video_br']; $audioBr = $profile['audio_br']; $preset = $profile['preset']; $crf = $profile['crf']; // scale with aspect ratio preservation, pad to target size $scaleFilter = "scale={$width}:{$height}:force_original_aspect_ratio=decrease," . "pad={$width}:{$height}:(ow-iw)/2:(oh-ih)/2:black"; $cmd = implode(' ', [ 'ffmpeg -y', "-i " . escapeshellarg($inputPath), "-vf " . escapeshellarg($scaleFilter), "-c:v libx264", "-preset {$preset}", "-crf {$crf}", "-maxrate {$videoBr}", "-bufsize " . (intval($videoBr) * 2) . "k", "-c:a aac", "-b:a {$audioBr}", "-movflags +faststart", "-progress pipe:1", "-loglevel error", escapeshellarg($outputPath), ]); $descriptors = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; $proc = proc_open($cmd, $descriptors, $pipes); // ... read progress and check exit code } } 

-movflags +faststart is mandatory: it moves the moov atom to the beginning of the MP4, allowing the browser to start playback before fully downloading the file. Without it, the video won't start until the entire file is downloaded.

Choosing Between Software and Hardware Encoding

Software encoding (libx264) delivers better quality at low bitrates but is slower. Hardware encoding (NVENC) is faster but may degrade quality under strong compression. Comparison:

Parameter Software (libx264) Hardware (NVENC)
Speed 1x 3-5x
Quality Better at low bitrate Slightly worse
CPU load High Low
Availability Always Requires GPU

For production, we often combine: NVENC hardware acceleration for previews, libx264 for final archive. The optimal choice depends on your priorities: speed or quality. Advanced rate-distortion optimization (RDO) in libx264 further improves compression efficiency, albeit at higher computational cost.

What's Included in the Work

As part of developing this FFmpeg pipeline, we provide:

  • Queue setup (RabbitMQ/Redis) and supervisor worker for workers.
  • Implementation of an FFmpeg service with progress parsing.
  • Creation of Job classes with success/error handlers.
  • Configuration of adaptive profiles for your needs.
  • Endpoints to retrieve progress and results.
  • WebSocket notification integration (optional).
  • Deployment and monitoring documentation.
  • Post-delivery support and training.

The pipeline development typically costs between $800 and $1200 and delivers a return on investment within a few months through reduced server and CDN costs.

Timeline and Ordering

Developing a basic pipeline takes 2 to 4 days, depending on profile complexity and WebSocket requirements. We'll evaluate your project for free—contact us to discuss the details. We guarantee code quality and post-delivery support.

Common mistakes and how to avoid them
  • Ignoring the moov atom: without -movflags +faststart, video won't stream. Check with ffprobe -v quiet -print_format json -show_format output.mp4 | grep moov.
  • Too many parallel workers: CPU overload. Use numprocs=1 per worker in supervisor.
  • Forgetting job timeout: set an adequate timeout (e.g., one hour for long videos).
  • Not handling FFmpeg errors: check the return code and log stderr.

Use these recommendations—and your pipeline will run stably even under high load.