yum upgrades for production use, this is the repository for you.
Active subscription is required.
The NGINX MPEG-TS module (nginx-module-ts) transforms NGINX into a powerful live streaming origin server. It receives MPEG-TS streams over HTTP and automatically generates HLS (HTTP Live Streaming) and MPEG-DASH manifests and segments for playback on any device.
This NGINX module is ideal for scenarios where you need a lightweight, high-performance solution to ingest live video from encoders like FFmpeg, OBS Studio, or hardware encoders, and deliver adaptive bitrate streams to viewers.
Why Use the NGINX MPEG-TS Module?
Traditional streaming servers like Wowza or Adobe Media Server are often overkill for simple live streaming setups. The NGINX MPEG-TS module provides:
- Lightweight operation: Runs as an NGINX module with minimal resource overhead
- HTTP-based ingest: Receives streams via standard HTTP POST, simplifying firewall configuration
- Dual output formats: Generates both HLS and MPEG-DASH from a single ingest point
- Adaptive bitrate support: Automatically creates master playlists for multi-bitrate streams
- Automatic cleanup: Manages segment files automatically, removing old segments as new ones arrive
If you need to add authentication to your streams, NGINX makes that straightforward with additional modules.
How the NGINX MPEG-TS Module Works
The module operates in three phases:
- Ingest: An encoder sends an MPEG-TS stream to NGINX via HTTP POST
- Processing: The module parses the transport stream, extracts audio and video elementary streams
- Output: Segments and playlists are written to disk in HLS (
.m3u8+.ts) or DASH (.mpd+.mp4) format
The stream name is derived from the last component of the request URI. For example, posting to /publish/livestream creates output in a livestream subdirectory.
Installation
RHEL, CentOS, AlmaLinux, Rocky Linux
Install the module from the GetPageSpeed repository:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-ts
Then load the module in your nginx.conf:
load_module modules/ngx_http_ts_module.so;
Debian and Ubuntu
First, set up the GetPageSpeed APT repository, then install:
sudo apt-get update
sudo apt-get install nginx-module-ts
On Debian/Ubuntu, the package handles module loading automatically. No
load_moduledirective is needed.
For detailed package information, visit the RPM module page or APT module page.
Configuration Directives
The NGINX MPEG-TS module provides three directives for configuring live streaming.
ts
Syntax: ts;
Context: location
Enables the MPEG-TS handler for the location. This directive is required for any streaming configuration. It tells NGINX to accept incoming MPEG-TS data and process it according to the ts_hls and ts_dash directives.
location /publish/ {
ts;
# Additional ts_hls or ts_dash configuration here
}
ts_hls
Syntax: ts_hls path=PATH [segment=MIN[:MAX]] [segments=NUMBER] [max_size=SIZE] [noclean]
Context: location
Enables HLS (HTTP Live Streaming) output generation.
| Parameter | Default | Description |
|---|---|---|
path |
required | Directory where HLS files are written |
segment |
5s:10s |
Minimum and maximum segment duration |
segments |
6 |
Number of segments to keep in the playlist |
max_size |
16m |
Maximum segment size before forced split |
noclean |
disabled | Disable automatic deletion of old segments |
The module creates a subdirectory for each stream under the specified path. For example, with path=/var/media/hls, a stream named live creates files in /var/media/hls/live/.
Example HLS configuration:
location /publish/ {
ts;
ts_hls path=/var/media/hls segment=10s segments=5;
client_max_body_size 0;
}
ts_dash
Syntax: ts_dash path=PATH [segment=MIN[:MAX]] [segments=NUMBER] [max_size=SIZE] [noclean]
Context: location
Enables MPEG-DASH output generation. Parameters are identical to ts_hls.
location /publish/ {
ts;
ts_dash path=/var/media/dash segment=6s segments=4;
client_max_body_size 0;
}
Practical Configuration Examples
Basic Live Streaming Setup
This configuration creates a complete live streaming server with both HLS and DASH output:
server {
listen 8080;
# Ingest endpoint - receives MPEG-TS from encoders
location /publish/ {
ts;
ts_hls path=/var/media/hls segment=10s;
ts_dash path=/var/media/dash segment=10s;
# Allow unlimited upload size for continuous streaming
client_max_body_size 0;
}
# Playback endpoint - serves HLS/DASH to viewers
location /play/ {
types {
application/x-mpegURL m3u8;
application/dash+xml mpd;
video/MP2T ts;
video/mp4 mp4;
}
alias /var/media/;
# Disable caching for live content
add_header Cache-Control "no-cache";
# Enable CORS for web players
add_header Access-Control-Allow-Origin "*";
}
}
After creating this configuration:
mkdir -p /var/media/hls /var/media/dash
chown nginx:nginx /var/media /var/media/hls /var/media/dash
nginx -t && systemctl reload nginx
For more advanced header handling, see our guide on the pitfalls of add_header.
Streaming with FFmpeg
Send a live stream to the NGINX MPEG-TS module using FFmpeg:
ffmpeg -f lavfi -i "testsrc2=duration=60:size=1280x720:rate=30" \
-f lavfi -i "sine=frequency=440:duration=60" \
-c:v libx264 -preset fast -tune zerolatency -g 30 \
-c:a aac -b:a 128k \
-f mpegts http://your-server:8080/publish/livestream
The stream becomes available at:
– HLS: http://your-server:8080/play/hls/livestream/index.m3u8`http://your-server:8080/play/dash/livestream/index.mpd`
- DASH:
Adaptive Bitrate Streaming (ABR)
The NGINX MPEG-TS module automatically creates HLS master playlists when receiving multi-program MPEG-TS streams. Use FFmpeg’s -program option to create multiple quality variants:
ffmpeg -f lavfi -i "testsrc2=duration=120:size=1280x720:rate=30" \
-f lavfi -i "sine=frequency=440:duration=120" \
-map 0:0 -map 1:0 -map 0:0 -map 1:0 \
-c:v:0 libx264 -b:v:0 2500k -s:v:0 1280x720 -preset fast -g 30 \
-c:a:0 aac -b:a:0 128k \
-c:v:1 libx264 -b:v:1 800k -s:v:1 640x360 -preset fast -g 30 \
-c:a:1 aac -b:a:1 64k \
-program "st=0:st=1" -program "st=2:st=3" \
-f mpegts http://your-server:8080/publish/abr
This creates:
– index.m3u8 – Master playlist with bandwidth information
– 1.m3u8 – High quality variant (720p @ 2500kbps)
– 2.m3u8 – Low quality variant (360p @ 800kbps)
The master playlist format:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=2628000
1.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=864000
2.m3u8
Video players that support adaptive bitrate streaming will automatically switch between quality levels based on network conditions.
Recording Mode with noclean
For recording scenarios where you want to preserve all segments after the stream ends:
location /record/ {
ts;
ts_hls path=/var/media/recordings segment=10s noclean;
client_max_body_size 0;
}
Without noclean, the module automatically removes segments that are no longer referenced in the playlist.
Testing and Verification
Verify Module Installation
Check that the module file exists:
ls -la /usr/lib64/nginx/modules/ngx_http_ts_module.so
Verify the module is loaded:
nginx -T 2>&1 | grep ts_module
Test Configuration Syntax
Always test your configuration before reloading:
nginx -t
Verify Stream Processing
Start a test stream and check the output:
# Start a 30-second test stream
ffmpeg -f lavfi -i "testsrc2=duration=30:size=640x360:rate=25" \
-c:v libx264 -preset ultrafast -g 25 \
-f mpegts http://localhost:8080/publish/test
# Check generated files
ls -la /var/media/hls/test/
# View the playlist
cat /var/media/hls/test/index.m3u8
Expected playlist output:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:10
#EXTINF:5.000,
0.ts
#EXTINF:5.000,
1.ts
#EXTINF:5.000,
2.ts
Test HTTP Playback
Verify content is accessible via HTTP:
curl -I http://localhost:8080/play/hls/test/index.m3u8
Expected response:
HTTP/1.1 200 OK
Content-Type: application/x-mpegURL
Performance Considerations
Segment Duration
Shorter segments (2-4 seconds) reduce latency but increase HTTP requests. Longer segments (8-12 seconds) are more efficient but increase start-up time. A segment duration of 5-10 seconds works well for most live streaming scenarios.
Keyframe Interval
The encoder’s keyframe interval (GOP size) should match the minimum segment duration. If keyframes are infrequent, segments may extend to the maximum duration, causing inconsistent playback.
For a 10-second segment:
ffmpeg ... -g 300 ... # Keyframe every 300 frames (10s at 30fps)
Disk I/O
The module continuously writes segments to disk. For high-bitrate streams, use:
- Fast storage (SSD or NVMe)
- Dedicated partition for media files
- tmpfs for extremely low latency (if RAM permits)
Example tmpfs configuration in /etc/fstab:
tmpfs /var/media/live tmpfs size=2G,mode=0755 0 0
Worker Processes
Each stream consumes a worker connection. Ensure worker_connections is sufficient for your expected concurrent streams plus viewers. For optimal NGINX performance, proper buffer tuning also matters.
Troubleshooting
Stream Not Starting
Symptom: FFmpeg reports “Connection refused”
Solutions:
1. Verify NGINX is running: systemctl status nginx
2. Check the module is loaded: nginx -T | grep ts_module
3. Verify the port is listening: ss -tlnp | grep nginx
Empty Output Directory
Symptom: No files appear in the HLS/DASH directory
Solutions:
1. Check directory permissions: ls -la /var/media/
2. Ensure directory ownership: chown nginx:nginx /var/media/hls
3. Verify client_max_body_size is set: client_max_body_size 0;
Playlist Shows Wrong Duration
Symptom: #EXT-X-TARGETDURATION doesn’t match configuration
Cause: The value is calculated based on maximum segment duration, not minimum.
With segment=5s:10s, target duration will be 10 seconds.
Segments Disappearing
Symptom: Segment files are deleted while streaming
Cause: This is normal behavior. The module removes segments older than segments × max_segment_duration.
Solution: Use noclean for recording scenarios.
Comparison with NGINX RTMP Module
| Feature | MPEG-TS Module | RTMP Module |
|---|---|---|
| Ingest Protocol | HTTP | RTMP |
| Firewall Friendly | Yes (HTTP/HTTPS) | Requires port 1935 |
| Setup Complexity | Simple | Moderate |
| VOD Support | No | Yes |
| Recording | Via noclean | Built-in |
| Transcoding | External only | External only |
Choose the NGINX MPEG-TS module when you need HTTP-based ingest, particularly for cloud environments where only HTTP/HTTPS ports are available.
Conclusion
The NGINX MPEG-TS module provides a simple yet powerful solution for live streaming directly from NGINX. With HTTP-based ingest, automatic HLS and MPEG-DASH generation, and adaptive bitrate support, it handles common streaming scenarios without requiring additional streaming software.
Key takeaways:
– Use ts directive to enable the handler
– Configure ts_hls and/or ts_dash for output format
– Set client_max_body_size 0 for continuous streaming
– Use -program in FFmpeg for adaptive bitrate streams
– Add noclean when recording is needed
For the latest updates and to report issues, visit the nginx-ts-module GitHub repository.
