例子: http://youku.com-t-youku.com/20190209/3349_fcce50be/1000k/hls/index.m3u8
ffmpeg -i index.m3u8 -c copy -c:v h264 out.ts
①不一定要-c:v h264
,也可以-b:v 900k
,反正就是别-c:v copy
。大概在 160.ts 左右就开始出现 dup=0 drop=
丢弃帧(这样在ffmpeg -re
推流时有一段时间看起来就是没数据的),为什么会这样,如何解决?
FFmpeg 与下载的区别
ffmpeg -i index.m3u8 -c copy m3u8-ffmpeg.ts
aria2c -i index.m3u8 --download-result=hide
然后cat
合并
需补全 index.m3u8 内文件的地址
aria2c 是原样下载(因为它就是个下载工具),ffmpeg -c copy
和原件还是有区别
ffmpeg -c copy
和原件还是有区别"
fix: "ffmpeg -i index.m3u8 -c copy -c:v h264 out.ts"
ffmpeg -i index.m3u8 -c copy -c:v h264 out.ts
1
Satelli 2020-03-04 21:09:37 +08:00
接在 -i 后面的是针对输出的参数。
-c:v 是制定视频流的编码器,没有 h264 这个编码器,软件编码是默认 libx264。 -b 是制定流码率。-b:v 是指定视频码率,不能和 -c copy 混用。如果你需要重推流,-re 后接 -c copy 且不要指定码率。 ffmpeg -c copy 是与原件有区别,你只是单独拿出来里面的一条视频轨道和一条音频轨道再重新 mux 到你指定的容器格式里。原本容器的元数据、格式已经丢弃。 .m3u8 是播放列表,aria2 当然不能直接 -i 进来后只能看到文件名,没有原始路径。而且最后下载下来的也只是该资源在 HLS 分发下的片段。 ffmpeg 本质不是下载,只是把每一个片段按照 .m3u8 播放列表拼接在一起,最后再根据你指定的容器格式封装。 在这个情况下,原件就是这些片段。 |
2
Satelli 2020-03-04 21:19:09 +08:00
另,尝试了手动指定 -c:v h264 -b:v 900k,会 fallback 到 libx264。默认 -preset 是 medium。
在 Intel 45W 6 核心 6 线程的 CPU 能力下,该视频能有 5x 的编码速度。 |
3
lxk11153 OP @Satelli #1
- 其实我不太懂 h264 在具体上下文指什么,比如 -- 1. ffmpeg(/ffprobe): Stream #0:0: Video: h264 (High) -- 2. Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) -- 3. ffmpeg -codecs ---- DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb h264_amf h264_videotoolbox ) - 1. 不能混用我知道 2. 重推流,如果想原画推就-c copy,如果想调码率可以加呀 3. 我说到"-c:v h264"和"-b:v 900k"只是想表达你可以使用"ffmpeg -i index.m3u8 -c copy -c:v h264 out.ts"/"ffmpeg -i index.m3u8 -c copy -b:v 900k out.ts"来测试我说的"大概在 160.ts 左右出现 drop",然后在 drop 情况下-re 推流,别人在看流的话就会出现信号中断(/黑画面 maybe),So 如何解决?★ - 拿 aria2 来说,把片段都下载下来然后 cat 合成一个 out.ts 文件,我其实已经不知道这个 out.ts 文件还存不存在"元数据"还是.ts 这种格式有无"元数据"?★ - 因为 m3u8 里是相对路径,所以补全成绝对路径就可以 aria2c -i 使用了,对应我说的"需补全 index.m3u8 内文件的地址" |
4
lxk11153 OP fix #3 "1. 不能混用我知道 ……"
1. 混用问题不好意思,思考短路导致文案出错了 2. 重推流,如果想原画推就-c copy,如果想调码率可以加呀 3. see 第 2 条附言 |
5
mxalbert1996 2020-03-04 23:49:03 +08:00 via Android
这是原视频的问题,你可以试一下播放原视频的 11 分 3 秒左右。
另外 H264 是编码格式,libx264 ( x264 )是编码器,一个编码格式可能有很多种编码器,x264 是 H264 的编码器之一,ffmpeg 的 -c:v 和 -c:a 后面接的是编码器,比如同为 H264 的编码器你还可以选择 OpenH264。 |
6
lxk11153 OP new #4 "1. 不能混用我知道 ……"
1. 混用问题不好意思,思考短路导致文案出错了 2. (可能是前面混用引起的连锁,不纠结这里) 重推流,如果想原画推就 ffmpeg -re -i in -c copy out,如果想调码率可以指定码率呀 ffmpeg -re -i in -c copy -c:v h264 -b:v 900k out (后面的-c 会覆盖前面的,这里意思就是-c:v h264 其它 copy ) 3. see 第 2 条附言 ps: ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers built with Apple LLVM version 10.0.0 (clang-1000.11.45.5) |
7
fgodt 2020-03-04 23:58:10 +08:00
我看了下-c copy 存下来的视频没有问题啊,也没出现过 drop 现象 ffmpeg 是 4.2.2
|
8
lxk11153 OP @Satelli #2 因为我看官方文档上也有-c:v h264 的写法,感觉是自适应编码器(比如只有 OpenH264 的 ffmpeg 和只有 libx264 的编码器,两者的通用写法,我猜的);是只有个别的才有这种写法还是其它的也可以,比如 av1 对应 libaom-av1,vp9 对应 libvpx-vp9 ?
@mxalbert1996 #5 "播放原视频的 11 分 3 秒" 感谢,第一次接触 drop(都没想到原来是视频本身有问题),本地播放器看的话我这看到画面湖了几秒然后正常续播;但拿去推流,然后看流,会显示信号中断 /之后画面定格声音续播等状况然后可能会正常续播(可以手动刷新正常续播,不同浏览器看和手机 app 看可能出错表现不一样)。。。可能没啥好的解决方案吧,就这样吧。👆 @fgodt #7 不能都 copy 加个-c:v h264 就有 drop 了 |
9
Satelli 2020-03-05 12:28:15 +08:00
@lxk11153
.ts 也是一种容器格式。在你这个 case 下,原文件只是已经通过 HLS 分发出来的 .ts 片段。视频流总是指容器里的 H.264 数据。逻辑上你通过 cat 或 ffmpeg -f concat -c copy 拼接出来的整个文件不是原本的文件,但是视频流是没有变化的。音频同理。 h264 指 H.264 编码。H.264 有很多编码器,你可以通过 ffmpeg -encoders | grep h264 列出 ffmpeg 可用的编码器选项及注释。ffmpeg -codecs 列出的是编码,括号内接的就是该编码可用的编码器。 你的 log 里有一行 Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) 这行是指原容器的该条视频流将会用原生 H.264 解码器解码,通过 libx264 软件编码,放入新的容器中。 官方就 H.264 的编码向导 https://trac.ffmpeg.org/wiki/Encode/H.264 ,里面用的 libx264 做例子。使用 h264、vp9、av1 应该只会匹配到首个可用编码器。如果是自适应,macOS 平台用 h264 应该会使用更节能、快速的 VideoToolbox,而不是软件实现的 libx264,虽然质量无法与后者相比。这里为猜测。 手动指定编码器会 drop 原因应该和楼上指出 11 分 3 秒的视频数据损坏有关。-c copy 不会涉及解码,ffmpeg 会原封不动把原视频流拿过来,放入新的容器中。手动指定之后 ffmpeg 会使用默认的(或你指定的)解码器解码每一帧,再通过默认的(或你指定的)编码器进行编码后,再放入新的容器中。原视频视频流有错误,ffmpeg 解码就会出错。 |