如何用 ffmpeg 找到损坏的视频 50 块钱悬赏答案

2022-09-01 04:58:30 +08:00
 1054850490
为了避免同时出现两个答案的情况,悬赏按照时间先后顺序给,最好就是如果有哥们觉得自己会的话,可以评论一下自己在弄,占一下位,避免别的哥们白忙活。

我用着 yt-dlp+aria2 下载着 youtube 视频,视频后处理是 ffmpeg ,因为下载的视频多大几万部,所以有个问题可能存在了很久但是一直没发现,就是有些视频损坏了,就是前面正常,但是后面其中某些段落播放花屏,但是我重新下载的时候又是好的,所以我猜测应该是合成 m3u8 的时候出现了错误,由于 aria2 的关系,下载的视频是分段下载的,而且一直是挂后台下载的,并没有日志,如果有小伙伴知道 yt-dlp 如何开启日志也可以告知。

我现在就是求如何从几万部视频中,自动化的识别出损坏的部分视频,我下面贴上损坏的视频下载链接,可以试一下

https://imgur.com/OXoRgP9
https://imgur.com/clQlBRZ


https://drive.google.com/file/d/1TDbxYD0vri0D8aIJ6a1OSY2abE9tc6Lk/view?usp=sharing
https://drive.google.com/file/d/1Z_kWFZp4YP5q16CixMv_RmlIWIXFTrzb/view?usp=sharing
4462 次点击
所在节点    FFmpeg
32 条回复
Valyrian
2022-09-01 06:01:58 +08:00
ffmpeg -xerror -i filename.mkv -f null -
JasonEWNL
2022-09-01 10:17:29 +08:00
「 yt-dlp 如何开启日志」的角度,以第一个视频为例:

$ yt-dlp "<amp-youtube data-videoid="olOzlESoEh0" layout="responsive" width="480" height="270"></amp-youtube>" > log.txt 2>&1

成功时:

$ cat log.txt
[youtube] olOzlESoEh0: Downloading webpage
[youtube] olOzlESoEh0: Downloading android player API JSON
[info] olOzlESoEh0: Downloading 1 format(s): 248+251
[download] Destination: 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f248.webm
[download] 100% of 28.26MiB in 00:01 at 25.82MiB/s
[download] Destination: 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f251.webm
[download] 100% of 1.75MiB in 00:00 at 14.48MiB/s
[Merger] Merging formats into "220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].webm"
Deleting original file 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f251.webm (pass -k to keep)
Deleting original file 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f248.webm (pass -k to keep)

失败时:

$ cat log.txt
[youtube] olOzlESoEh0: Downloading webpage
[youtube] olOzlESoEh0: Downloading android player API JSON
[info] olOzlESoEh0: Downloading 1 format(s): 248+251
[download] Destination: 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f248.webm
[download] 100% of 28.26MiB in 00:01 at 17.19MiB/s
[download] Destination: 220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].f251.webm
[download] 100% of 1.75MiB in 00:00 at 5.02MiB/s
[Merger] Merging formats into "220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam [olOzlESoEh0].webm"
ERROR: Postprocessing: Press [q] to stop, [?] for help
1054850490
2022-09-01 16:30:04 +08:00
@Valyrian 我测试了一下,h264 的视频错误发现了,但是 vp9 的并没有发现,也就是下面链接这个视频
https://drive.google.com/file/d/1Z_kWFZp4YP5q16CixMv_RmlIWIXFTrzb/view?usp=sharing
Valyrian
2022-09-02 02:54:49 +08:00
数一下时间和总帧数对比一下吧

https://stackoverflow.com/questions/2017843/fetch-frame-count-with-ffmpeg
https://superuser.com/questions/650291/how-to-get-video-duration-in-seconds

你这个视频是 30fps 但 60 秒只有 947 帧

$ ffmpeg -i 우주소녀\ 루다\ 부탁해-宽度 720-码率 897.992-编码 vp9-频道名\(지구젤리\)-网页地址 flh-q3MpgVg.mkv
ffmpeg version 5.1 Copyright (c) 2000-2022 the FFmpeg developers
built with Apple clang version 13.1.6 (clang-1316.0.21.2.5)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/5.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-neon
libavutil 57. 28.100 / 57. 28.100
libavcodec 59. 37.100 / 59. 37.100
libavformat 59. 27.100 / 59. 27.100
libavdevice 59. 7.100 / 59. 7.100
libavfilter 8. 44.100 / 8. 44.100
libswscale 6. 7.100 / 6. 7.100
libswresample 4. 7.100 / 4. 7.100
libpostproc 56. 6.100 / 56. 6.100
Input #0, matroska,webm, from '우주소녀 루다 부탁해-宽度 720-码率 897.992-编码 vp9-频道名(지구젤리)-网页地址 flh-q3MpgVg.mkv':
Metadata:
ENCODER : Lavf59.16.100
Duration: 00:01:00.07, start: 0.000000, bitrate: 594 kb/s
Stream #0:0(eng): Video: vp9 (Profile 0), yuv420p(tv, smpte170m/bt470bg/bt709), 720x1228, SAR 1:1 DAR 180:307, 30 fps, 30 tbr, 1k tbn (default)
Metadata:
DURATION : 00:00:59.999000000
Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp (default)
Metadata:
HANDLER_NAME : ISO Media file produced by Google Inc.
VENDOR_ID : [0][0][0][0]
DURATION : 00:01:00.070000000
At least one output file must be specified

$ ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 우주소녀\ 루다\ 부탁해-宽度 720-码率 897.992-编码 vp9-频道名\(지구젤리\)-网页地址 flh-q3MpgVg.mkv
60.070000

$ ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 우주소녀\ 루다\ 부탁해-宽度 720-码率 897.992-编 码 vp9-频道名\(지구젤리\)-网页地址 flh-q3MpgVg.mkv
947
1054850490
2022-09-02 05:34:11 +08:00
@Valyrian 意思是只能通过间接证据推敲视频有没有损坏吗?因为我视频非常的多,用这种方法估计不太现实,ffmpeg 能不能自动分析到错误的帧并且反馈?慢点没关系
Valyrian
2022-09-02 06:23:03 +08:00
@1054850490 这个也可以自动化的,一条命令变成三条命令而已
1054850490
2022-09-02 06:56:13 +08:00
@Valyrian 好吧这个间接方法对我来说应该没什么用了,要写一个逻辑判断对我来说还是很难做到的,我昵称就是我的 id ,加我拿悬赏吧
1054850490
2022-09-02 06:56:53 +08:00
@Valyrian 我 id 就是我 qq 账号
ungrown
2022-09-02 09:50:23 +08:00
要是大段的数据丢失,那可能还能通过媒体流的帧率、总长之类的来推测。
如果只是中间一小段、甚至一两帧损坏,那这种粗粒度的推测就没效果。
要彻底检测,就必须要把每一帧都检查,用 ffplay 加速解码播放,或者用 ffmpeg 选最小的分辨率最快的编码进行转码,整个过程 loglevel 全开,然后在 stderr 里面匹配关键词。
1054850490
2022-09-02 16:43:32 +08:00
@ungrown 是呀,刚才那个方法不通用,有一个 h264 的视频帧数和原本差不了几帧,很难判断有没有问题,我在想,这些损坏的视频,他们有没有明显的特征?间接证据的方法太难用了
acreti
2022-09-03 18:44:20 +08:00
@1054850490 “有一个 h264 的视频帧数和原本差不了几帧”,这个视频能不能发出来看看。如果楼主能追加悬赏得话,我可以写一个 Powershell+FFmpeg 批处理脚本,筛选出所有错误视频。
1054850490
2022-09-03 22:51:35 +08:00
@acreti
https://drive.google.com/file/d/1TDbxYD0vri0D8aIJ6a1OSY2abE9tc6Lk/view?usp=sharing

就是这个链接的视频,ffmpeg 读取帧数为“2985”,potplayer 读取为“3145”,而我把秒数*帧数的话是“3120”,由于帧速率后面是小数点,我四舍五入当 30 帧了,但是由于视频时长不确定,如果碰到视频时长更长,而且只损坏几帧的话,很容易就当误差范围了,所以我听听你的方法,如果可行的话倒是可以加酬劳,不可行的话就不用浪费太多时间了
acreti
2022-09-03 23:38:16 +08:00
@1054850490 你这种情况属于时间戳上丢失了视频帧,如图: https://imgur.com/a/3GKa3nr ,这个视频实际帧数量 2372 帧。脚本代码:ls *.mkv,*.mp4 -Recurse | % {ffmpeg -v 8 -stats -hwaccel cuda -i $_ -fps_mode cfr -f null - 2>Temp.txt; $S=gc Temp.txt -Tail 1; if($S.Contains('dup')){echo $_.FullName$S`n; mv $_ D:\}}

1. 确保 FFmpeg.exe 已在环境变量中,在包含视频的上级目录下 Shift+右键,此处打开 powershell ,运行命令后将筛选文件夹中所有视频。无所谓 h264 、vp9 ,即使只丢失一帧,也能挑出来
2. 脚本只检索了 mkv 和 MP4 ,若有其他后缀的视频,自行添加
3. 默认移出错误视频到 D 盘根目录,可自行更改
4. 运行后会输出错误视频信息和丢失帧数量,如:dup=773
5. 默认开启 N 卡的 cuda 硬件加速,提升解码筛选速度,我这里的筛选速度是视频时长的十几倍,你可以先找个比较长的视频测试下硬解( ffmpeg -v 8 -stats -hwaccel cuda -i [input] -fps_mode cfr -f null -)和软解( ffmpeg -v 8 -stats -i [input] -fps_mode cfr -f null -)哪个快一点
acreti
2022-09-03 23:41:40 +08:00
@acreti 写错了“速度是视频时长的十几倍”,应为“所需时间是视频时长的十几分之一”
1054850490
2022-09-04 16:03:31 +08:00
@acreti 请稍等哈,我还在做更多的实验来验证这个可行性
acreti
2022-09-04 17:19:30 +08:00
@1054850490 过程中有什么问题,随时问我。毕竟每个人的运行环境都不一样,我这里运行正常。这是我能找到的最快的筛选方案了,而 FFprobe 数帧数量的方法要花费大概 4 倍时间。
1054850490
2022-09-04 22:54:52 +08:00
@acreti 有个疑问,如果视频本身就是缺帧的,我怎么知道他原本的多少帧的?难道帧数在视频里本身就有记录?然后用 ffmpeg 去遍历帧的看有没有帧错误
acreti
2022-09-05 01:25:06 +08:00
@1054850490 原本多少帧,要对比完好无损的原视频。类似于一把梳子,缺了几个针,但基座还在,就是丢帧。帧数量不记录,帧数 FPS 会记录。没有帧错误这么一说,解码 B 帧时要参考后面的帧,但后面的时间戳上没有对应的视频帧,所以解码到此处时出现画面错误,既然后面时间戳上没有视频帧,就会一直显示这个错误画面。不太会解释,不知道你看懂了没有,可以先 Google 一下 I 、P 、B 帧是什么。
ungrown
2022-09-05 09:45:48 +08:00
@acreti #18 我印象里,ffmpeg 在转码这种损坏的视频时,日志输出里面会有带颜色的警告消息,提示哪里哪里有问题。
但是我印象不深,因为我遇到的这类情况,数量极少,时间久远。
但如果确实如此的话,就可以通过从输出日志里搜索关键词来进行判断。
ungrown
2022-09-05 11:33:09 +08:00
@1054850490 #10 细节处理肯定不会通用的,但正确的思路、模式是能够泛用的。我实践了一下,发现还是卓有成效的,但并不是每个有问题的视频都会输出类似的错误日志、都会输出相同的关键词,需要针对不同类型的损坏添加特征集,一遍一遍地筛查。但毫无疑问,这个过程肯定是自动化的,是比人工快得多的。

首先作为演示,我们需要一个视频作为对照组,为表诚意,当然得选择“同类型”的视频啦,好在我的收藏里是有这类视频的,虽然只有唯一一个:
[직캠_Fancam] 150520 밤비노(BAMBINO) (은솔) 댄스공연 Intro @ 건양대 [nljhfXCcXlE][pharkil 2015].mp4
https://anonfiles.com/D262Hc6dy4/_Fancam_150520_BAMBINO_Intro_nljhfXCcXlE_pharkil_2015_mp4

那么,先用`ffplay -i filename`来播放它,好的,播放正常,播放过程中可以左右 seek 跳转快进快退,都没问题。不过在播放到结尾的时候,画面并没有消失,ffplay 程序也没有退出,底部状态那一行还在飞速变化,我们看看它显示的什么:
91.23 A-V: -7.910 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
91.23 是当前播放位置,其实已经是视频结束了,这个视频就这么长,所以这个数值尽管在跳动,但其实不变了。
A-V 这个数值,看字面意思,莫非是音频轨和视频轨之间的差值?好像是这样的,播放过程中,这个值是一个在 0 附近跳动的微小数值,体现了音画之间的同步差值。但等到播放结束之后,音频肯定停了,但画面还在跑(虽然只有黑屏),于是这个值开始在负轴上一路狂奔,朝着负无穷勇往直前。
这个时候,如果再按右键进行快进,那么自然是“异常”的,虽然程序不会退出,但是会打印红色的错误信息“error while seeking”,嘛,说得通,毕竟后面已经没了,播放结束了。
那么,如果是加速播放呢,用命令`ffplay -i filename -vf "setpts=0.1*PTS"`,跟刚才差不多。唯一不同是,播放过程之中,A-V 就开始往负轴跑,毕竟音画不同步了,这个命令只调快了画面。顺便,setpts=0.1*PTS 按理来说应该是 10 倍速播放,但结果显然不是,只有 2 倍多一点,我不知道为什么,先不管。
那么,如果换用 ffmpeg 转码呢,自然也是没问题的,因为这个视频本身没问题嘛,所以转码过程没任何不良消息。顺便一提,我这台笔记本显卡是 RTX 3050 Ti ,30 系显卡的硬件转码真的是又好又快啊,我用 ffmpeg 自带的 nvenc 编码器,转码倍速能到 20x ,即使不缩小输出画面尺寸也能有 18x 。

好了,对照组完毕,现在来看看实验组样品。

220708 #뮤직뱅크 퇴근길 #비비지 #VIVIZ (#은하 #신비 #엄지) Fancam-宽度 1920-码率 4445.735-编码 avc1.640028-频道名(전람회)-网页地址 olOzlESoEh0.[origin].mkv
出门口的这个视频。
这个视频问题明显,所以输出日志中的错误消息也很明显,一大串的类似下面截取的消息:
[NULL @ 000002e318718d40] missing picture in access unit with size 276
[h264 @ 000002e318771000] Invalid NAL unit size (0 > 5688).
[h264 @ 000002e318771000] Error splitting the input into NAL units.
[NULL @ 000002e318718d40] Invalid NAL unit size (0 > 36089).
[NULL @ 000002e318718d40] missing picture in access unit with size 36093
[h264 @ 000002e3187aec00] Invalid NAL unit size (0 > 7954).
[h264 @ 000002e3187aec00] Error splitting the input into NAL units.
[NULL @ 000002e318718d40] Invalid NAL unit size (0 > 5930).
[NULL @ 000002e318718d40] missing picture in access unit with size 5934
[h264 @ 000002e3187af0c0] Invalid NAL unit size (0 > 21100).
[h264 @ 000002e3187af0c0] Error splitting the input into NAL units.
[NULL @ 000002e318718d40] Invalid NAL unit size (0 > 19469).
[NULL @ 000002e318718d40] missing picture in access unit with size 19473
真的是一大串,不停地刷屏。你看,这种特征明显,关键字固定的错误最好找了对不对? ffplay 和 ffmpeg 跑都是这样的错误,好了,这个类型的损坏视频算是搞定了。

우주소녀 루다 부탁해-宽度 720-码率 897.992-编码 vp9-频道名(지구젤리)-网页地址 flh-q3MpgVg.[origin].mkv
舞台上白色短裙的这个视频。
这个视频特征不明显。ffmpeg 转码(目标容器格式维持原格式,mkv )的时候,一共蹦出来三行警告:
[matroska @ 000001745e3eae40] Invalid DTS: 15100 PTS: 10133 in output stream 0:0, replacing by guess
[matroska @ 000001745e3eae40] Invalid DTS: 25233 PTS: 17700 in output stream 0:0, replacing by guess
[matroska @ 000001745e3eae40] Invalid DTS: 45500 PTS: 35267 in output stream 0:0, replacing by guess
但如果转成 mp4 的话,则完全没提示任何错误警告,仿佛没事一样。
那么如果用 ffplay 来播放呢,也没输出错误警告。
好吧,这种缺帧的视频我们就认怂换个思路,老老实实比对实际帧数和理论帧数吧。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/876873

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX