场景检测和连拍使我的视频更长(FFMPEG)

时间:2019-03-29 18:44:55

标签: ffmpeg video-encoding

我正在按场景对视频进行编码。目前,我有两种解决方案。第一个是使用Python应用程序,它为我提供了代表场景的帧列表。像这样:

285
378
553
1145
...

第一个场景从帧1到285,第二个场景从285到378,依此类推。因此,我制作了一个bash脚本来对所有这些场景进行编码。基本上,它的工作是获取当前帧和先前帧,然后将它们转换为时间,最后运行ffmpeg命令:

begin=$(awk 'BEGIN{ print "'$previous'"/"'24'" }') 
end=$(awk 'BEGIN{ print "'$current'"/"'24'" }') 
time=$(awk 'BEGIN{ print "'$end'"-"'$begin'" }') 

ffmpeg -i $video -r 24 -c:v libx265  -f mp4 -c:a aac -strict experimental -b:v 1.5M -ss $begin -t $time "output$count.mp4" -nostdin

这很完美。第二种方法是使用ffmpeg本身。我运行此命令,并提供了的列表。像这样:

15.75
23.0417
56.0833
71.2917
...

我再次制作了一个bash脚本,对所有这些时间进行编码。在这种情况下,我不必转换为时间,因为我得到的就是时间:

time=$(awk 'BEGIN{ print "'$current'"-"'$previous'" }') 
ffmpeg -i $video -r 24 -c:v libx265  -f mp4 -c:a aac -strict experimental -b:v 1.5M -ss $previous -t $time "output$count.mp4" -nostdin

在所有这些解释之后,问题就来了。对所有场景进行编码后,我需要对它们进行合并,为此,我要做的是创建一个包含视频名称的列表,然后运行ffmpeg命令。

list.txt

file 'output1.mp4'
file 'output2.mp4'
file 'output3.mp4'
file 'output4.mp4'

命令:

ffmpeg -f concat -i list.txt -c copy big_buck_bunny.mp4

问题在于,“连接的”视频比原始视频长2.11秒。原始的持续596.45秒,编码的持续598.56秒。我将每个视频时长加起来,得出598.56。因此,我认为问题出在编码过程中。两个视频具有相同的帧号。我的目标是获取有关编码过程的指标,当我运行VQMT以获得PSNR和SSIM时,我得到了奇怪的结果,我认为是针对此问题的。

顺便说一句,我正在使用big_buck_bunny视频。

2 个答案:

答案 0 :(得分:1)

可能的差异归因于copy编解码器。在后一种情况下,您告诉ffmpeg复制段,但是根据您的输入时间,它无法做到这一点。 它必须先找到先前的I帧(无需参考任何先前的帧即可解码的帧),然后从此处开始。

要获得所需的内容,您需要重新编码视频(就像您在前面两个示例中所做的一样),或者更改停止在I帧处的时间。

断言我正确地解决了您的问题:

  1. 您有一个源视频(以可变帧频编码,接近18fps)
  2. 您要通过将帧频强制设置为24 fps,来通过ffmpeg分割源视频。
  3. 然后要合并每个段。

我认为问题主要在于您在时间安排上存在一些差异(如果将帧索引除以给定的时间,则我得到的是16fps至18fps)。在步骤2中进行转换时,输出视频片段时间将为24fps。 ffmpeg不会在时间轴上重新采样,因此如果您强制使用视频速率,则视频将加速或减速。 流还存在一致性问题: 通常,视频流必须以I帧开始,因此,在分割时,FFMPEG必须定位先前的I帧(使用copy编解码器时,这会更改段的持续时间)。

在连接时,还可能存在一致性问题(即,如果要连接的段确实以I帧结尾,而下一个以I帧开头,则FFMPEG可能会丢弃其中一个,虽然我不记得现在的行为是什么)

因此,要解决您的问题,如果我是您,我将避免执行第2步(无论如何对质量都是不利的)。也就是说,我将使用ffmpeg根据png或ppm帧中的帧号(这是您的方案中唯一不是近似的唯一值)(或如果不包含的话,将其分割为管道)来分割感兴趣的段不在乎保留它们),然后通过在最后一步以预期速率设置为totalVideoTime / totalFrameCount对其进行编码来合并所有帧。

您将获得更小,更高质量的最终视频。

如果出于某种原因(至少对于concat输入)无法执行我说的内容,则应使用ffconcat格式:

ffconcat version 1.0
file segment1
duration 12.2
file segment2
duration 10.3

如果每个片段较长,则会缩短预期的持续时间

要按帧号进行选择(而不是时间,因为很难在可变帧速视频上获得正确的时间),应使用select过滤器,如下所示:

-vf select=“between(n\,start_frame_num\,end_frame_num),setpts=STARTPTS"

答案 1 :(得分:0)

我建议检查输入和输出帧速率,并确保它们匹配。这可能是差异的原因。