nginx rtmp流媒体服务HLS刷新仅播放音频视频黑屏问题咨询
问题根因前置说明
该问题90%以上概率由关键帧间隔和HLS分片时长不匹配导致:你设置的HLS分片时长为1s,但OBS推流的关键帧间隔为2s,会有一半的TS分片不包含视频关键帧。播放器刷新后如果加载的首个分片没有关键帧,无法解码视频首帧,而音频解码不需要依赖关键帧,就会出现有声音无画面的黑屏现象。
排查步骤
- 验证TS分片的关键帧分布
执行ffprobe命令检查任意TS分片是否包含关键帧:ffprobe -v error -select_streams v:0 -show_entries packet=flags -of compact=p=0:nk=1 目标分片文件.ts
如果输出结果中没有携带K标记的内容,说明该分片无视频关键帧,即可确认根因。 - 检查m3u8索引配置
打开生成的m3u8文件,确认是否存在#EXT-X-INDEPENDENT-SEGMENTS标记,缺少该标记时部分播放器不会主动跳转至之前的分片拉取关键帧,只会等待当前分片的关键帧出现,延长黑屏时间。 - 确认播放器首分片加载逻辑
用浏览器开发者工具的网络面板,查看刷新后播放器请求的第一个TS分片序号,匹配该分片的关键帧存在情况,确认是否为首分片无关键帧触发的问题。
解决方案
最优方案:对齐参数配置
将推流端关键帧间隔和服务端HLS分片时长调整为一致即可:
- 方案1:修改OBS推流配置,将关键帧间隔调整为1s,保证每个1s的TS分片都包含至少一个关键帧
- 方案2:修改nginx配置,将
hls_time调整为2s,和OBS的关键帧间隔对齐,避免生成无关键帧的分片
服务端兼容配置(无需修改推流端)
如果无法调整推流端参数,可以修改nginx rtmp配置做兼容:
rtmp { server { listen 1935; application live { live on; hls on; hls_path /tmp/hls; # 强制HLS分片对齐关键帧 hls_flags split_discont; # 强制m3u8第一个分片始终为带关键帧的分片 hls_start_on_keyframe on; # 输出独立分片标记,让播放器支持分片独立解码 hls_independent_segments on; } } }
兜底方案:服务端实时转码
如果上述配置不生效,可以在nginx层增加ffmpeg实时转码逻辑,强制重写视频关键帧间隔为1s,保证所有TS分片都包含关键帧。
内容的提问来源于stack exchange,提问作者Nguyễn Thành Duy
相关产品推荐
相关产品推荐

