Stream Video Over HTTP Chunked Encoding with FFmpeg

This guide explains how to stream live or pre-recorded video over HTTP chunked transfer encoding using FFmpeg. You will learn how HTTP chunked transfer works for video, the exact FFmpeg commands required to configure the stream, and how to set up a receiving server to capture the chunked video data in real time.

Understanding HTTP Chunked Transfer Encoding

HTTP chunked transfer encoding allows a server or client to send data in a series of “chunks” without needing to know the final size of the content beforehand. This is ideal for live video streaming because the video is generated continuously, making it impossible to define a Content-Length header in advance.

By using chunked transfer encoding, FFmpeg can continuously push video data to an HTTP server using a POST or PUT request as the video is being encoded.

The FFmpeg Command for Chunked Streaming

To stream video via HTTP chunked transfer encoding, you must use FFmpeg’s HTTP protocol muxer and enable the -chunked_post option.

Below is the standard command to stream an input video file (or live camera feed) to a remote server using MPEG-TS format over chunked HTTP:

ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -c:a aac -f mpegts -chunked_post 1 http://yourserver.com/live/stream

Parameter Breakdown:

Setting Up a Receiving Server

For the stream to work, you need a web server configured to accept HTTP POST requests and handle the incoming chunked data. Below is a minimal example using Node.js to receive the stream and save it to a file on the disk:

const http = require('http');
const fs = require('fs');

const server = http.createServer((req, res) => {
    if (req.method === 'POST') {
        console.log('Receiving chunked video stream...');
        const writeStream = fs.createWriteStream('received_stream.ts');
        
        req.on('data', (chunk) => {
            writeStream.write(chunk);
        });

        req.on('end', () => {
            writeStream.end();
            res.writeHead(200, { 'Content-Type': 'text/plain' });
            res.end('Stream finished');
            console.log('Stream completed.');
        });
    } else {
        res.writeHead(404);
        res.end();
    }
});

server.listen(8080, () => {
    console.log('Server listening on port 8080');
});

To stream to this local test server, you would point your FFmpeg command to: http://localhost:8080/.

Optimizing for Low Latency

If you experience high latency when streaming, adjust the following FFmpeg settings to reduce buffering:

An optimized low-latency command looks like this:

ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -tune zerolatency -g 30 -bf 0 -c:a aac -f mpegts -chunked_post 1 http://localhost:8080/