Як перетворити відео в GIF за допомогою ffmpeg з розумною якістю?


310

Я перетворюю FLVфільм у GIFфайл із ffmpeg.

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

Він чудово працює, але вихідний файл gif має дуже низьку якість.

Будь-які ідеї, як я можу покращити якість перетвореного gif?

Виведення команди:

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%

Дякую.


1
Дивно, як люди все ще роблять палітри з GIF, коли APNG - це річ.
— Константин Ван

Відповіді:


447

ffmpeg приклад

GIF вихід з ffmpeg
183k

ffmpegможе виводити високоякісний GIF. Завжди рекомендується використовувати останню версію: завантажити або компілювати .

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
  • Цей приклад пропустить перші 30 секунд ( -ss 30) вводу та створить 3-секундний вихід ( -t 3).
  • fps фільтр встановлює частоту кадрів.
  • масштабний фільтр дозволить змінити розмір виходу на 320 пікселів в ширину і автоматично визначити висоту при збереженні співвідношення сторін.
  • фільтри palettegen і paletteuse генерують та використовують користувацьку палітру, сформовану з ваших даних.
  • розділений фільтр дозволить зробити все в одній команді.
  • Управління циклом з -loopопцією виводу. Значення 0нескінченного циклічного циклу.

Дивіться високоякісний GIF з FFmpeg для багатьох інших прикладів та варіантів.


Imagemagick convertприклад

GIF вихід з ffmpeg
227k

Інший метод командного рядка для труби від ffmpegдо convert(або magick) від ImageMagick.

 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

Встановлення частоти кадрів

Встановити частоту кадрів за допомогою комбінації fpsфільтра в ffmpegі -delayв convert. Це може ускладнитися, тому що convertпросто отримується необроблений потік зображень, тому не зберігається кадрів в секунду. По-друге, -delayзначення in convertє в тиках (є 100 тиків в секунду), а не в кадрах на секунду. Наприклад, при fps=12.5= 100 / 12,5 = 8 = -delay 8.

convertокругляє -delayзначення на ціле число, тому 8,4 призводить до 8 та 8,5 результатів у 9. Це ефективно означає, що підтримуються лише деякі частоти кадрів при встановленні рівномірної затримки для всіх кадрів (конкретна затримка може бути встановлена ​​на кадр, але це виходить ця відповідь).

-delayЗдається, ігнорується, якщо використовується як вихідний параметр, тому його потрібно використовувати раніше, -як показано в прикладі.

Нарешті, веб-переглядачі та переглядачі зображень можуть впроваджувати мінімальну затримку, тому ви -delayвсе одно можете ігнорувати.

Відео надано Національним навчальним центром з охорони риби та дикої природи США.


4
Додано кілька прикладних результатів (хоча все ще кадри). Тут перший файл - 4,1 Мб, другий - близько 8 Мб.
— slhck

2
@LordNeckbeard, ти приголомшливий! велике спасибі за-vf scale=320:-1,format=rgb8,format=rgb24
— Каміль Гісматуллін

6
До речі, для convertкоманди для перетворення кадрів з PNG я в кінцевому підсумку використовував convert -delay 5 -loop 0 -dither None -colors 80 "frames/ffout*.png" -fuzz "40%" -layers OptimizeFrame "output.gif", що зовсім скорочує загальний розмір файлу
— Вільф

2
Гаразд, я це отримав, я використав scale=0:-1, тому коли ви встановите масштаб 0, він зніме масштаб з відео.
— Mousa Alfhaily

2
Це питання повинні бути постійно закодовані у томе (або, можливо, поки що просто "приколото"), оскільки через сто років все спілкування буде здійснюватися через меми. Я думаю, що про це говорить лише діяльність на цій посаді.
— Джонатан Нойфельд

87

Якщо ви хочете уникати проміжних файлів зображень, команди, надані LordNeckBeard, можна переносити між зображеннями ffmpegі ImageMagick, convertтак що проміжні файли не потрібні:

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

-f image2pipeКаже FFmpeg , щоб розділити відео на зображення і зробити його придатним бути конвеєру з, і -vcodec ppmвизначає формат виведення бути частин на мільйон (за якою - то причини , якщо формат PNG, або convertне читає все зображення з труби, або FFmpeg робить не виводити їх усіх). -Для обох команд вказує , що труба буде використовуватися для виведення і введення відповідно.

Щоб оптимізувати результат без збереження файлу, ви можете передавати висновок від convertдругої convertкоманди:

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:-Каже convertдо труби його вихід , як GIF дані в форматі , і -layers Optimizeкаже друга convertдля виконання optimize-frameі optimize-transparancyметоди (див ImageMagick Введення в анімації оптимізації ). Зауважте, що вихідний -layers Optimizeфайл може не завжди забезпечувати менший розмір файлу, тому ви можете спробувати перейти в gif без оптимізації спочатку, щоб бути впевненим.

Пам'ятайте, що під час всього цього процесу все знаходиться в пам'яті, тому вам може знадобитися достатня кількість пам'яті, якщо зображення досить великі.


1
Цей набір команд також працює зavconv
— raphael

Вам слід об'єднати дві останні команди перетворення:convert -delay 5 -loop 0 -layers Optimize - output.gif
— Clément

Здається, gif працює з 2х швидкістю вихідного відео?
— Титан

@Titan вважає, що -r 10 в першій команді, а -delay 5 в другій. Я також змінив затримку на 10 і, схоже, зараз грає нормально.
— Стівен Хуан

2
Ви також можете уникнути проміжних файлів зображень, використовуючи splitфільтр у ffmpeg. Не потрібно взагалі нічого 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
— казати

37

Щодо ffmpeg 2.6, ми можемо зробити ще краще:

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

Я створив власну версію сценарію, яка також параметризує вихідну роздільну здатність і частоту кадрів.

Запуск ./gifenc.sh input.mov output.gif 720 10буде виводити GIF з 720p шириною 10 кадрів в секунду з фільму, який ви йому дали. Можливо, вам доведеться зробити chmod +x gifenc.shдля файлу.

#!/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"

Ви можете прочитати подробиці на моєму Github

Припущення: ffmpeg встановлений, а сценарій знаходиться в тій самій папці, що й інші файли.


3
Дуже дякую за ваш сценарій. Я просто перевірив це, і він чудово працює!
— orschiro

15

Відповідь від @Stephane дуже хороша. Але воно отримає попередження, як Buffer queue overflow, dropping.для деяких відео, і у створеного gifзнизився кадр.

Ось краща версія з fifoфільтром, яку слід уникати Buffer queue overflowпри використанні paletteuseфільтра. Використовуючи splitфільтр, щоб уникнути створення проміжної палітри PNG-файлу.

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

Якщо я правильно це розумію, ви розділяєте вхід на o1 і o2, а копіюєте o2 в o3. То навіщо вам потрібен o3? Чому б просто не використовувати o2 безпосередньо?
— Хлоя

1
@Chloe Ви бачили роботу fifoфільтра між o2і o3? Щоб уникнути Buffer queue overflowпопередження.
— аліяндро

+1 Це для мене дуже добре (і вирішено проблему, на яку посилаються).
— Ієн Коллінз

Я абсолютно люблю це рішення. Кудо!
— Леонід Усов

10

зробив сценарій, перевірив і працює.

використання:

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

МАЙТЕ ФОНУ :)

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 :)

ДЯКУЄМО МНОГО Майкла Кохаупта :) Рок стійкий.

деяка статистика розміру файлу:

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

дивіться результати тут.


10

ffmpegЗ палітрою метод може працювати в одній команді, без проміжного .pngфайлу.

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

Це можна зробити завдяки splitфільтру.


10

Linux / Unix / macOS

Дотримуючись @LordNeckbeard підхід з ffmpegкомандою, знайдіть наступну корисну функцію Bash, яку можна додати у ваш ~/.bash_profileфайл:

# 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"
}

Після завантаження функції (вручну або з неї . ~/.bash_profile), ви повинні мати нову video2gifкоманду.

Приклад використання:

video2gif input.flv

або:

video2gif input.flv 320 10

Масштаб до 320 ширини з 10 кадрами в секунду.

Ви також можете вказати інший формат відео (наприклад, mp4).


macOS

Ви можете спробувати додаток GIF Brewery , який може створювати GIF з відеофайлів.


Крім того, є кілька веб-сайтів, які здійснюють конверсію в Інтернеті безкоштовно.


ваш сценарій викликає у мене помилку про відсутність png-файлу, і я не отримую gif-виводу, але вхідний файл .mp4 залишається незмінним
— lacostenycoder

7

Вибрана відповідь передбачає, що ви бажаєте масштабувати вихідне відео та змінити його кадрів в секунду у створеному GIF. Якщо вам цього не потрібно, виконайте такі дії:

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

Це було корисно, коли я хотів подарувати подарунок, який сумлінно відтворив вихідне відео, яке я використовував.


6

Для користувачів Windows:
створіть video2gif.batфайл у каталозі Windows із цим вмістом:

@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

І тоді будь-де ви можете скористатись цим прикладом:

video2gif myvideo.mp4

Потім у вас є myvideo.gifпоточний каталог.
Якщо myvideo.gifтакий існує, запитайте про його перезапис.

Редагувати:

Пропоную використовувати цей пакетний сценарій: https://github.com/NabiKAZ/video2gif


2
Я бачу, що ви тут зробили дві речі: (1) записали команди як сценарій команд Windows (.BAT), і (2) надали різну комбінацію фільтрів (жоден з інших відповідей не використовує і те, fps=10 і іншеscale=-1:-1 ).  Відповідь Sun, вже дав нам пакетний файл, і що один (наприклад , сценарії оболонки в відповідь ПРД в і відповідь thevangelist в ) має перевагу , що він привласнює список фільтрів змінної ( один раз ), ... (продовження)
— Скотт

1
(Продовжував)… тому не потрібно списувати список двічі (як це робить ваш пакетний файл). (Я припускаю, що це створює ризик, що якщо користувач редагує сценарій для зміни одного зі списків, а не іншого, невідповідність спричинить проблему.) Чи можете ви хоча б пояснити свій вибір фільтрів ( fps=10,scale=-1:-1)? (Дивіться відповідь помітного на прикладі пояснення частин команди.)
— Скотт

1
@Scott Ви сказали правильно, тому я пишу новий корисний сценарій тут: github.com/NabiKAZ/video2gif
— Nabi KAZ

4

Нижче наведено пакетний файл для користувачів Windows:

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

Джерело: GIF високої якості з FFmpeg: Витяг просто зразка

Якщо ви просто хочете використовувати одну вхідну змінну і маєте вихідне ім'я лише розширення GIF (вимовляється JIF), використовуйте це замість цього:

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

Як додати запис контекстного меню Windows 7/10 "клацнути правою кнопкою миші", щоб перетворити ваш відеофайл у gif

Деякі з інших відповідей згадували сценарій video2gif , який я використав. Але ви можете використовувати будь-який сценарій.

Щоб створити параметр контекстного меню, вам потрібно відредагувати свій реєстр. Відкрийте командний рядок powerhell, запустивши w / admin privs. Виконайте ці команди:

$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

Тепер, коли ви клацнете правою кнопкою миші на файл, у вас буде опція "Запустити Video2Gif"!

btw Я встановив ffmpeg C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\і поставив video2gif.batскрипт у bin dir прямо поруч ffmpeg.exe. Я також додав C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\binдо своїх вікон PATH, але я не думаю, що потрібно.

Якщо ви хочете, щоб мати можливість подавати деякі додаткові прапорці / аргументи командного рядка до скрипту, тоді створіть новий файл з назвою video2gif-prompt.bat, і реєстр посилатиметься на нього замість 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%

Ви можете просто натиснути клавішу Enter, щоб швидко отримати налаштування за замовчуванням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.