Building a Live Streaming Platform with Nginx, FFmpeg, and RTMP/HLS

Architectural Overview

A live video broadcasting system comprises three fundamental components: a publishing endpoint, a media server, and playback clients. The publishing side uses FFmpeg for encoding and sending streams. The server layer employs Nginx enhanced with an RTMP module to ingest and distribute content. Viewer-side playback can be handled by tools like Video.js or VLC media player.

Compiling Nginx with the HTTP-FLV Module

Begin by setting up the build environment on a CentOS 7.8 system. Install the required development toolchain and libraries:

yum install -y gcc gcc-c++ autoconf pcre pcre-devel make automake
yum install -y wget httpd-tools vim

Next, obtain the module source code. The nginx-http-flv-module extends the original RTMP module with additional features and is available with Chinese documentation. Download and unpack it:

cd /opt
wget https://github.com/winshining/nginx-http-flv-module/archive/master.zip
unzip master.zip

Fetch the Nginx source archive as well:

wget http://nginx.org/download/nginx-1.17.6.tar.gz
tar -zxvf nginx-1.17.6.tar.gz

Navigate into the Nginx source directory and configure the build, specifying the path to the extra module:

cd nginx-1.17.6
./configure --add-module=../nginx-http-flv-module-master

To prevent compilation from halting on non-critical warnings, edit the generated Makefile to remove the -Werror flag:

vim objs/Makefile

After saving the changes, compile and install Nginx:

make && make install

Configuring Live and On-Demand Services

Open the main Nginx configuration file with an editor:

vim /usr/local/nginx/conf/nginx.conf

Add an rtmp block to define publishing endpoints for live streaming, HLS delviery, and video-on-demand:

rtmp {
    server {
        listen 1935;
        chunk_size 4096;

        application live {
            live on;
        }

        application hls {
            live on;
            hls on;
            hls_path /usr/local/nginx/html/hls;
        }

        application vod {
            play /opt/video/vod;
        }
    }
}

Create the directories referenced by the configuration:

mkdir -p /usr/local/nginx/html/hls
mkdir -p /opt/video/vod

Verify the syntax and launch the Nginx service:

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx

Publishing Streams with FFmpeg

Use FFmpeg to send a pre-recorded video file as a live stream. The -re flag ensures the input is read at its native frame rate:

ffmpeg -re -i sample.mp4 -vcodec libx264 -acodec aac -f flv rtmp://your-server-ip/hls/streamkey

To stream directly from a webcam on Windows:

ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f flv rtmp://your-server-ip/live/streamkey

Performing On-Demand Playback with VLC

VLC supports RTMP and HLS protocols natively. After placing media files inside the /opt/video/vod directory, on-demand access becomes available through the server. Open VLC, choose "Open Network Stream", and enter the appropriate URL based on the publication point defined in the configuration.

Delivering HLS Playback via Video.js

To embed HLS streams in a web page, integrate Video.js along with the HLS-compatible source tags. Ensure your server's Nginx configuration includes proper MIME types and CORS headers within the HTTP context:

types {
    application/vnd.apple.mpegurl m3u8;
    video/mp2t ts;
}
expires -1;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

Example HTML snippet:

<link href="https://vjs.zencdn.net/7.0.3/video-js.css" rel="stylesheet">
<video id="player" class="video-js vjs-default-skin" controls preload="auto" width="720" height="540" data-setup='{}'>
    <source src="http://your-server-ip/hls/streamkey.m3u8" type="application/x-mpegURL">
</video>
<script src="https://vjs.zencdn.net/7.0.3/video.js"></script>

Automating Streams via Python

Python scripts can control FFmpeg processes for tasks like screen recording and automated publishing. The following example records a 5-second desktop capture and then publishes a file:

import subprocess
import time

record_cmd = (
    'ffmpeg -thread_queue_size 16 -f gdigrab -i desktop '
    '-s 1280x720 -vcodec libx264 -y capture.mp4'
)
ffmpeg_proc = subprocess.Popen(record_cmd, shell=True, stdin=subprocess.PIPE)
time.sleep(5)
ffmpeg_proc.stdin.write('q'.encode("GBK"))
ffmpeg_proc.communicate()

stream_cmd = (
    'ffmpeg -re -i d:/movies/video.mp4 -vcodec libx264 '
    '-acodec aac -f flv rtmp://192.168.0.102:1935/hls/demo'
)
subprocess.Popen(stream_cmd, shell=True, stdin=subprocess.PIPE)

Adding Access Authentication

Adding token-based authentication or other permissoin checks requires modifying the Nginx RTMP configuration. Official directives can be found in the module's documentation:

https://github.com/arut/nginx-rtmp-module/wiki/Directives

Reference implementations are available at: https://www.cnblogs.com/zkfopen/p/11764127.html

Tags: nginx ffmpeg rtmp HLS LiveStreaming

Posted on Sat, 11 Jul 2026 17:35:30 +0000 by fbm