Ffmpeg kullanarak bir videoyu GIF'e uygun kalitede nasıl dönüştürebilirim?


310

Ffmpeg ile dosyaya FLVfilm dönüştürüyorum GIF.

ffmpeg -i input.flv -ss 00:00:00.000 -pix_fmt rgb24 -r 10 -s 320x240 -t 00:00:10.000  output.gif

Harika çalışıyor, ancak çıktı gif dosyasının kalitesi çok düşük.

Dönüştürülmüş gif kalitesini nasıl artırabilirim?

Komutun Çıktısı:

ffmpeg -i input.flv -ss 00:00:00.000 -pix_fmt rgb24 -r 10 -s 320x240 -t 00:00:10.000  output.gif
ffmpeg version 0.8.5-6:0.8.5-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers
  built on Jan 24 2013 14:52:53 with gcc 4.7.2
*** THIS PROGRAM IS DEPRECATED ***
This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.flv':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
  Duration: 00:00:18.85, start: 0.000000, bitrate: 3098 kb/s
    Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720, 2905 kb/s, 25 fps, 25 tbr, 50 tbn, 50 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 192 kb/s
    Metadata:
      creation_time   : 2013-02-14 04:00:07
[buffer @ 0x92a8ea0] w:1280 h:720 pixfmt:yuv420p
[scale @ 0x9215100] w:1280 h:720 fmt:yuv420p -> w:320 h:240 fmt:rgb24 flags:0x4
Output #0, gif, to 'output.gif':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
    encoder         : Lavf53.21.1
    Stream #0.0(und): Video: rawvideo, rgb24, 320x240, q=2-31, 200 kb/s, 90k tbn, 10 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Stream mapping:
  Stream #0.0 -> #0.0
Press ctrl-c to stop encoding
frame=  101 fps= 32 q=0.0 Lsize=    8686kB time=10.10 bitrate=7045.0kbits/s dup=0 drop=149    
video:22725kB audio:0kB global headers:0kB muxing overhead -61.778676%

Teşekkürler.


1
APNG bir şey olduğunda insanların GIF ile hala nasıl paletteworks yaptıkları komik.
Константин Ван

Yanıtlar:


447

ffmpeg örnek

Ffmpeg'den GIF çıktısı
183K

ffmpegyüksek kaliteli GIF çıktısı alabilir. Her zaman yeni bir sürüm kullanmanız önerilir: indirin veya derleyin .

ffmpeg -ss 30 -t 3 -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif
  • Bu örnek -ss 30, girişin ilk 30 saniyesini ( ) atlar ve 3 saniyelik bir çıkış ( -t 3) oluşturur.
  • fps filtresi kare hızını ayarlar.
  • Ölçek filtresi çıktısını 320 piksel genişliğinde yeniden boyutlandırır ve en boy oranını koruyarak yüksekliği otomatik olarak belirler.
  • paletli ve paletli filtreler, girdilerinizden oluşturulan özel bir palet oluşturur ve kullanır.
  • split filter her şeyin tek bir komutla yapılmasına izin verecektir.
  • -loopÇıkış seçeneği ile kontrol döngü . Değeri 0sonsuz döngüdür.

Daha fazla örnek ve seçenek için bkz. FFmpeg ile yüksek kaliteli GIF .


Imagemagick convertörneği

Ffmpeg'den GIF çıktısı
227k

Başka bir komut satırı yöntem, boru için ffmpegiçin convert(ya da magick) imagemagic'den.

 ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam -f image2pipe - | convert -delay 10 - -loop 0 -layers optimize output.gif

Kare hızını ayarlama

Kare hızını, fpsfiltre giriş ffmpegve -delaygiriş kombinasyonuyla ayarlayın convert. Bu karmaşıklaşabilir çünkü convertham bir görüntü akışı elde edilir, böylece fps korunmaz. İkinci olarak, -delaydeğeri convertolduğu kene yok saniye başına kare, (saniyede 100 keneler vardır). Örneğin, fps=12.5= 100 / 12.5 = 8 = ile -delay 8.

convertyuvarlar -delaybir tam sayı değer, yani, 8 8.4 sonuçları ve 9'da 8,5 sonuç Bu etkili olduğu anlamına gelir , sadece bazı kare hızları desteklenen (belirli bir gecikme kare başına ayarlanır, ancak bu ötesinde edilebilir tüm çerçeveler boyunca düzgün bir gecikme ayarlarken bu cevap).

-delayÇıkış seçeneği olarak kullanılırsa göz ardı edilir, bu nedenle -örnekte gösterildiği gibi kullanılmalıdır .

Son olarak, tarayıcılar ve resim görüntüleyiciler asgari bir gecikme uygulayabilir, bu nedenle -delayyine de göz ardı edilebilir.

ABD Balık ve Yaban Hayatı Servisi Ulusal Koruma Eğitim Merkezi'nin izniyle.


4
Bazı örnek sonuçlar eklendi (ancak yine de çerçeveler). Burada ilk dosya 4.1 MB, ikincisi 8 MB civarında.
slhck

2
@ LordNeckbeard, harikasınız! çok teşekkürler-vf scale=320:-1,format=rgb8,format=rgb24
Kamil Hismatullin

6
Bu arada, kullanmaya başladığım convertPNG çerçevelerinden dönüştürme komutu için convert -delay 5 -loop 0 -dither None -colors 80 "frames/ffout*.png" -fuzz "40%" -layers OptimizeFrame "output.gif"genel dosya boyutunu biraz
küçültüyor

2
Tamam, kullandım scale=0:-1, kullandım , ölçeği ayarladığınızda, ölçeği 0videodan alacak.
Mousa Alfhaily 16:17

2
Bu soru-cevap bir kalıcı olarak kodlanmış olmalıdır (ya da şimdilik sadece "sabitlenmiş") çünkü bundan yüz yıl sonra tüm iletişim memler aracılığıyla yapılacaktır. Bence sadece bu yazıdaki etkinlik bununla konuşuyor.
Jonathan Neufeld

87

Ara görüntü dosyalarından kaçınmayı tercih ederseniz, LordNeckBeard tarafından sağlanan komutlar ffmpegve ImageMagick'ler arasında aktarılabilir, convertböylece hiçbir ara dosya gerekmez.

ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -loop 0 - output.gif

-f image2pipeGörüntülerin içine video bölmek ve dışarı taşınıyor olması uygun hale getirmek için ffmpeg söyler ve -vcodec ppmbiçim png ise nedense (ppm olduğu çıktı biçimini belirtir, ya convertborunun tüm resimleri okumuyor, ya da ffmpeg yapar hepsini çıkarmaz). Her -iki komut için de, sırasıyla çıkış ve giriş için bir borunun kullanılacağını belirtir.

Bir dosyayı kaydetmeden sonucu optimize etmek için çıktıyı convertikinci bir convertkomuta iletebilirsiniz:

ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -loop 0 - gif:- | convert -layers Optimize - output.gif

gif:-Söyler convertgif biçimlendirilmiş veri olarak boruya çıkışını ve -layers Optimizeikinci söyler convertgerçekleştirmek optimize-frameve optimize-transparancyyöntemleri (ImageMagick bkz Animasyon Optimizasyonu için giriş ). Nottan çıkan çıktı -layers Optimizeher zaman daha küçük bir dosya boyutu sağlamayabilir; bu nedenle, önce emin olmak için optimizasyon olmadan bir gif'e dönüştürmeyi deneyebilirsiniz.

Tüm bu süreç boyunca her şeyin hafızada olduğunu unutmayın, bu nedenle görüntüler oldukça büyükse yeterli hafızaya ihtiyacınız olabilir.


1
Bu komut dizisi ayrıca şu şekilde de çalışıravconv
raphael

Son iki dönüştürme komutunu birleştirmelisiniz:convert -delay 5 -loop 0 -layers Optimize - output.gif
Clément

GIF kaynak videonun 2 katı hızla çalışıyor mu?
Titan

@Titan, birinci komutta -r 10 ve ikincide -delay 5 olduğuna inanıyor. Gecikmeyi de 10 olarak değiştirdim ve şimdi normal oynuyor gibi görünüyor.
Steven Huang,

2
splitFiltreyi ffmpeg kullanarak da ara görüntü dosyalarından kaçınabilirsiniz . Hiçbir şeye boru ffmpeg -ss 30 -t 3 -i "input.flv fps=10,scale=320:-1:flags=lanczos,split[x][z];[z]palettegen[y];[x][y]paletteuse" output.gif
eklemenize

37

Ffmpeg 2.6'dan itibaren daha iyisini yapabiliriz:

palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos"

ffmpeg -i input.flv -vf "$filters,palettegen" -y $palette
ffmpeg -i input.flv -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y output.gif

HT


18

Çıktı çözünürlüğünü ve kare hızını da belirleyen komut dosyasının kendi sürümünü yaptım.

Koşu ./gifenc.sh input.mov output.gif 720 10, verdiğiniz filmden 720p genişliğinde 10fps GIF çıktısı alacak. chmod +x gifenc.shDosya için yapmanız gerekebilir .

#!/bin/sh

palette="/tmp/palette.png"

filters="fps=$4,scale=$3:-1:flags=lanczos"

ffmpeg -v warning -i "$1" -vf "$filters,palettegen" -y "$palette"
ffmpeg -v warning -i "$1" -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y "$2"

Detayları Github'ımda okuyabilirsin.

Varsayımlar: ffmpeg yüklü ve script diğer dosyalar ile aynı klasörde.


3
Senaryonuz için çok teşekkür ederim. Sadece test ettim ve harika çalışıyor!
orschiro

15

@Stephane'den cevap çok iyi. Ancak Buffer queue overflow, dropping.bazı videolarda olduğu gibi bir uyarı alır ve oluşturulan gifbazı çerçeve düştü.

Burada ile daha iyi bir sürümüdür fifoönlemek için filtrenin Buffer queue overflowkullanırken paletteusefiltreyi. splitPNG dosyası ara palet oluşturulmasını önlemek için filtre kullanarak .

ffmpeg -i input.mp4 -filter_complex 'fps=10,scale=320:-1:flags=lanczos,split [o1] [o2];[o1] palettegen [p]; [o2] fifo [o3];[o3] [p] paletteuse' out.gif

Bunu doğru anlarsam, girişi o1 ve o2'ye bölüp o2'yi o3'e kopyalarsınız. Peki neden o3'e ihtiyacın var? Neden sadece doğrudan o2 kullanmıyorsunuz?
Chloe,

1
@Chloe ve fifoarasında filtre işlemini gördünüz mü ? Uyarıyı önlemek için . o2o3Buffer queue overflow
alijandro

+1 Bu benim için gerçekten iyi çalışıyor (ve başvurulan sorunu çözdü).
Iain Collins

Bu çözümü kesinlikle seviyorum. Kudos!
Leonid Usov

10

senaryo yazdı, test edildi ve çalışıyor.

kullanımı:

./avi2gif.sh ./vokoscreen-2015-05-28_12-41-56.avi

PHUN var :)

vim avi2gif.sh

#!/bin/sh

INPUT=$1

# default settings, modify if you want.

START_AT_SECOND=0; # in seconds, if you want to skip the first 30 seconds put 30 here

LENGTH_OF_GIF_VIDEO=9999999; # in seconds, how long the gif animation should be

echo "Generate a palette:"
ffmpeg -y -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png

echo "Output the GIF using the palette:"
ffmpeg -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" $INPUT.gif

btw: vokoscreen Linux için mükemmel bir ScreenCapturing aracıdır :)

Çok teşekkür ederim Michael Kohaupt :) Kaya sabit.

bazı dosya boyutu istatistikleri:

5.3M = vokoscreen-2015-04-28_15-43-17.avi -> vokoscreen-2015-05-28_12-41-56.avi.gif = 1013K

sonuçları burada görebilirsiniz .


10

ffmpegPaleti ile yöntemle aracı olmadan, tek bir komut çalıştırılabilir .pngdosyaya.

ffmpeg -y -ss 30 -t 3 -i input.flv -filter_complex \
"fps=10,scale=320:-1:flags=lanczos[x];[x]split[x1][x2]; \
[x1]palettegen[p];[x2][p]paletteuse" output.gif

Bu splitfiltre sayesinde yapılabilir .


10

Linux / Unix / MacOS

Aşağıdaki @LordNeckbeard yaklaşımı ile ffmpegkomuta, senin içine eklenebilir aşağıdaki kullanışlı Bash işlevi bulabilirsiniz ~/.bash_profiledosyası:

# Convert video to gif file.
# Usage: video2gif video_file (scale) (fps)
video2gif() {
  ffmpeg -y -i "${1}" -vf fps=${3:-10},scale=${2:-320}:-1:flags=lanczos,palettegen "${1}.png"
  ffmpeg -i "${1}" -i "${1}.png" -filter_complex "fps=${3:-10},scale=${2:-320}:-1:flags=lanczos[x];[x][1:v]paletteuse" "${1}".gif
  rm "${1}.png"
}

İşlev yüklendikten sonra (el ile veya üzerinden . ~/.bash_profile), yeni bir video2gifkomut almanız gerekir .

Örnek kullanım:

video2gif input.flv

veya:

video2gif input.flv 320 10

Saniyede 10 kare ile 320 genişliğe ölçeklendirin.

Farklı bir video formatı da (mp4 gibi) belirleyebilirsiniz.


Mac os işletim sistemi

Video dosyalarından GIF oluşturabilen GIF Brewery uygulamasını deneyebilirsiniz .


Alternatif olarak, çevrimiçi ortamda ücretsiz dönüşüm yapan birkaç web sitesi vardır.


betiğiniz benim için png dosyası hakkında bir hata oluşturmuyor ve gif çıktısı
almıyorum

7

Seçilen cevap, kaynak videoyu ölçeklemek ve fif'i üretilen gif ile değiştirmek istediğinizi varsayar. Bunu yapmanız gerekmiyorsa, aşağıdakiler işe yarar:

src="input.flv"
dest="output.gif"
palette="/tmp/palette.png"

ffmpeg -i $src -vf palettegen -y $palette
ffmpeg -i $src -i $palette -lavfi paletteuse -y $dest

Bu, kullandığım kaynak videoyu güvenilir bir şekilde yeniden oluşturan bir gif istediğimde işe yaradı.


6

Windows kullanıcıları için: Windows dizininde bu içerikle dosya
oluşturun video2gif.bat:

@echo off
set arg1=%1
set arg2=%arg1:~0,-4%
ffmpeg -y -i %arg1% -vf fps=10,scale=-1:-1:flags=lanczos,palettegen %TEMP%\palette.png
ffmpeg -i %arg1% -i %TEMP%\palette.png -filter_complex "fps=10,scale=-1:-1:flags=lanczos[x];[x][1:v]paletteuse" %arg2%.gif
del /f %TEMP%\palette.png

Ve sonra kullanabileceğiniz her yerde bu örnek gibi olur:

video2gif myvideo.mp4

Sonra myvideo.gifgeçerli dizinde var.
Varsa myvideo.gif, üzerine yazmak için sizden soru.

DÜZENLE:

Bu toplu betiği kullanmanızı öneririm: https://github.com/NabiKAZ/video2gif


2
Burada iki şey yapmış olduğunu görüyoruz: (1) Windows (BAT) komut dosyası olarak komutları yazılır ve (2) farklı bir filtre kombinasyonu (diğer cevapların hiçbiri kullanır sağladı hem fps=10 ve scale=-1:-1).  Sun'ın cevabı bize zaten bir toplu iş dosyası verdi ve birisinin ( pje'nin cevabındaki kabuk senaryoları ve thevangelist'in cevabındaki gibi ) bir değişkene filtre listesi atama avantajına sahip olduğu (bir kere ),… (Devamı)
Scott

1
(Devam)… bu yüzden listeyi iki defa hecelemenize gerek kalmaz (toplu iş dosyanızda olduğu gibi). (Kullanıcı listeden birini değiştirmek için diğerini değil, komut dosyasını düzenlerse tutarsızlığın soruna yol açması riskini doğurur.) En azından filtre seçiminizi açıklayabilir misiniz fps=10,scale=-1:-1? ( Bir komutun bölümlerinin bir açıklaması için notun cevabına bakınız .)
Scott

1
@Scott Doğru dedin, bu yüzden buraya yeni bir faydalı senaryo yazıyorum
Nabi KAZ

4

Windows kullanıcıları için toplu iş dosyası aşağıdadır:

gifenc.bat:

set start_time=0
set duration=60
set palette="c:\temp\palette.png"
set filters="fps=15,scale=-1:-1:flags=lanczos"
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -vf "%filters%,palettegen" -y %palette%
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %2

Kaynak: FFmpeg ile yüksek kaliteli GIF: Sadece bir örnek çıkarma

Yalnızca bir giriş değişkeni kullanmak istiyorsanız ve çıktı adının yalnızca GIF (telaffuz edilen JIF) uzantısına sahip olmasını istiyorsanız, bunun yerine şunu kullanın:

set start_time=0
set duration=60
set palette="c:\temp\palette.png"
set filters="fps=15,scale=-1:-1:flags=lanczos"
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -vf "%filters%,palettegen" -y %palette%
set var1=%1
set var2=%var1:~0,-4%
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %var2%.gif

3

Video dosyanızı gif'e çevirmek için Windows 7/10 "sağ tıkla" içerik menüsü girişi nasıl eklenir

Diğer cevapların bazıları kullandığım video2gif betiğini belirtti . Ancak, herhangi bir komut dosyasını kullanabilirsiniz.

Bağlam menüsü seçeneğini oluşturmak için kayıt defterini düzenlemeniz gerekir. Yönetici ayrıcalıklarını çalıştırarak bir powershell komut istemini açın. Bu komutları yürütün:

$key = "Registry::HKEY_CLASSES_ROOT\`*\shell\Run Video2Gif"
New-Item -Path $key"\Command" -Value "C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat `"%1`"" -Force

Şimdi bir dosyayı sağ tıkladığınızda "Run Video2Gif" seçeneğiniz olacak!

btw Ben ffmpeg kurdum C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\ve video2gif.batbetiği hemen yanındaki çöp dizinine koydum ffmpeg.exe. Ayrıca C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\binpencerelerime de ekledim PATH, ama buna gerek duymuyorum.

Komut satırına bazı ekstra komut satırı bayrakları / video2gif-prompt.batargları verebilme seçeneğine sahip olmak istiyorsanız, adında yeni bir dosya oluşturun ve kayıt defterine bunun yerine başvuruda bulunmasını isteyin video2gif.bat:

@echo off
set /p inp=Enter extrta args, if desired:
C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat %* %inp%

Varsayılanları hızlıca bulmak için hala enter'a basabilirsiniz.

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.