Hızlı bir şekilde ffmpeg ile düşük kaliteli animasyonlu GIF'leri nasıl oluştururum?


3

Kalitesi onları üretmek için harcadığı zaman kadar önemli olmayan pek çok küçük resim GIF'i üretiyoruz. Ffmpeg ile yüksek kaliteli GIF üretmek çok iyi bir şekilde kaplanmıştır, ancak düşük kaliteli olanları mümkün olduğunca çabuk nasıl üreteceğinizi bulmakta çok fazla şansım yok.

Palet hesaplama, yürütme zamanının çoğunu aşağıdaki komutla alır (burada çok zincirli süzgeç yanıtından alınmıştır: Web üzerinden bir video bölümünden en iyi palet paleti nasıl verimli bir şekilde oluşturulur ):

ffmpeg -y -threads 8 -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter_complex "fps=24,scale=150:-1:flags=fast_bilinear,split=2 [a][b]; [a] palettegen [pal] fifo [b]; [b] [pal] paletteuse" output.gif

Bu komutun 1000 kareyle yürütme süresi yaklaşık 72 saniyedir. Bunun yaklaşık 67 saniyesi palet geçişidir ve daha sonra gerçek GIF nesnesinden yaklaşık 5 saniye içinde parlar. Tüm yürütme süresini olabildiğince düşürmek ve hız için birçok görüntü kalitesini feda etmek istiyorum.


1
Komutunuz sözdizimsel olarak yanlış; Bir [b]etiket eksik . Her iki durumda da, paleti kullanmak hızlı bir testten yargılamak yaklaşık 200 is yavaştır. Hiç kullanmamak sizin için bir seçenek değil mi?
08:

@slhck Bu konuda ffmpeg docs grok için oldukça zor buluyorum, ancak paleti ortadan kaldırmak için bu geldi: ffmpeg -y -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter:v "scale=150:-1:flags=fast_bilinear" output.gifBununla ilgili iki sorun: 1) Sadece 13 saniye (72 yerine 59 saniye), ve 2 ) Bu komutun palet hesaplamasını tamamen ortadan kaldırdığından% 100 emin değilim (yalnızca daha önce belirttiğim palet hesaplamasının dahil edilmediğini).
Rjak

1
Evet, temelde demek istediğim buydu. Bu kadar açık olmadığım için üzgünüm, kullandığınız filtre komutunun ne yaptığını bildiğinizi sanıyordum. Testlerimde, paleti tamamen dışarıda bırakmak aslında komutu önemli ölçüde arttırdı . Asıl şifrelemenin sadece 5 saniye sürdüğü konusundaki orijinal karara ne vardınız?
slhck

Muhtemelen büyük bir gösterge olmayan çıktıların gözlenmesi. Komutu palet oluşturmadan çalıştırdığımda, "geçerli çerçeve" göstergesi hemen açılıyor ve çerçeveleri işlemeye başlıyoruz. Palet oluşturma ile çalıştırdığımda, mevcut çerçeve işlem bitmeden yaklaşık 5 saniye öncesine kadar 0'da oturur, sonra da kareler içinde çok hızlı bir şekilde döner.
Rjak,

1
Evet, gözlemlediğim de bu, ama o zaman çok daha hızlı. Ama sanırım videonun uzunluğuna bağlı. Dürüst olmak gerekirse, GIF'i oluşturmanın daha hızlı bir yolu olup olmadığını bilmiyorum ffmpeg -i <input> <scale> <output.gif>.
slhck

Yanıtlar:


2

Kullanımınız palettegen/ paletteusefiltreler komut çalıştırma yavaş yapıyor. Daha düşük kaliteli bir GIF elde etmenin basit yolu şudur:

ffmpeg -f image2 -i "frames.%04d.jpg" output.gif

Ek ölçeklendirme ile:

ffmpeg -f image2 -i "frames.%04d.jpg" -vf scale=150:-1 output.gif

Ayrıca kareleri GIF çıktısına bırakabilir, yani kareleri örnekleyebilir, böylece hepsi işlenmez. Örneğin, bir fpsfiltre kullanarak sadece 1 FPS çıktısına sahip olmak :

ffmpeg -i "frames.%04d.jpg" -vf "fps=fps=1,scale=150:-1" output.gif

Bence bu son örnekte bir yazım hatası var ... `-vf" fps = 1, scale = 150: -1 "olmalı. İkinci örneğin yürütme süresi 68.48 saniyedir. Fps = 1 belirtilmesi 1 FPS GIF ile sonuçlanır, ancak kaynak 120 fps'dir, böylece sonuç çok yavaş çalınır ve yürütme süresi yeterince iyileştirilmez (59.44s). Concat yükleyiciyi kullanmayı deniyorum ve her Nfc çerçevesini ffmpeg ile okutuyorum. Bunu yaparken, Lanczos yeniden ölçeklendirme ve çerçeve başına palet oluşturma özelliğini kullanarak her 5. kareyi örneklersem, zamansal kalite harika görünüyor, renk kalitesi mükemmel görünüyor ve komut 8 saniyenin altında çalışıyor.
Rjak,

Tamamen test ettikten ve yürütme zamanlamaları olduktan sonra, bir şeyi burada bir yorumda paylaşacağım.
Rjak,

@Rjak Filtrenin ilk seçeneği fpsadlandırılmıştır fps, yani bunlar eşdeğerdir. Kaynağınız 120fps ise, -framerate 120 -i "frames…"giriş için varsayılan değer 24 olduğundan, belirtmeniz gerekir.
saat

1

Animasyonlu bir GIF oluşturmak için gereken süreyi, 150 piksel genişliğinde 30 kareye mümkün olduğunca yakın bir sürede azaltmakla görevlendirildim. Ürettiğimiz dizilerin çoğu 1000 karenin altında. 15.000 kare dizilimimiz vardı ve oluşturma düğümlerimiz kabul edilemez derecede yavaş olan bu ~ 30 kare GIF'i üretmek için 17 dakika alıyordu .

Ffmpeg'i bir aldatıcı olarak kullanıyorduk ve hayal etmek için boru kullanıyorduk. Birkaç saatlik deney boyunca aşağıdaki sonuçlara vardım:

  • Ffmpeg'den işlem yapmasını istediğiniz giriş çerçevelerinin sayısı , yürütme hızı açısından en etkili girdi BY FAR'dir . Girdi çerçevelerini atlamak için concat demuxer kullanmak bir seçenek ise, bu en büyük performans farkını yaratacaktır. Her 5. kareyi alarak , yüksek kaliteli lanczos yeniden ölçeklendirme ve çerçeve başına palet hesaplama ile toplam hesaplama süresini 1 dakika 45 saniyeye indirmeyi başardım . 30 kare önizleme minik resmimizi oluşturmak artık 1 saniyenin altında sürüyor .

  • Kireç çözme algoritması bir sonraki en büyük performans çarpma aygıtıydı (ama çok uzak bir saniye). Lanczos yerine fast_bilinear kullanılması, 15.000 çerçevenin tümüne 150 saniyelik işlem süresinden tasarruf etti.

  • En az etkili değişken, palet hesaplamasıydı ve bu, yeniden boyutlandırma algoritmasıyla değişiyordu. Lanczos kullanarak 15.000'den fazla kare, palet hesaplamasını elimine edersek, yürütme zamanından yaklaşık 17 saniye tasarruf ettik. Fast_bilinear kullanarak yaklaşık 75 saniyelik uygulama süresinden tasarruf ettik.

Yeniden ölçeklendirme algoritması ve palet hesaplaması ihmal edilebilir olduğundan, onları en yüksek kalitede tutmaya başladık. Hesaplama zamanımızı 17 dakikadan 1 saniyenin altına düşürdük, çoğunlukla ffmpeg'e okuma dosyalarını atlamasını söyleyerek.

ANAHTAR TAKEAWAY: SKIPPING GİRİŞ ÇERÇEVELERİ vs SKIPPING ÇIKIŞ ÇERÇEVELERİ

Sürecimizin bu kadar uzun sürmesinin nedeni, image2 demuxer kullanırken çerçeve bırakmanın yürütme süresine yardımcı olmamasıdır. -rBayrak ve fpsfiltre ile çakışırsanız , son GIF'te görünen kare sayısını etkileyeceksiniz, ancak ffmpeg hala 15.000 giriş karesinde bir şeyler yapıyor gibi görünüyor.

Ffmpeg'un giriş çerçevelerini atlamasını sağlayabilmemin tek yolu concatdemuxer'ı kullanmak .

Giriş makinelerini atlayarak şu anda dev makinemde 1 saniyenin altında yüksek kaliteli animasyonlu GIF küçük resimleri oluşturuyorum:

# create text file which describes the ~30 input frames we want ffmpeg to process
seq -f "file 'left_frames.%04g.jpg'" 10000 500 25000 > tmp.txt

# generate the animated gif using ffmpeg only
ffmpeg -f concat -i tmp.txt -filter_complex "scale=150:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" output.gif
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.