Как без потерь кодировать последовательность изображений jpg в видео в ffmpeg?

21

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

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

Есть ли какой-то кодек и подходящие настройки для ffmpeg, которые могут этого добиться?

ГДж.
источник
Связанный: avp.stackexchange.com/questions/4642/…
Друг Георга
Также связанные: avp.stackexchange.com/questions/7300/…
Друг Георга
1
sequence-of-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

Теперь добавьте, 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
...

В приведенных выше примерах каждый связанный кадр для ввода и вывода совместно использует один и тот же хеш, гарантируя, что кадры идентичны и что выходной сигнал не имеет потерь.

Также см

llogan
источник
Не могли бы вы уточнить, чего framemd5должны достичь две команды, помимо простого перечисления хэшей? как получить дополнительное сжатие, если идентифицированы идентичные кадры?
ГДж.
1
Хэши были включены только для того, чтобы показать вам, что кадры совпадают с отдельными изображениями, поэтому, таким образом, вы выполняете требование сохранения «каждого отдельного кадра jpg как есть (без повторного сжатия)».
Llogan
Написал мой собственный ответ с непроверенной идеей удаления дубликатов кадров, чтобы в итоге получить VFR MJPEG.mkv. VFR - это единственный способ использовать временную избыточность с MJPEG. : P
Питер Кордес
SSIM может быть более быстрым способом сравнения верности.
Джан
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 в качестве входных данных. Измените значение 9in %09d.jpgна количество нулей в именах последовательности изображений. Если ваши имена файлов, например, img0001.jpg, то это будет выражаться как img% 04d.jpg
  • -vcodec libx264 - сообщает ffmpeg для вывода в файл, совместимый с H.264
  • -profile:v high444 - говорит libx264 использовать прогнозируемый профиль High 4: 4: 4 High Lossless, позволяя кодировать без потерь
  • -refs 16 - сообщает libx264, что в буфере должно храниться 16 изображений, чтобы на них могли ссылаться другие изображения в видео
  • -crf 0 - говорит libx264 выполнить кодирование без потерь
  • -preset ultrafast - говорит libx264 расставить приоритеты скорости кодирования над размером выходного файла
  • a.mp4- сообщает ffmpeg сохранить выходные данные в файле MP4 с именем a.mp4. Измените это на имя файла и формат, который вы хотите использовать
Адам Шанс
источник
3
Несколько замечаний: -f image2здесь лишнее. Файл изображения демультиплексора следует использовать -framerateвместо -r. libx264 автоматически выберет подходящее -profileдля без потерь, и -presetбудет иметь дело с -refs.
Llogan
-refs 5в большинстве случаев, если вы не знаете, что в вашем контенте есть идентичные изображения, разделенные несколькими другими, это может привести к тому, что 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) Настройтесь на следующий год AOMedia AV1 / IETF - 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 даже при максимальном качестве.
А.Дж. Хендерсон
На самом деле, я думаю, он был готов к некоторому сжатию, хотя я не уверен, как это будет происходить на длинных последовательностях одного и того же кадра. Я все еще думаю, что необходим формат представления с переменной частотой кадров, хотя я не уверен, поддерживает ли ffmpeg их.
AJ Henderson
CorePNG также может создавать P-кадры. Обычно jpeg - это не сжатие без потерь, и я сомневаюсь, что mjpeg может создавать P-кадры. Я согласен, что я не отвечаю на вопрос в том виде, в котором он задан, но я даю решение получить видео без потерь с помощью ffmpeg.
Оливье С
4

Чтобы расширить ответ LordNeckbeard, просто добавьте данные JPEG в видеопоток MJPEG. Это будет наименьшее представление точной последовательности выходных изображений, даже несмотря на то, что по современным стандартам MJPEG является ужасно неэффективным кодеком. (нет временной избыточности и даже нет внутреннего предсказания.

Вы можете создать MJPEG-видео с переменной частотой кадров, чтобы использовать дубликаты изображений на входе.

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

Хм, это не сработает, поскольку mpdecimate не будет работать со сжатыми данными, и мы не можем позволить ffmpeg декодировать, а затем повторно записать данные изображений без потерь и затрат на процессор.

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

Поскольку этот вопрос даже не недавний, я не собираюсь тратить время на то, чтобы понять, как это сделать, если кто-то не ответит, чтобы спросить, как это сделать. Но так как MJPEG может входить в контейнер mkv, я уверен, что возможно иметь файл, который не дублирует данные jpeg для повторяющихся кадров, но вместо этого просто не имеет выходного кадра для декодирования, пока последовательность дубликатов не будет над.

О, вот идея:

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

Затем удалите (или переместите в сторону) все jpegs для кадров, которые mpdecimate хочет отбросить (возможно, у него есть некоторые параметры ведения журнала? Или -vf showinfo, и проанализируйте его, и переместите или жестко связывайте только кадры, которые отображаются в его выходных данных, оставляя позади упал JPEG?). Примените это к MJPEG.mkv, затем сделайте что-нибудь с mkvmerge, чтобы заменить временные метки кадра в этом на временные метки из mpdecimate.timestamps.

Если бы вы использовали xcoding вместо простого преобразования данных jpeg в MJPEG, это было бы НАМНОГО проще, поскольку вы просто использовали бы мою первую команду с mpdecimate и любым другим кодеком, кроме copy, и это было бы просто Work (tm).

Я не пробовал ничего из этого, так как это был старый вопрос. Также причина, по которой я не заполнил пробелы в том, как на самом деле фильтровать ваш каталог jpegs на основе вывода mpdecimate, или как на самом деле использовать поток меток времени.

Питер Кордес
источник