使用 FFmpeg 每 N 秒准确提取帧

Mob*_*oba 6 video ffmpeg cuda

用法

\n

我使用从视频中提取图像ffmpeg

\n

我每 10 秒(含 10 秒)转储一张缩小的图像,并将其组合成蒙太奇imagemagick。当将滑块悬停在基于网络的视频播放器中时,这些蒙太奇再次用于显示视频预览。(计算要显示蒙太奇中的哪个图像)。

\n

命令

\n

经过尝试后,我最终得到了以下命令,其中的想法是速度而不是质量:

\n
ffmpeg \\\n    -loglevel error \\\n    -hwaccel cuvid \\\n    -hwaccel_output_format cuda \\\n    -c:v h264_cuvid \\\n    -i "$video_file" \\\n    -r 0.1 \\\n    -filter:v "scale_cuda=w=-1:h=100,thumbnail_cuda=2,hwdownload,format=nv12" \\\n    -color_range 2 \\\n    f%09d.jpg\n
Run Code Online (Sandbox Code Playgroud)\n

这看起来效果很好。镜头有时会落后 \xc2\xb1 0.5 - 1 秒,但还算可以接受。

\n

问题

\n

问题是ffmpeg在视频开始时会产生一张额外的图像。例如文件是:

\n
file             time\nf000000001.jpg   00:00:00\nf000000002.jpg   00:00:00\nf000000003.jpg   00:00:10\nf000000004.jpg   00:00:20\nf000000005.jpg   00:00:30\n...\n
Run Code Online (Sandbox Code Playgroud)\n

有时第一和第二会相差几毫秒。

\n

据我所知(现在)我可以简单地删除第一个图像并继续处理其余图像,但不确定为什么会发生这种情况以及它是否是错误或其他原因。

\n

换句话说:我需要知道前两个帧的“效果”是否可靠,以便我ffmpeg也可以在其他版本中删除它。

\n

当我使用图像来显示 10 秒时。如果我不删除生成的第一张图像,则指定时间的视频快照会关闭 10 秒。如果由于某种原因它不应该在开始时创建重复项、其他版本或其他任何内容,则删除第一个图像会产生相同的问题。

\n

剪辑

\n

(如果感兴趣的话,蒙太奇的创建方式类似于):

\n
montage -tile 5x -geometry +0+0 -background none [file1  - file50 ]  montage01.jpg\nmontage -tile 5x -geometry +0+0 -background none [file51 - file100]  montage02.jpg\n...\n
Run Code Online (Sandbox Code Playgroud)\n
\n

我现在根据答案使用的命令(shell):

\n
file             time\nf000000001.jpg   00:00:00\nf000000002.jpg   00:00:00\nf000000003.jpg   00:00:10\nf000000004.jpg   00:00:20\nf000000005.jpg   00:00:30\n...\n
Run Code Online (Sandbox Code Playgroud)\n

Rot*_*tem 3

使用-r 0.1将输出帧速率设置为 0.1Hz,但不能保证每 10 秒从输入视频中获取帧(我不确定为什么)。

解决该问题的一种方法是使用select filter

示例(没有 GPU 加速):

ffmpeg -i input.mp4 -vf "select=bitor(gte(t-prev_selected_t\,10)\,isnan(prev_selected_t))" -vsync 0 f%09d.jpg
Run Code Online (Sandbox Code Playgroud)
  • bitor(gte(t-prev_selected_t\,10)1指“通过的”时间戳之间的差异大于等于 10 秒。
    当表达式计算为 时1,框架被“选择”并传递到输出。
  • bitorwithisnan(prev_selected_t)传递第一帧,其中prev_selected_tNaN(没有值)。
  • -vsync 0应用“直通” - 每个帧及其时间戳从解复用器传递到复用器。

这是一个带有scale_cuda和的示例thumbnail_cuda

ffmpeg \
    -loglevel error \
    -hwaccel cuvid \
    -hwaccel_output_format cuda \
    -c:v h264_cuvid \
    -i "$video_file" \
    -filter:v "scale_cuda=w=-1:h=100,thumbnail_cuda=2,hwdownload,format=nv12,select=bitor(gte(t-prev_selected_t\,10)\,isnan(prev_selected_t))" \
    -vsync 0 \
    -color_range 2 \
    f%09d.jpg   
Run Code Online (Sandbox Code Playgroud)
  • 由于需要使用thumbnail_cuda过滤器,所以我们必须将select过滤器放在最后。

测试:
以 10fps 的帧计数器构建合成视频:

ffmpeg -y -f lavfi -r 10 -i testsrc=size=128x72:rate=1:duration=1000 -vf setpts=N/10/TB -vcodec libx264 -pix_fmt yuv420p input.mp4
Run Code Online (Sandbox Code Playgroud)

执行上述命令后输出帧:

在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述
在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述 在此输入图像描述

正如您所看到的,所选帧恰好是每 10 秒一次。