微赞上的一个直播看完后,有直播回放,想把回放内容下载下来。下面是直播地址:
https://wx.vzan.com/live/tvchat-1258543007?v=1616723281737#/
打开chrome的检查,选择Network,用m3u8过滤,能得到一个m3u8文件的地址:
https://i3.vzan.cc/clip/673854892/1258543007/BFEB1A7F8C00BE99.m3u8
ffmpeg -stats -i https://i3.vzan.cc/clip/673854892/1258543007/BFEB1A7F8C00BE99.m3u8 output.mp4
发现执行了一段时间后,会提示 Non-monotonous DTS in output stream 0:1; previous: 7516921, current: 531870; changing to 7516921. This may result in incorrect timestamps in the output file.
原来是由于直播中断过几次,导致ts包计数不连续。
引发问题的根源在于 HLS/m3u8 流文件列表中,存在两个相邻切片之间的 TS 包计数不连续。(TS 包计数不连续的情况,可在 直播过程中存在推流中断后重推 的 直播流/回放流列表 中出现)。对于这种情况,HLS/m3u8 流文件列表会在与前者计数不连续的文件前加上 EXT-X-DISCONTINUITY 标签来显式地告诉播放器留意。但遗憾的是,FFmpeg 的 HLS 处理模块不支持该标签,进而导致遇到计数不连续的 TS 时,无意识地强制合并两个计数不连续的 TS,导致 Non-monotonous DTS in output stream 警告,再加上其他一些缺陷,最终导致合并后时间码不正确。
https://ynyyn.tk/i/post-32.html
于是将m3u8文件下载下来,手动根据 EXT-X-DISCONTINUITY 标签,将文件分割为20个文件,然后每个文件使用上述命令单独将每个m3u8文件下载转码成mp4
手动将 m3u8 依 #EXT-X-DISCONTINUITY 标签切分,构造成多个独立的 m3u8 列表,然后丢给 FFmpeg。
manually split the m3u8 in several pieces. where you see the #EXT-X-DISCONTINUITY tags. then (after making these pieces valid m3u8 singleton) feed them all to ffmpeg.这样每段各自合并成一个视频,之后再用 FFmpeg 的 concat 命令(https://trac.ffmpeg.org/wiki/Concatenate)把多个段的视频合并到一起,这样做就不会有问题(就是这么神奇)。
https://ynyyn.tk/i/post-32.html
that will give you several video pieces, but you can (as strangely as it may sound) merge them all together using ffmpeg without problem using the concat command (https://trac.ffmpeg.org/wiki/Concatenate).
ffmpeg -stats -protocol_whitelist "file,http,https,tcp,tls" -i BFEB1A7F8C00BE99_5.m3u8 5.mp4
上述问题真的不存在了。但是发现下载转码速度很慢,而且CPU满载,于是考虑用云服务器来执行,于是ssh连上云服务器,并通过ffmpeg的docker镜像执行
docker run -v $(pwd):$(pwd) -w $(pwd) jrottenberg/ffmpeg:4.1-alpine -stats -protocol_whitelist "file,http,https,tcp,tls" -i BFEB1A7F8C00BE99_5.m3u8 $(pwd)/5.mp4
漫长的等待过去之后,成功得到了20个mp4文件,这个过程成功将我的云服务器的CPU拉满
每个文件都可以正常播放,发现只有1、16、17、18、19这五个是需要的,其他都是广告,于是将这五个视频合并成一个。
先将五个mp4各自转为无损的ts
ffmpeg -i 1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
再将这五个ts合并成一个mp4
ffmpeg -i "concat:1.ts|16.ts|17.ts|18.ts|19.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
最终成功得到了高清的直播回放mp4