Як без втрат кодувати послідовність зображень у форматі jpg до відео у ffmpeg?


21

У мене є великий набір jpgs, який я хочу конвертувати у відео без втрат (або, принаймні, дуже близький до втрат, якщо час кодування не набагато вище, ніж інакше).

Наївно, я б подумав, що повинен бути який-небудь кодек, який може зберігати кожен окремий кадр jpg таким, який є (без рекомпресії), і, можливо, досягти приємного стиснення, замінивши деякі кадри просто інформацією про дельту з попереднього кадру. У моєму випадку існує безліч послідовностей кадрів, які однакові між собою, або мають між собою невелику різницю.

Чи є якийсь кодек та відповідні налаштування для ffmpeg, які можуть цього досягти?




1
послідовність jpegs була кодеком довгий час. Цифрові камери, які не використовують h.264, незмінно записують MJPEG, і карти відеозахоплення, які використовуються для його використання, я думаю.
Пітер Кордес

Відповіді:


24

Просто заглуште зображення

Ви можете просто відключити зображення JPG, щоб зробити відео:

ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv

Зауважте, що якщо ви пропустите, -framerateто -framerate 25до вводу буде застосовано за замовчуванням .

Оптимізація без втрат

Ви можете використовувати jpegtranдля оптимізації без втрат на кожному кадрі, що може забезпечити значну економію розміру файлу:

mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done

Тепер mux з, ffmpegяк показано вище.

Перевірка, що це насправді без втрат

Framehash мультплексор може бути використаний для порівняння унікального хеша кожного кадру , щоб гарантувати , що результат дійсно без втрат:

$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0,          0,          0,        1,   460800, 29bcc2db3726c7dfec1826c5740f603f
0,          1,          1,        1,   460800, b5fdc23d93cbd043dc2b9290dc8378f0
0,          2,          2,        1,   460800, ee0709942f24b458fd2380d134dcb59d
...

У вищенаведених прикладах кожен асоційований кадр для вводу та виводу поділяє один і той же хеш, забезпечуючи, щоб кадри були однаковими та що вихід не втрачав.

Також див


Ви можете, будь ласка, уточнити, що framemd5повинні досягти дві команди, крім простого переліку хесів? як би я отримав додаткове стиснення, коли таким чином ідентифіковані кадри?
GJ.

1
Хеші були включені лише для того, щоб показати вам, що кадри є такими ж, як і окремі зображення, тому досягайте вашої вимоги зберігати "кожен окремий кадр jpg таким, який є (без рекомпресії)".
логіан

Опублікував власну відповідь з неперевіреною ідеєю скидання дублікатів кадрів, щоб закінчити VFR MJPEG.mkv. VFR - це єдиний спосіб, з якого я можу подумати, щоб скористатися тимчасовою надмірністю з MJPEG. : P
Пітер Кордес

SSIM може бути швидшим способом порівняння вірності.
Gyan

11

Це виведе відео H.264 без втрат, де кадри будуть використовувати інформацію з інших кадрів

ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4

Пояснення варіантів:

  • -f image2 - повідомляє ffmpeg вибрати групу зображень
  • -r 30 - повідомляє ffmpeg кодувати зі швидкістю 30 кадрів (або зображень) в секунду (змінити це на потрібний кадр)
  • -i %09d.jpg- каже ffmpeg використовувати зображення 000000000.jpg до 999999999.jpg як вхід. Зміна 9в %09d.jpgтому , як багато нулів назви вашої послідовності зображень має. Якщо назви ваших файлів, наприклад, img0001.jpg, це виражатиметься як img% 04d.jpg
  • -vcodec libx264 - повідомляє ffmpeg виводити файл, сумісний з H.264
  • -profile:v high444 - говорить libx264 використовувати високий профіль прогнозування 4: 4: 4 без втрат, що дозволяє кодувати без втрат
  • -refs 16 - повідомляє libx264 мати 16 зображень, що зберігаються в буфері, щоб вони могли посилатися на інші зображення у відео
  • -crf 0 - повідомляє libx264 виконувати кодування без втрат
  • -preset ultrafast - вказує libx264 надати пріоритет швидкості кодування над розміром вихідного файлу
  • a.mp4- повідомляє ffmpeg зберегти висновок у файлі MP4 під назвою a.mp4. Змініть це на ім'я та формат, який ви хочете використовувати

3
Кілька зауважень: -f image2тут зайве. Файл зображень demuxer слід використовувати -framerateзамість -r. libx264 автоматично вибере відповідний -profileдля без втрат, і -presetбуде вирішуватися -refs.
логікан

-refs 5в MOST, якщо ви не знаєте, що у вашому вмісті є однакові зображення, розділені кількома іншими, це може призвести до втрати посилання x264 до того, як він потрапить до дубліката. Вищий, ніж ultrafastробить мало різним у режимі без втрат, окрім посилення CABAC на 10% над CAVLC (для високої вартості процесора на бітрейтах, необхідних для без втрат). Серйозно, на деяких реалізовуваних 720x480p60 (вихід деінтерлейс) superfastбуло 28 ГБ, slowerбуло 27 Гб. Якщо час кодування не має значення, але час декодування є, переконайтеся, що ви уникаєте CABAC. Можливо, навіть -tune fastdecode. Помірна кількість посилань не повинна зашкодити.
Пітер Кордес

І якщо у вас є процесор, який ви можете записати, ви навіть можете спробувати -preset placeboкілька додаткових фракцій відсотків.
DrYak

Також для повноти h265 також є власний режим без втрат. -vcodec libx265 -x265-params lossless=1є рівнозначним варіантом. (Але, за моїм досвідом (= запис презентацій слайд-шоу Powerpoint), це не обов'язково краще, але це набагато повільніше, ніж h264) Слідкуйте за наступним роком AVA / IETF's NETVC1 AOMedia NETVC1 / Xiph's Daala / що б там не було перейменовано до того часу ... режим без втрат
DrYak

5

Ви можете створити aviанімацію у вигляді серії pngзображень ( png це без втрат , так що jpeg => pngперетворення не повинно погіршувати свої фотографії):

якщо ваші зображення названі img_0001.jpg

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec png video.avi

де "25" - частота кадрів, яку ви хочете в отриманому відео. -start_numberне потрібен, якщо він 1, але він корисний, якщо ваш перший номер відео не 1.

Якщо ви хочете зашифрувати mjpegкомандний рядок найвищої якості, це:

ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec mjpeg -qscale 1 video.avi

А краса в тому, що ви можете перетворити відео назад у серію фотографії:

ffmpeg -i video.avi "img_series_%04d.png"
ffmpeg -i video.avi "img_series_%04d.jpg"

тощо ...


Це насправді не відповідає потребам запитувачів. Він шукає спосіб, щоб кадр можна було безперервно оновлювати лише тоді, коли зображення змінюється. Це означає, що одне і те ж зображення може використовуватися не один раз. Також jpeg від природи не є без втрат, оскільки я вважаю, що він використовує стиснення jpeg навіть у максимальній якості.
AJ Henderson

Насправді я здогадуюсь, що він хотів би трохи стиснутись, хоча я не впевнений, як це робити на довгих послідовностях одного і того ж кадру. Я все ще думаю, що потрібен формат подання змінної частоти кадрів, хоча я не впевнений, чи підтримує ffmpeg.
AJ Henderson

CorePNG також може створювати P кадри. Зазвичай jpeg не є стисненням без втрат, і я сумніваюся, mjpeg може створювати P кадри. Я згоден, я не відповідаю на запитання, як його задають, але я даю рішення мати відео без втрат із ffmpeg.
Олів'є S

4

Щоб розширити відповідь LordNeckbeard, так, просто перенесіть дані JPEG у відеопотік MJPEG. Це буде найменше представлення точної послідовності вихідних зображень, навіть незважаючи на те, що MJPEG є надзвичайно неефективним кодеком за сучасними мірками. (немає тимчасової надмірності і навіть не внутрішнє передбачення).

Ви можете зробити MJPEG-відео із змінним кадром, щоб скористатись повторюваними зображеннями у вашому введенні.

ffmpeg -framerate 30 -i input%03d.jpg -vf mpdecimate -codec copy output.mkv  # doesn't work.

Хрм, це не спрацює, оскільки mpdecimate не буде працювати на стислих даних, і ми не можемо дозволити ffmpeg декодувати, а потім повторно jpeg зображення зображень без втрат і вартості процесора.

Можливо, якщо ви замінили дублікати вихідних файлів jpg на порожні файли з цим порядковим номером, чи щось?

Оскільки це запитання навіть не нещодавно, я не збираюся витрачати час, щоб розібратися, як це зробити, якщо хтось не відповість на запитання як. Але оскільки MJPEG може перейти в контейнер mkv, я впевнений, що можливо мати файл, який не дублює дані jpeg для повторних кадрів, а натомість просто не має вихідного кадру для декодування, поки послідовність дублікатів не буде над.

О, ось ідея:

ffmpeg -framerate blah -input blah -vf mpdecimate -f mkvtimestamp_v2 mpdecimate.timestamps

Потім видаліть (або відсуньте в сторону) всі jpegs для кадрів, які mpdecimate хоче скинути (ймовірно, у нього є деякі параметри реєстрації? Або -vf showinfo, і проаналізуйте це, і перемістіть або жорстке посилання тільки кадри, які відображаються у його результаті, залишаючи позаду скинуті JPEG?). mux, що для MJPEG.mkv, тоді зробіть щось з mkvmerge, щоб замінити часові позначки кадру на ті, що мають часові позначки від mpdecimate.timestamps.

Якби ви використовували xcoding, замість того, щоб просто відключити дані jpeg до MJPEG, це було б МНОГО простіше, оскільки ви просто використовуєте мою першу команду з mpdecimate та будь-яким кодеком, окрім copy, і це було б просто працювати (tm).

Я нічого з цього не пробував, оскільки це було давнє питання. Також причина, що я не заповнив прогалини, як насправді фільтрувати ваш каталог jpegs на основі виводу mpdecimate, або як насправді використовувати потік міток часу.

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