HLS 直播系统架构
一套完整的 HLS 直播链路包含四个环节:
- 推流端:OBS / FFmpeg 将摄像头或屏幕画面编码为 H.264+AAC,通过 RTMP 协议推送到流媒体服务器
- 流媒体服务器:接收 RTMP 推流,实时切割成 2-6 秒的 .ts 片段,并动态更新 M3U8 播放列表
- CDN 分发(可选):将 M3U8 和 TS 文件缓存到全球节点,降低源站压力
- 播放端:浏览器通过 HLS.js,或移动端通过 AVPlayer,拉取 M3U8 播放
OBS 推流设置
在 OBS 中配置推流:设置 → 串流 → 服务选择「自定义」,填入以下参数:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 服务器 | rtmp://your-server-ip/live | 流媒体服务器地址 |
| 推流码 | stream_key(自定义) | 区分不同推流来源 |
| 编码器 | x264 或 硬件编码 | 有 GPU 用硬件编码节省 CPU |
| 码率 | 2500-6000 kbps | 720p 用 2500,1080p 用 4000-6000 |
| 关键帧间隔 | 2 秒 | 必须设置,影响切片精度 |
Nginx-rtmp 服务器配置
# nginx.conf
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
# 开启 HLS 切片
hls on;
hls_path /tmp/hls; # 切片文件存储路径
hls_fragment 3s; # 每个 TS 片段时长
hls_playlist_length 12s; # M3U8 列表保留时长
# 允许任意来源推流(生产环境应限制 IP)
allow publish all;
allow play all;
}
}
}
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 替代方案
SRS(Simple Realtime Server)是另一个优秀的流媒体服务器,配置更简单,性能更好,支持 HTTP-FLV 和 WebRTC,推荐国内用户使用:
# SRS 最简 HLS 配置(conf/srs.conf)
listen 1935;
http_server {
enabled on;
listen 8080;
}
vhost __defaultVhost__ {
hls {
enabled on;
hls_fragment 3;
hls_window 12;
hls_path ./objs/nginx/html;
}
}
推流后,M3U8 地址为:http://server-ip:8080/live/stream_key.m3u8
在 StreamFlow 播放器 中输入该地址,即可验证直播流是否正常推送。
hls_fragment 设置为 2s(Nginx)或 2(SRS)可将端到端延迟降至 6-10 秒。进一步降低延迟(<4s)需要使用 LL-HLS,配置更复杂。CDN 接入注意事项
接入 CDN 后,M3U8 文件和 TS 文件的缓存策略要分开处理。M3U8 文件内容每隔几秒就会更新,必须设置 Cache-Control: no-cache 或极短的 TTL(如 5 秒);TS 片段文件名唯一,内容不变,可以长期缓存(Cache-Control: max-age=86400),大幅减少源站回源压力。
- 推流中断后 M3U8 列表仍可访问:Nginx-rtmp 默认不会立即清除旧的 M3U8,设置
hls_cleanup on可在推流结束后自动删除切片 - 播放器报"网络错误"但推流正常:99% 是 CORS 配置问题,检查 HTTP 响应头中是否有
Access-Control-Allow-Origin - 直播延迟越来越大:播放器累积了大量缓冲,检查
liveSyncDurationCount配置,或让播放器跳到最新片段 - OBS 推流绿屏/花屏:通常是关键帧间隔设置不对,确保设置为固定 2 秒,不要用"自动"
- 多人同时观看时源站压力大:立即接入 CDN,不要让播放器直接连源站