6

Из-за ошибки в старых версиях 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, вероятно, была введена здесь.)

2 ответа2

1

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

В моем случае я использую 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.

0

Преобразованное видео в файл только с необработанным видео

ffmpeg -i VID_1550287359485.mp4 -vcodec copy -an -bsf:v h264_mp4toannexb raw2.h264
ffmpeg -framerate 24 -i raw2.h264  -c copy output-a.mp4

Извлечение аудио из видео в формате mp3

ffmpeg -i VID_1550287359485.mp4 -b:a 192K -vn music2.mp3

Исправление проблемы с аудио и видео длиной

ffprobe -i  music2.mp3  -show_entries  format=duration  -v quiet  -print_format json
ffprobe -i  output-a.mp4  -show_entries  format=duration  -v quiet  -print_format json
ffmpeg  -i music2.mp3 -filter:a atempo="0.827415438" new-latest2.mp3

Повернуть видео на 90 градусов против часовой стрелки

ffmpeg -i output-a.mp4 -vf "transpose=2" output-new.mp4

Объединение видео и аудио для создания выходного файла

ffmpeg -i output-new.mp4 -i new-latest2.mp3 -c:v libx264 -c:a aac -strict experimental -shortest output-second.mp4

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .