FFMPEG 精确叠加

FFMPEG 精确叠加

让我们直入主题,我在使用 ffmpeg 的叠加功能时遇到了问题。我有两个视频。一个是 2865 帧,第二个也是 2865 帧。两者的帧率都是 30000/1001 fps。在叠加之前,我已经检查了它们的时间戳,并将其记录到一个文件中,如果我有声誉的话,我会将这个文件作为图像叠加到我的帖子中,所以现在你只需要相信我说的都是实话,它们的时间戳完全相同。

现在,尽管视频帧速率匹配,但该命令的结果如下:

"ffmpeg", "-i", fmt.Sprintf("%s%s", CCME.PathsToUse[0], CCME.UnderlayVideo),
                   "-i", fmt.Sprintf("%s%s", CCME.PathsToUse[1], CCME.VideoName), 
                   "-filter_complex", "overlay=0:0", "-vsync", "0", "-crf", "18", "-y", "-shortest", "-strict", "-2",
                   fmt.Sprintf("%s%s.%s", CCME.PathsToUse[2], CCME.FinalVideoName, CCME.VidFormat

结果是在视频末尾添加了两个额外的帧,这没什么问题,因为我可以排除或删除添加到末尾的额外帧。但是,在进行分析时,会弹出以下警告:

Frame 770: Repeated

Frame 1500: Repeated

Frame 2276: Repeated

Missing Or Mangled Frame(s) After Frame 2591

QR DATA: 2593

3 frames repeated and or added.

似乎尽管使用了精确的帧速率、帧编号和时间戳,ffmpeg 仍然很难以将每个帧与另一个视频的相应帧对齐的方式叠加视频。为了完成这个项目,我需要绝对准确地对齐这些帧,但我做不到这一点。我已经绞尽脑汁想了两个星期,但还是想不出为什么会发生这种情况,或者我可以使用哪些其他选项来防止帧重复、丢失和在视频末尾添加帧。

有谁知道为什么会发生这种情况,上面的命令中缺少什么,或者可以添加什么来使这些视频对齐或防止重复和丢帧?据我所知,这种情况不应该发生,但似乎我到目前为止所做的一切都无法解决这个问题。

答案1

您的两个文件不具有相同的帧速率或持续时间。但如果您确定主视频的帧速率是恒定的,则可以为两个视频流生成新的平滑时间戳,然后执行叠加。

ffmpeg -i main.mp4 -i overlay -filter_complex
    "[0]setpts=1001*N/30000/TB[m];
     [1]setpts=1001*N/30000/TB[o];
     [m][o]overlay=shortest=1"
 -crf 18 out.mp4

答案2

当 Gyan 得到答案时,我会讲讲我是如何让它发挥作用的。

由于我自己能够匹配电影的精确持续时间和帧速率,从而获得两个视频的完美叠加的可能性在最好的情况下也几乎为零,在最坏的情况下则是不可能的,所以我决定采取另一种方法。

通过将目标视频解构为各个帧,可以实现帧完美叠加:

exec.Command("ffmpeg", "-i", fmt.Sprintf("%s%s", CCME.PathsToUse[0], CCME.UnderlayVideo),
                             "-start_number", "0", "-qscale:v", "2", fmt.Sprintf("%s%s%%d.jpg", TempDirPath[0], VideoName))

单独叠加框架:

for x:=0; x<len(files)-2; x++ {
    overlayFile := exec.Command("ffmpeg", "-i", fmt.Sprintf("%s%s%d.jpg", TempDirPath[0], VideoName, x),
                                "-i", fmt.Sprintf("%s%s%d.png", CCME.PathsToUse[1], CCME.VideoName, x),
                                "-filter_complex", "overlay", "-y", fmt.Sprintf("%s%s%d.jpg", TempDirPath[1], VideoName, x))

(注意:大多数情况下不需要 -2。执行此操作的 TempDir 包含需要考虑的子目录和音频文件。)

然后根据帧速率和视频类型重建视频,通过解析 ffmpeg -i 文件的输出来获取:

cmdConstruct := exec.Command("ffmpeg", "-framerate", AudioFS[1], "-i", fmt.Sprintf("%s%s%%d.jpg", TempDirPath[1], VideoName),
                            "-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-y",
                            "-vsync", "0", "-strict", "-2", fmt.Sprintf("%s%s.%s", CCME.PathsToUse[2], CCME.FinalVideoName, VideoFormat))

使用此方法时还需要重新添加音频。就我而言,只需从主文件中提取音频并将其混合到新视频上即可。

相关内容