我正在使用最新(从源代码构建)的 FFmpeg 编码实时 25 FPS 950x540 H.264 纯视频流,清单中包含 10 个片段,每个片段 5 秒,并在本地 LAN 上的另一台计算机上使用该流 [隐身以避免缓存问题] Chrome 具有最新的
hls.js
(cdn.jsdelivr.net/npm/hls.js@latest)。 编码后的视频可以播放但不可靠;我有两个问题:
hls.js
客户端在几分钟后开始无法与视频流同步,抱怨超出了同步窗口的末尾,并且在重新同步时获得空缓冲区。hls.js
客户端不会同步到流,除非我同时启动流和客户端:如果hls.js
客户端在启动后数十秒内尝试使用流,它再次无法同步随着溪流。 我可以成功启动流的唯一方法是先删除 .m3u8
文件,这样浏览器就找不到该文件,然后客户端读取该文件并开始流式传输。 Chrome 的 F12 窗口显示类似“[stream-controller]: Playback: 0.000 is located too far from the end of live slider playlist: 49.92, Reset currentTime to : 44.920”,这可能是预料之中的,但随后更神秘地显示“[abr]缓冲区为空,最佳质量级别 0”,在成功的情况下绝对不会发生这种情况。显然我有一些根本性的错误,我只是不明白是什么。 我对 FFmpeg 的 HLS 标志是
discont_start
和 omit_endlist
,并且客户端已被指示不要缓存。 这是一个示例 .m3u8
输出文件:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:5
#EXT-X-MEDIA-SEQUENCE:30
#EXTINF:5.120000,
http://10.10.1.16/watchdog30.ts
#EXTINF:4.880000,
http://10.10.1.16/watchdog31.ts
#EXTINF:5.120000,
http://10.10.1.16/watchdog32.ts
#EXTINF:4.880000,
http://10.10.1.16/watchdog33.ts
#EXTINF:5.120000,
http://10.10.1.16/watchdog34.ts
#EXTINF:4.880000,
http://10.10.1.16/watchdog35.ts
#EXTINF:5.120000,
http://10.10.1.16/watchdog36.ts
#EXTINF:4.880000,
http://10.10.1.16/watchdog37.ts
#EXTINF:5.120000,
http://10.10.1.16/watchdog38.ts
#EXTINF:4.880000,
http://10.10.1.16/watchdog39.ts
我还尝试添加标志
independent_segments
并包含 program_date_time
,但这没有帮助。
我错过了什么?
我的完整代码(FFMpeg 由其 C API 驱动)可以在这里找到:https://github.com/RobMeades/watchdog/blob/83e718390f779a7ef98d2be009784e8be5deaf5f/software/watchdog.cpp#L933。 此代码在最新的 Raspbian 下的 Raspberry Pi 5 上运行。
答案是...告诉 FFmpeg
libx264
视频编解码器到 -tune zerolatency
。
在 FFmpeg C API 中,这是通过
av_dict_set(&codecOptions, "tune", "zerolatency", 0)
完成的,其中 codecOptions
是 AVDictionary
,然后您将作为最后一个参数传递给 avcodec_open2()
。
为什么?我无法告诉你。 在我找到这个之前,我花了近一周的时间尝试了所有我能尝试的事情。 通过添加此单个选项,
hls.js
客户端在所有情况下每次都会与 HLS 流同步和重新同步。 如果没有它,如果在流开始后几秒钟启动,hls.js
将无法获得与 HLS 流的初始同步,并且如果失去同步也不会重新获得同步。
请注意,我确实尝试使用
hls.js
运行 lowLatency: false
但这并没有解决问题。
我们生活并学习。