FFMPEG:如何从可变长度的视频(包括第一帧和最后一帧)中选择 X 个间隔均匀的帧

FFMPEG:如何从可变长度的视频(包括第一帧和最后一帧)中选择 X 个间隔均匀的帧

我需要从“漫游”视频中提取给定数量的均匀分布的屏幕截图,确保包含第一帧和最后一帧。

我尝试过使用 -r 和 select="mod" 但计算结果总是有一点点偏差,以至于要么跳过最后一帧,要么得到比最后一帧早一点的结果(十进制舍入)。

如果我知道持续时间和帧速率,有什么方法可以将两个“在时间戳处选择帧”测试与“每 x 秒选择帧”结合起来?

谢谢!

詹姆士

答案1

这里有一个为您提供的简单的 Python 脚本...

#!/bin/env python3

import sys

def adjust(value):
  return int(int(value*10+0.5)/10)

if len(sys.argv)!=4:
  print('use:',sys.argv[0],' start stop steps',
        '\nPrints values evenly spread over the range from start to stop'
        )
  exit(1)

a, b, steps =sys.argv[1:]

a=float(a); b=float(b); steps=float(steps)
rnge=(b-a); stepval=(rnge/steps)

values=[ adjust(b) ]
value=a
while value < b:
  values.append( adjust(value) )
  value+=stepval

values=list(set(values))
values.sort()

i=1
for n in values:
  print(n,end=' ')
  i+=1
print()

...

现在安装 python,然后执行类似以下操作

$ python3 evensteps.py 10 211 3

获取均匀分布的整数,这可能是要提取的帧。

答案2

如果你想保存 - 比如说 - 25 fps 视频的第一帧、最后一帧和每 51 帧,你应该尝试:

$ ffmpeg -i <your-input> -ss 0.0 -vframes 1 -y first.png -vf fps=25/51 -y 51th_%02d.png -ss 60.0 -vframes 1 -y last.png

我使用 1501 帧长、25 fps 的视频对其进行了测试,每帧包含自己的时间码。输入视频:

$ ffmpeg -hide_banner -i ff.mkv

Input #0, matroska,webm, from 'ff.mkv':
  Metadata:
    ENCODER         : Lavf58.29.100
  Duration: 00:01:00.04, start: 0.000000, bitrate: 7989 kb/s
    Stream #0:0: Video: ffv1 (FFV1 / 0x31564646), yuv420p, 1920x1080, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      ENCODER         : Lavc58.54.100 ffv1
      DURATION        : 00:01:00.040000000

因此,第一帧的时间码应该是00:00:00:00最后应该有00:01:00:00。但是,“-vf 25/51”过滤器从第25届框架00:00:01:00视频。上述命令共输出 31 个文件,时间码如下:

  • 第一部分.png:00:00:00:00(第一帧,好)
  • 图片来源:https://www.youtube.com/watch?v=51h_01.png:00:00:01:00(应该从零开始)
  • 图片来源:https://www.youtube.com/watch?v=51h_02.png00:00:03:01(帧距可以)
  • 图片来源:https://www.youtube.com/watch?v=51h_03.png:00:00:05:02(帧距可以)
  • ...
  • 图片来源:51th_28.png:00:00:56:02(帧距可以)
  • 图片来源:51th_29.png:00:00:58:03(帧距可以)
  • 最后.png:00:01:00:00(最后一帧,好)

希望有所帮助。

相关内容