![使用 FFmpeg 每 N 秒準確擷取幀](https://rvso.com/image/1672321/%E4%BD%BF%E7%94%A8%20FFmpeg%20%E6%AF%8F%20N%20%E7%A7%92%E6%BA%96%E7%A2%BA%E6%93%B7%E5%8F%96%E5%B9%80.png)
用法
我使用從視頻中提取圖像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
,框架被「選擇」並傳遞到輸出。bitor
withisnan(prev_selected_t)
傳遞第一幀,其中prev_selected_t
是NaN
(沒有值)。-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 秒一次。