解决视频合并后无法拖动进度条的问题

问题发现

小米手机自带的相机录视频最多只能八分多钟一段,然后就会强制结束录制,得每次再手动点击录制,十分麻烦,且中断后衔接会不流畅。谷歌相机录像就没有这种问题,但是谷歌相机的录制实质上也是分段保存文件的,导致录上近两小时的视频会得到十多段视频片段。

因为我用的超极本剪辑压制和转档很慢,所以打算跳过渲染步骤直接把文件按封装格式合并后上传到视频网站让视频网站服务器来转档。起初打算使用小丸工具箱,打开后发现并没有合并视频片段的功能,于是在网上搜到了合并 MP4 文件的工具 MP4Joiner 。合并过程很顺畅,也和我想象的一样,没有渲染过程,在纯封装层面上进行操作的速度几乎只取决于硬盘的读写速度。合并完后我就删除了源文件,但是打开合并生成的文件后我就后悔了——前面片段正常播放,我把进度条拖到视频后段发现无法正常播放了,在 PotPlayer 中的表现就是只有进度条在走,视频画面停留在拖动前的画面,没有声音播放。并且导入 Adobe Premiere 后也无法正常拖动预览。

我以为是合并中出了问题,后面的片段都被破坏了,赶紧想恢复刚刚删除的文件,然而这对固态硬盘来说是几乎不可能的。又想可能只是文件信息部分被破坏了,就想用十六进制编辑器找文件头的方法,但总共 33G 的文件用十六进制编辑器打开寻找简直是天方夜谭,更何况查了 MP4 的封装格式之后彻底放弃,这样处理一个 MP4 文件太复杂了。

然后不死心,再次用 PotPlayer 打开,发现只要从头播放就一切正常,加速到12倍速播放,播过几个片段之后觉得没有问题,应该是合并过程中把时间索引给丢失了。网上搜了下,可能是手机拍摄视频把索引放在了文件末尾(通常应该在文件开头),合并时被舍弃造成的。

问题解决

考虑到是 MP4 封装的问题,直接抽取视频流,用小丸工具箱抽取,发现输出的视频流还是一个无法正常播放的 MP4(后来查了网上的 MP4Box 的用法,有一个地方说明的就是用 add 参数把一个 MP4 文件的视频流导出到另一个 MP4 文件里(add参数本意是用来合并音视频轨道的,可以不添加音频轨道就成这样了),我尝试之后发现导出的文件和用小丸工具箱直接导出的文件一样,都是一个帧率正常但是无法拖动进度条的MP4文件。

后来又搜到了一个工具叫 Yamb,它是一个 MP4Box 的 GUI 程序,下载安装 MP4Box 之后在 Yamb 中设置好路径然后抽取音视频流,此时抽取出的视频是 hvc 后缀的,PotPlayer 打开后发现可以正常拖动进度条了,但帧率是25fps,视频长度则从原来的1:48增长到2:10,想必是画面数据没有丢失,只是帧率被错误设置了。

原视频
抽取后的视频流

既然是 MP4Box 的 GUI 程序,打开log文件发现里面有 MP4Box 的命令,用了-raw参数,但没有帧率的设置,想必是默认25fps吧,去网上搜搜,发现 MP4Box 确实有个参数-fps可以用来设置帧率,但是命令行中使用没有效果,可能是在音视频轨道合并时用于覆盖原视频的帧率的吧,这样的话可以抽取后用-add参数再把音视频轨道合并成一个正常的 MP4 文件,或者改后缀为 hevc 后用小丸工具箱重新封装成 MP4,封装时可以直接选择正确的帧率。

不过既然已经得到了正常的视频流,直接导入 Adobe Premiere 后设置帧率(时长)再导出,顺便还能做一些剪辑效果,也不是什么难事。(PS:Adobe Premiere 无法导入hvc文件)