![](/img/trans.png)
[英]Fastest way to extract a specific frame from a video (PHP/ffmpeg/anything)
[英]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
.
小解釋:
+
代表 OR 和*
代表 AND\\,
只是逃避,
字符-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
我嘗試過這個。 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.