修复一个损坏的MP4文件

背景

最近打游戏都一直在录屏,用的是 shadowplay,就是GeForce experience自带的那个。

其实windows 自带的录屏更坑。

大概某天 录着录着 突然重启了,然后就得到了这个损坏的mp4文件。

然后就是接下来几乎要让人骂娘的过程。

尽管下面修复的部分描述的很少,但折腾过程 则是非常复杂的。

例如我试过 ffmpeg, mp4box, recover_MP4, Bandicam bdfix, 等等…

修复

1. 先检查一下有问题的视频

.\bin\ffprobe.exe 'share\Yuan Shen 原神 2021.02.12 - 23.05.40.05.mp4'
ffprobe version 4.3.2-2021-02-27-full_build-www.gyan.dev Copyright (c) 2007-2021 the FFmpeg developers
  built with gcc 10.2.0 (Rev6, Built by MSYS2 project)
  
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001c5bd50fc00] moov atom not found
share\Yuan Shen 原神 2021.02.12 - 23.05.40.05.mp4: Invalid data found when processing input

moov atom not found

moov atom 相当于描述 mp4 内容的一个关键信息,如果没有该信息 解码器就无法理解这个mp4容器里面到底有什么东西。

详细内容 参见:

用 untrunc 进行修复

https://github.com/anthwlock/untrunc

切记认准作者,这个是比较好用的那个。

对于 shadowplay 命令像是这样:

.\untrunc.exe -dyn .\good.mp4 .\bad.mp4

-dyn 参数非常重要。

日志输出:

PS C:\Applications\untrunc_x64> .\untrunc.exe -dyn .\22.40.50.04.mp4 .\23.05.40.05.mp4
Info: version 'b150ae5' using ffmpeg '3.3.4'
Info: reading .\22.40.50.04.mp4
Info: parsing healthy moov atom ...

Info: using dynamic stats, use '-is' to see them
Info: reading mdat from truncated file ...
Info: using 64-bit offsets for the broken file
[aac @ 0000000002805e00] Multiple frames in a packet.
[aac @ 0000000002805e00] Reserved bit set.
[aac @ 0000000002805e00] Number of bands (18) exceeds limit (14).
[aac @ 000000000280ac00] Reserved bit set.
[aac @ 000000000280ac00] Number of bands (18) exceeds limit (14).
[aac @ 0000000002805e00] Number of bands (12) exceeds limit (11).
[aac @ 000000000280ac00] Number of bands (12) exceeds limit (11).
[aac @ 0000000002805e00] Number of bands (54) exceeds limit (40).
[aac @ 000000000280ac00] Number of bands (54) exceeds limit (40).
[aac @ 0000000002805e00] Reserved bit set.
[aac @ 0000000002805e00] Number of bands (11) exceeds limit (8).
[aac @ 000000000280ac00] Reserved bit set.
[aac @ 000000000280ac00] Number of bands (11) exceeds limit (8).
[aac @ 0000000002805e00] Reserved bit set.
[aac @ 0000000002805e00] invalid band type
[aac @ 000000000280ac00] Reserved bit set.
[aac @ 000000000280ac00] invalid band type
Warning: guessed frame durations of 'mp4a' will probably be wrong!
Warning: guessed frame durations of 'avc1' will probably be wrong!
Info: Found 213773 packets ( mp4a: 65193 mp4a: 65189 avc1: 83391 avc1-keyframes: 2780 )
Info: Duration of mp4a: 23min 10s 784ms  (1390784 ms)
Info: Duration of mp4a: 23min 10s 668ms  (1390668 ms)
Info: Duration of avc1: 23min 11s 130ms  (1391130 ms)
Info: saving .\23.05.40.05.mp4_fixed-dyn.mp4
written length: 8472812002

59765 warnings were hidden!

完美修复!

DVR

但 还有一个视频有问题

之前还有一个不是使用 shadowplay 录制的 而使用的 windows 自带的DVR。

所以按照上面的方式 再次尝试发现音画不同步。

并且 输出的日志显示 长度不一样

Info: using dynamic stats, use '-is' to see them
Info: reading mdat from truncated file ...
Info: using 64-bit offsets for the broken file
[aac @ 000000000416b020] Multiple frames in a packet.
Warning: guessed frame durations of 'avc1' will probably be wrong!
Info: Found 231066 packets ( mp4a: 101403 avc1: 129663 avc1-keyframes: 4472 )
Info: Duration of mp4a: 36min 3s 264ms  (2163264 ms)
Info: Duration of avc1: 36min 15s 193ms  (2175193 ms)
Warning: Unknown sequences: 1
Warning: Bytes NOT matched: 8B (7.938e-008%)
Info: saving .\20-38-32.mp4_fixed-dyn.mp4
written length: 10077596492

仔细看了一番 最终发现是 游戏 drop 的帧 DVR 录出来也会 DROP?

算了一下 大概 drop 了 700 多帧 并且回放视频的时候 确实有很多地方都在卡顿,而且还有的地方帧不在正确的时间轴上。

所以 这段视频 拯救的不是非常完美,解决办法只有在剪辑的时候 手动对齐音轨。

还有就是DVR录制的音频有极大问题 ,在其他视频中 有部分音频损坏。

印度阿三写代码就满天bug呗??

TIPS

关于录制

我建议你尽量使用 shadowplay 去录,避免因为 CPU负载高,或其他软件bug 造成的画面和音频损失。

shadowplay 则是有专用的 NVENC编码器 和 其他专用的硬件单元来几乎无损失性能的录制,你可以将画质调很高 码率 >= 50M 这样很难出现画质损失了。

关于其他工具

1. Bandicam bdfix

如果你是用 Bandicam 录屏的,你就可以直接用 自带的bdfix来进行修复,在早期的时候 提供 .avi 修复,在更新的版本中 加入了.mp4 修复的支持。

不过仅能修复 Bandicam 录制的视频。

2. recover_MP4

https://restore.media/blog/how-to-fix-corrupted-mp4-files

如果你是 使用相机录制的,你就可以使用这个了。它的优势就在于恢复专用录像设备的媒体格式。

比如blackmagic,go pro,DJI 等等。因为模板是和设备绑定的。所以它并不适合录屏工具。

上面的链接是官网的指引文档。