Правильно исправить видео, которые были закодированы в старой версии x264

459
videoguy

Из-за ошибки в старых версиях x264, видеопотоки h.264 имеют следующие три свойства:

  1. закодирован с помощью x264 build 150 или более ранней версии
  2. используя подвыборку цветности 4: 4: 4
  3. битовый поток не содержит информации о версии x264

не будет воспроизводиться должным образом многими видео плеерами. В новых версиях видеоплеера mpvесть выделенная опция

--vd-lavc-assume-old-x264 

специально для решения этой проблемы (см .: https://mpv.io/manual/master/ ).

На баг-трекере FFmpeg предлагается добавить правильный видеопоток SEI.h264 в видеопоток (я думаю, что он содержит информацию о версии x264). Я предпочитаю не полагаться на такие хаки, поэтому мой вопрос: существует ли «правильный» способ (в идеале использующий ffmpeg) для восстановления файлов, как если бы они были закодированы с новой (фиксированной) версией x264 ?

Очевидно, я хотел бы сохранить (более или менее) качество видео и размер файла . Если перекодировка необходима, то она не должна ничего менять, кроме исправления некорректного поведения старой реализации x264. (Дополнительная информация: в отчете об ошибке приведен пример поврежденного файла. Предполагается, что ошибка в старой версии x264, вероятно, была представлена ​​здесь .)

5
Нет. Ffmpeg не может правильно декодировать такие потоки, тогда результат перекодирования будет иметь ошибки. Что не так со вставкой SEI? Gyan 6 лет назад 0
@ Гьян, возможно, вы могли бы предоставить команды, необходимые для вставки правильного SEI? cxrodgers 5 лет назад 0

1 ответ на вопрос

1
cxrodgers

Спасибо за размещение этого вопроса, это помогло мне понять природу проблемы, с которой я столкнулся. У меня есть решение, которое, кажется, работает.

В моем случае я использую ffmpeg из репозиториев Ubuntu. Последняя версия, которая смогла декодировать мои файлы libx264, была 2.8.6. После обновления до 2.8.14 или 2.8.15 у меня возникли проблемы с декодированием, которые вы описали. Я не хочу перекодировать мои старые видео, я просто хочу исправить заголовок, чтобы ffmpeg мог правильно идентифицировать ошибку, которая была допущена во время оригинального кодирования, и правильно воспроизвести их.

Итак, сначала я скачал статический двоичный файл, который включает в себя самую последнюю версию ffmpeg, v4 . Я связал этот двоичный файл в ffmpeg4моей системе, чтобы я мог контролировать, какую версию я использую. Нам нужны некоторые новые функции, которые были введены после 2.8 (не совсем точно, когда). Если у вас уже есть более новая версия FFmpeg установлена, просто использовать, что и заменить ffmpeg4с ffmpegкомандами ниже.

Теперь извлеките необработанный битовый поток из вашего испорченного видео (назовите его BROKEN.mkv).

ffmpeg4 -i BROKEN.mkv -vcodec copy -an -bsf:v h264_mp4toannexb raw.h264 

Я не уверен, что флаг h264_mp4toannexb необходим, он может быть автоматически вставлен для этого формата.

Теперь поместите поток битов в новый контейнер mp4 и исправьте информацию о старой глючной сборке x264 в заголовке SEI .

ffmpeg4 -r 30 -i raw.h264 -avoid_negative_ts 1 -bsf:v h264_metadata='sei_user_data=dc45e9bde6d948b7962cd820d923eeef+x264 - core 150' -c copy FIXED.mp4 

Поток битов не содержит информации о метках времени, поэтому вы получите здесь множество предупреждений. Я также обнаружил, что мне пришлось вручную установить частоту кадров 30 кадров в секунду ( -r 30), потому что в противном случае он угадал некоторую переменную частоту кадров между 25 и 30 кадров в секунду. Я не знаю, как правильно извлекать временные метки или правильно смешивать их в новый контейнер. Пожалуйста, дайте мне знать, если у вас есть исправление! Многие люди рекомендуют, -fflags +genptsно это, похоже, ничего не делает для меня. Наконец, я добавил -avoid_negative_ts 1, чтобы метка времени первого кадра была неотрицательной.

Наконец, и это необязательно, если вы хотите поместить результаты в контейнер MKV, вы можете сделать это

ffmpeg4 -i FIXED.mp4 -c copy FIXED.mkv 

Зачем сначала конвертировать в MP4, а затем в MKV ? Кажется, что контейнер MKV просто откажется работать без отметок времени, но MP4 сделает это и просто выдаст предупреждения. Затем вы можете конвертировать в MKV без предупреждения.

После всего этого у меня работают файлы MP4 и MKV. Тем не менее, я проверил некоторые кадры, и есть небольшие изменения (изменения яркости порядка ~ 2 уровней). Я не понимаю, почему это произошло, потому что это должно было быть без потерь. Пожалуйста, дайте мне знать, если у вас есть предложения о том, как это можно сделать лучше.

Изменить: я заметил, что некоторые из моих отметок времени были отрицательными в контейнере MP4, начиная с -0,066667 с. После перемещения в контейнер MKV все отрицательные метки времени стали нулями. Добавление -output_ts_offset 0.066667к команде исправило это и заставило их начинаться с нуля. Я не понимаю, почему это началось в -0.066667 все же.

Редактировать 2: Лучший способ удалить отрицательные метки времени - использовать «-avoid_negative_ts 1» при кодировании mp4.

@ Гьян Я вижу, что вы опубликовали много хороших ответов о метках времени, не могли бы вы подсказать, как правильно указывать метки времени в контейнере при предоставлении необработанного потока h264? спасибо за любые советы !! cxrodgers 5 лет назад 0

Похожие вопросы