簡體   English   中英

使用ffmpeg提取幀的最快方法?

[英]Fastest way to extract frames using ffmpeg?

嗨,我需要使用 ffmpeg 從視頻中提取幀.. 有沒有比這更快的方法:

ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg

?

如果 JPEG 編碼步驟的性能過於密集,您始終可以將未壓縮的幀存儲為 BMP 圖像:

ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp

這還具有通過轉碼為 JPEG 進行量化不會導致更多質量損失的優點。 (PNG 也是無損的,但編碼時間往往比 JPEG 長得多。)

遇到了這個問題,所以這里有一個快速比較。 比較這兩種從 38 分 07 秒長的視頻中每分鍾提取一幀的不同方法:

time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp

1m36.029s

這需要很長時間,因為 ffmpeg 解析整個視頻文件以獲得所需的幀。

time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4   -frames:v 1 period_down_$i.bmp ; done

0m4.689s

這大約快 20 倍。 我們使用快速搜索到所需的時間索引並提取一幀,然后為每個時間索引調用多次 ffmpeg。 請注意-accurate_seek是默認值,並確保在輸入視頻-i選項之前添加-ss

請注意,最好使用-filter:v -fps=fps=...而不是-r因為后者可能不准確。 雖然票被標記為 fixed ,但我仍然遇到了一些問題,所以最好安全一點。

如果您確切知道要提取哪些幀,例如 1、200、400、600、800、1000,請嘗試使用:

select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
       -vsync vfr -q:v 2

我將它與 Imagemagick 蒙太奇的管道一起使用,以便從任何視頻中獲得 10 幀預覽。 顯然,您需要使用ffprobe找出ffprobe

ffmpeg -i myVideo.mov -vf \
    select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',scale=320:-1 \
    -vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
  | montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png

.

小解釋:

  1. 在 ffmpeg 表達式中+代表 OR 和*代表 AND
  2. \\,只是逃避,字符
  3. 沒有-vsync vfr -q:v 2它似乎不起作用,但我不知道為什么 - 有人嗎?

每分鍾輸出一張圖像,命名為 img001.jpg、img002.jpg、img003.jpg 等。 %03d 指示每個輸出圖像的序號將使用 3 位數字進行格式化。

ffmpeg -i myvideo.avi -vf fps=1/60 img%03d.jpg

fps=1/60更改為fps=1/30以每 30 秒捕獲一次圖像。 同樣,如果您想每 5 秒捕獲一次圖像,則將fps=1/60更改為fps=1/5

來源: https://trac.ffmpeg.org/wiki/每 X 秒創建一個視頻縮略圖

我嘗試過這個。 32 秒 3600 幀。 你的方法真的很慢。 你應該試試這個。

ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg

這對我有用

ffmpeg -i file.mp4 -vf fps=1 %d.jpg

到目前為止,這比所有其他命令都簡單:

ffmpeg -i input.mp4 '%04d.png'

04更改為保存所有幀所需的位數。

就我而言,我至少每秒都需要幀。 我使用了上面的“尋求”方法,但想知道我是否可以並行化任務。 我在這里使用了帶有 FIFO 方法的 N 個進程: https : //unix.stackexchange.com/questions/103920/parallelize-a-bash-for-loop/216475#216475

open_sem(){
  mkfifo /tmp/pipe-$$
  exec 3<>/tmp/pipe-$$
  rm /tmp/pipe-$$
  local i=$1
  for((;i>0;i--)); do
    printf %s 000 >&3
  done
}
run_with_lock(){
    local x
    read -u 3 -n 3 x && ((0==x)) || exit $x
    (
    "$@" 
    printf '%.3d' $? >&3
    )&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4  -frames:v 1 /tmp/output/period_down_$i.jpg  & done

本質上,我使用 & 對進程進行了分叉,但將並發線程數限制為 N。

在我的情況下,這將“尋求”方法從 26 秒改進為 16 秒。 唯一的問題是主線程沒有干凈地退出回終端,因為 stdout 被淹沒了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM