Yanıtlar:
JPEG kodlama adımı çok yüksek performans gerektiriyorsa, sıkıştırılmamış kareleri her zaman BMP görüntüleri olarak saklayabilirsiniz:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Bu aynı zamanda, JPEG'ye kod dönüştürme yoluyla niceleme yoluyla daha fazla kalite kaybına uğramama avantajına sahiptir. (PNG ayrıca kayıpsızdır ancak kodlanması JPEG'den çok daha uzun sürer.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
değil mi? (kaçırıyordunuz -i
)
Bu soruyla karşılaştık, işte hızlı bir karşılaştırma. 38m07s uzunluğundaki bir videodan dakikada bir kare çıkarmak için bu iki farklı yolu karşılaştırın:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029s
Bu uzun sürer çünkü ffmpeg istenen kareleri elde etmek için tüm video dosyasını ayrıştırır.
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
Bu yaklaşık 20 kat daha hızlı. İstenilen zaman indeksine gitmek ve bir çerçeve çıkarmak için hızlı aramayı kullanırız, ardından her zaman indeksi için birkaç kez ffmpeg çağırırız. Bunun -accurate_seek
varsayılan olduğunu
ve -ss
video giriş -i
seçeneğinden önce eklediğinizden emin olun .
Kullanımı daha iyi olduğunu Not -filter:v -fps=fps=...
yerine -r
olarak ikincisi hatalı olabilir. Bilet düzeltildi olarak işaretlenmiş olsa da , yine de bazı sorunlar yaşadım, bu yüzden güvenli oynamalıyım.
bc
yerel bir Ubuntu paketi değildir, bunun yerine bash: kullanılabilir let "i = $i * 60"
. BTW - excellent idea
-ss
Önceden iyi bir ipucu eklemek -i
. Aksi takdirde, tüm videonun kodu çözülecek ve gerekli olmayan kareler atılacak
ffmpeg
, ana makinenizin çekirdeği başına bir tane çalışıyor gibi görünüyor - bu (bmp için) hızda neredeyse doğrusal iyileştirmeler sağlıyor (disk gibi başka bir darboğazla karşılaşana kadar).
Tam olarak hangi karelerin çıkarılacağını biliyorsanız, örneğin 1, 200, 400, 600, 800, 1000, kullanmayı deneyin:
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
Bunu, herhangi bir videodan 10 kare önizleme almak için Imagemagick'in montajına giden bir boru ile kullanıyorum. Açıkçası kullanarak çözmeniz gereken çerçeve numaraları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
.
Küçük açıklama:
+
OR ve *
AND anlamına gelir\,
sadece ,
karakterden kaçıyor-vsync vfr -q:v 2
işe yaramıyor gibi görünüyor ama nedenini bilmiyorum - kimse?Denedim. 32 saniyede 3600 kare. yönteminiz gerçekten yavaş. Bunu denemelisin.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
Giriş URL'sinin bir https bağlantısı olması gereken yerde deniyorum .
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Benim durumumda en azından her saniye çerçevelere ihtiyacım var. Yukarıdaki 'aramak' yaklaşımını kullandım ama görevi paralelleştirip paralelleştiremeyeceğimi merak ettim. Burada FIFO yaklaşımıyla N işlemlerini kullandım: /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
Esasen süreci çatalladım ve eşzamanlı iş parçacığı sayısını N ile sınırladım.
Bu, benim durumumda 'arama' yaklaşımını 26 saniyeden 16 saniyeye çıkardı. Tek sorun, stdout taşındığı için ana iş parçacığının terminale temiz bir şekilde geri çıkmamasıdır.
Bu benim için çalıştı
ffmpeg -i file.mp4 -vf fps=1 %d.jpg