如何使用mkvmerge和外部时间码强制进行A / V同步?

时间:2017-04-12 02:46:38

标签: audio video ffmpeg video-encoding mkv

背景

我正在开发一个项目,其中视频和音频是MKV源文件的算法解释,我使用ffmpeg -ss和-t来提取音频和视频的特定区域以分离文件。我在音频过程中使用视频中的场景变化(即视频场景变化的音频变化),因此同步至关重要。

音频为48khz,使用512个样本块。 视频是23.976fps(我也试过24)。

我将sceneChanges的帧开始按累积块存储在文件中:

blocksPerFrame = (48000 / 512) / 23.976
sceneOnsetBlock = sceneOnsetFrame*blocksPerFrame

我在音频代码中使用这些块将与每个场景关联的样本视为一组。

当我将音频和视频重新组合在一起时(目前使用ffmpeg在MKV容器中生成mp4(v)mp3(a)),音频和视频开始同步但逐渐漂移,直到最终为~35几秒钟。最糟糕的是音频延迟是非线性的!通过非线性,我的意思是,如果我将滞后与时间滞后的位置进行对比,我不会得到一条线,但是你在下面的图片中看到了这一点。由于这种非线性,我不能只是移动或缩放音频以适应视频。我无法弄清楚这种非线性增加音频延迟的原因;我已经对我的数学进行了两次和三次检查。

Cumulative lag against time

由于我知道场景变化的确切时间,我应该能够为mkvmerge生成“外部时间码”(来自上面的块)以完美地同步输出!

子问题:

  1. 这是最好的方法(除了试图弄清楚首先出了什么问题)?因为我正在使用我的视频帧 参考,如果我使用场景更改作为音频的时间码, 它会强制视频与音频匹配,反之亦然?我不太关心持续时间而不是同步。视频制作起来比较费力,所以我宁愿松开一些声音而不是一些帧。

  2. 我不清楚在时间码文件中使用什么号码。 根据mkvmerge documentation“对于视频,这是完全正确的 一帧,对于音频,这是一个特定音频类型的数据包。“ 由于我使用MP3,数据包大小是多少?理想情况下,我可以指定匹配块大小(512)的数据包大小(在音频编码器中?),以保持一致和简单。我可以用ffmpeg吗?

  3. 谢谢!

1 个答案:

答案 0 :(得分:0)

我最终在我的代码中解决了问题的原因,所以我从来不需要按照上面的想法进行操作。在与mkvmerge的作者讨论时,我确定了以下答案:

  1. 最好将视频同步到音频,因为有些播放器使用音频时间戳(时间码)作为参考,视频比播放器更容易减慢和加速。

  2. 音频没有单个数据包大小。数据包大小取决于编码器,甚至可能在流的不同部分具有不同的大小。必须从MKV头中提取每个数据包中的样本数,并使用它来计算每个数据包的持续时间以生成时间戳。