HLS Live Streaming Architecture
- Encoder: OBS/FFmpeg encodes camera or screen capture as H.264+AAC and pushes via RTMP to the media server
- Media Server: Receives the RTMP stream, cuts it into 2-6 second .ts segments, and dynamically updates the M3U8 playlist
- CDN (optional): Caches M3U8 and TS files at global edge nodes, reducing origin server load
- Player: Browser via HLS.js, or mobile via AVPlayer, fetches the M3U8 URL for playback
OBS Streaming Settings
In OBS: Settings → Stream → Service: Custom
| Setting | Recommended value | Notes |
|---|---|---|
| Server | rtmp://your-server-ip/live | Media server address |
| Stream key | your_stream_key | Identifies the stream source |
| Encoder | x264 or hardware | Use hardware encoding if GPU available |
| Bitrate | 2500–6000 kbps | 2500 for 720p, 4000–6000 for 1080p |
| Keyframe interval | 2 seconds | Required — affects segmentation accuracy |
Nginx-rtmp Configuration
rtmp {
server {
listen 1935;
application live {
live on;
record off;
hls on;
hls_path /tmp/hls;
hls_fragment 3s;
hls_playlist_length 12s;
}
}
}
http {
server {
listen 8080;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
}
}
SRS as an Alternative
SRS (Simple Realtime Server) offers simpler configuration and better performance than Nginx-rtmp:
listen 1935;
http_server { enabled on; listen 8080; }
vhost __defaultVhost__ {
hls {
enabled on;
hls_fragment 3;
hls_window 12;
hls_path ./objs/nginx/html;
}
}
After streaming, the M3U8 URL is: http://server-ip:8080/live/stream_key.m3u8
Paste this URL into the StreamFlow player to verify your stream is working.
hls_fragment to 2 seconds reduces end-to-end latency to 6–10 seconds. Getting below 4 seconds requires LL-HLS, which has more complex configuration requirements.CDN Caching Strategy
M3U8 playlists update every few seconds — set Cache-Control: no-cache or a very short TTL (5 seconds). TS segments have unique filenames and never change — set Cache-Control: max-age=86400 to dramatically reduce origin server load.
- Stream stops but M3U8 is still accessible: Nginx-rtmp does not clean up old playlists by default. Set
hls_cleanup onto auto-delete segments after the stream ends. - Player shows network error but stream is running: 99% of the time this is CORS. Check that the HTTP response includes
Access-Control-Allow-Origin. - Latency keeps growing: The player is accumulating buffer. Check
liveSyncDurationCountin HLS.js config, or force the player to jump to the latest segment. - OBS shows green screen/artifacts: Keyframe interval is not set correctly. Use a fixed 2-second interval — do not use "auto".
- High origin server load with many viewers: Immediately add a CDN. Players should never hit the origin directly in production.