使用 FFmpeg 每 N 秒準確擷取幀

使用 FFmpeg 每 N 秒準確擷取幀

用法

我使用從視頻中提取圖像ffmpeg

我每 10 秒(含 10 秒)轉儲一張縮小的圖像,然後將其組合成蒙太奇imagemagick。當將滑桿懸停在基於網路的視訊播放器中時,這些蒙太奇再次用於顯示視訊預覽。 (計算要顯示蒙太奇中的哪個圖像)。

命令

經過嘗試後,我最終得到了以下命令,其中的想法是速度而不是品質:

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

這看起來效果很好。鏡頭有時會有 ± 0.5 - 1 秒的偏差,但這還算可以接受。

問題

問題是ffmpeg在影片開始時會產生額外的圖像。例如文件是:

file             time
f000000001.jpg   00:00:00
f000000002.jpg   00:00:00
f000000003.jpg   00:00:10
f000000004.jpg   00:00:20
f000000005.jpg   00:00:30
...

有時第一和第二會相差幾毫秒。

據我所知(現在)我可以簡單地刪除第一個圖像並繼續處理其餘圖像,但不確定為什麼會發生這種情況以及它是否是錯誤或其他原因。

換句話說:我需要知道前兩個幀的「效果」是否是可靠的這樣我ffmpeg也可以在其他版本中刪除它。

當我使用圖像來顯示 10 秒時。指定時間的影片快照關閉了 10 秒如果我不刪除生成的第一張圖像。如果出於某種原因應該那麼不是在開始時建立一個副本,其他版本或其他任何內容,刪除第一個圖像會產生相同的問題。

剪輯

(如果有興趣的話,蒙太奇的創建方式類似於):

montage -tile 5x -geometry +0+0 -background none [file1  - file50 ]  montage01.jpg
montage -tile 5x -geometry +0+0 -background none [file51 - file100]  montage02.jpg
...

我現在根據答案使用的命令(shell):

# Set on call or global:
file_in=sample.mp4
pix_fmt=yuvj420p
sec_snap_interval=10
nr_start=1
pfx_out=snap


ffmpeg \
    -loglevel warning \
    -hwaccel cuvid \
    -hwaccel_output_format cuda \
    -c:v h264_cuvid \
    -i "$file_in" \
    -pix_fmt "$pix_fmt" \
    -filter:v "
        scale_cuda=
            w = -1 :
            h = 100,
        thumbnail_cuda = 2,
        hwdownload,
        format = nv12,
        select = 'bitor(
            gte(t - prev_selected_t, $sec_snap_interval),
            isnan(prev_selected_t)
        )'
    " \
    -vsync passthrough \
    -color_range 2 \
    -start_number "$nr_start" \
    "$pfx_out%09d.jpg"

答案1

使用-r 0.1將輸出幀速率設定為 0.1Hz,但不能保證每 10 秒從輸入影片中取得幀(我不確定為什麼)。

解決這個問題的一種方法是使用選擇過濾器

範例(沒有 GPU 加速):

ffmpeg -i input.mp4 -vf "select=bitor(gte(t-prev_selected_t\,10)\,isnan(prev_selected_t))" -vsync 0 f%09d.jpg

  • 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   
  • 由於需要使用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

執行上述指令後輸出幀:

在此輸入影像描述在此輸入影像描述在此輸入影像描述在此輸入影像描述在此輸入影像描述
在此輸入影像描述在此輸入影像描述在此輸入影像描述在此輸入影像描述在此輸入影像描述

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

相關內容