Hai, saya perlu mengekstrak bingkai dari video menggunakan ffmpeg .. Apakah ada cara yang lebih cepat untuk melakukannya daripada ini:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Hai, saya perlu mengekstrak bingkai dari video menggunakan ffmpeg .. Apakah ada cara yang lebih cepat untuk melakukannya daripada ini:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Jawaban:
Jika langkah pengkodean JPEG terlalu intensif kinerja, Anda selalu dapat menyimpan bingkai yang tidak dikompresi sebagai gambar BMP:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Ini juga memiliki keuntungan karena tidak menimbulkan lebih banyak kehilangan kualitas melalui kuantisasi dengan melakukan transcoding ke JPEG. (PNG juga lossless tetapi cenderung membutuhkan waktu lebih lama daripada JPEG untuk dienkode.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, kan? (Anda kehilangan -i
)
Menemukan pertanyaan ini, jadi inilah perbandingan singkatnya. Bandingkan dua cara berbeda ini untuk mengekstrak satu frame per menit dari video berdurasi 38m07s:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029s
Ini membutuhkan waktu lama karena ffmpeg mem-parsing seluruh file video untuk mendapatkan frame yang diinginkan.
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
Ini sekitar 20 kali lebih cepat. Kami menggunakan pencarian cepat untuk membuka indeks waktu yang diinginkan dan mengekstrak bingkai, lalu memanggil ffmpeg beberapa kali untuk setiap indeks waktu. Perhatikan bahwa -accurate_seek
ini adalah default
, dan pastikan Anda menambahkan -ss
sebelum opsi input video -i
.
Perhatikan bahwa lebih baik menggunakan -filter:v -fps=fps=...
daripada -r
karena yang terakhir mungkin tidak akurat. Meskipun tiket ditandai sebagai sudah diperbaiki , saya masih mengalami beberapa masalah, jadi lebih baik bermain aman.
bc
bukan paket Ubuntu asli, bukan satu dapat menggunakan bash: let "i = $i * 60"
. BTW - ide bagus
-ss
sebelumnya -i
. Jika tidak, seluruh video akan didekodekan dan bingkai yang tidak diperlukan akan dibuang
ffmpeg
per inti host Anda - yang (untuk bmp) menghasilkan peningkatan kecepatan yang hampir linier (sampai Anda mencapai beberapa hambatan lain, seperti disk).
Jika Anda tahu persis frame mana yang akan diekstrak, misalnya 1, 200, 400, 600, 800, 1000, coba gunakan:
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
Saya menggunakan ini dengan pipa ke montase Imagemagick untuk mendapatkan pratinjau 10 bingkai dari video mana pun. Jelas nomor bingkai yang perlu Anda ketahui menggunakanffprobe
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
.
Sedikit penjelasan:
+
singkatan dari OR dan*
AND\,
hanya keluar dari ,
karakter-vsync vfr -q:v 2
itu sepertinya tidak berhasil tetapi saya tidak tahu mengapa - siapa?Saya mencobanya. 3600 bingkai dalam 32 detik. metode Anda sangat lambat. Anda harus mencobanya.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
mana URL masukan harus berupa tautan https.
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Dalam kasus saya, saya membutuhkan bingkai setidaknya setiap detik. Saya menggunakan pendekatan 'mencari' di atas tetapi bertanya-tanya apakah saya bisa memparalelkan tugas tersebut. Saya menggunakan proses N dengan pendekatan FIFO di sini: /unix/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
Pada dasarnya saya membagi proses dengan & tetapi membatasi jumlah utas bersamaan ke N.
Ini meningkatkan pendekatan 'seek to' dari 26 detik menjadi 16 detik dalam kasus saya. Satu-satunya masalah adalah utas utama tidak keluar dengan bersih kembali ke terminal karena stdout dibanjiri.
Ini berhasil untuk saya
ffmpeg -i file.mp4 -vf fps=1 %d.jpg