ffmpeg concat представляет проблему синхронизации аудио/видео

У меня есть один двухчасовой видеофайл, и я хочу добавить в его начало 10-секундную последовательность заголовков. Длинный файл имеет идеальную аудио/видео синхронизацию от начала до конца. Однако, когда я использую ffmpeg -f concat -i mylist.txt -c copy outfile.mp4для объединения файла заголовка с длинным файлом, звук в длинном файле постепенно выходит из синхронизации, постепенно ухудшаясь, пока в конце 2 часов звук не отстает от видео на целую секунду или две. Я могу понять, почему это concatможет нарушить синхронизацию, но я не понимаю, почему это приведет к постепенному ухудшению синхронизации.

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

Буду очень признателен за любые предложения. Я полуновичок в цифровом видео и столкнулся с крутой кривой обучения, но я учусь. Я использую Ubuntu Linux 16.04 и ffmpeg 2.8.6-1ubuntu2, думаю, это последняя версия ffmpeg. У меня есть около 20 старых двухчасовых семейных видеокассет, которые я оцифровываю.

Фон файла:

  1. Длинный файл представляет собой файл MP4 с использованием H264 и AAC. Он возник как файл .ts, и я использую ffmpeg для его кодирования в формат mp4. Перед объединением файла заголовка он всегда находится в идеальной аудио/видео синхронизации. Разрешение 720х480, битрейт 127. Я снял видео с ленты Sony Handycam Video8 с помощью USB-конвертера Hauppauge Live-2, используя интерфейс командной строки VLC для создания исходного файла .ts. Продолжительность около 120 минут.

  2. Титульный файл я создал в Blender и попытался продублировать формат длинного файла: 720x480, битрейт 127, MP4, содержащий H264 и AAC. На самом деле в нем нет звука, так как это всего лишь два «слайда» текста. (Я знаю, что, вероятно, на самом деле есть звуковая дорожка, созданная Blender, но это просто тишина, поскольку я не добавляю звуковые дорожки к простым заголовкам.) Это всего 10 секунд.

Результаты ffmpeg -i longfile.mp4:

Metadata:
major_brand     : isom
minor_version   : 512
compatible_brands: isomiso2avc1mp41
encoder         : Lavf56.36.100
Duration: 01:17:06.58, start: 0.013000, bitrate: 2134 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p,
720x480 [SAR 32:27 DAR 16:9], 1997 kb/s, 29.97 fps, 29.97 tbr, 29971
tbn, 59.94 tbc (default)
Metadata:
handler_name    : VideoHandler
Stream #0:1(unk): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, 
fltp, 127 kb/s (default)
Metadata:
handler_name    : SoundHandler

Результаты ffmpeg -i titlefile.mp4_

Metadata:
major_brand     : isom
minor_version   : 512
compatible_brands: isomiso2avc1mp41
encoder         : Lavf56.40.101
Duration: 00:00:10.01, start: 0.012000, bitrate: 421 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 
720x480 [SAR 1:1 DAR 3:2], 284 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 
59.94 tbc (default)
Metadata:
handler_name    : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, 
stereo, fltp, 127 kb/s (default)
Metadata:
handler_name    : SoundHandler

Ответы (1)

Бег

ffmpeg -i titlefile.mp4 -vf setdar=16/9 -video_track_timescale 29971 -ac 1 newtitle.mp4

а затем запустите concat с новым заголовком видео.

Современные контейнеры, такие как MP4, имеют метки времени представления , которые обозначаются относительно временной базы. Таким образом, если значение временной базы равно 1/500, а PTS кадра равно 200, это указывает видеопроигрывателю показывать этот кадр с размером 200*(1/500) = 0,4 секунды. Значения , показанные в показаниях, являются обратными значениями этой временной развертки. Теперь демультиплексор concat из-за конструктивного упущения (или выбора!?) не перемасштабирует значения PTS так, чтобы все входы имели кадры с PTS, использующими одну и ту же временную базу. Ваши два видео имеют разные ТБ, поэтому длинное видео после объединения ускоряется. Разница в восприятии незаметна, за исключением звукового дрейфа. Чтоtbntbnзначение для видеопотока. Аудиопотоки имеют собственную временную базу, связанную с частотой дискретизации, которая здесь одинакова.

Это работает! Спасибо огромное! Кроме того, спасибо за многочисленные комментарии к подобным темам, которые вы оставили. Это очень ценится.
Хорошо, это очень помогло с моей аналогичной проблемой. Не могли бы вы немного подробнее рассказать о временной шкале аудио? Как мне проверить, что они находятся на той же временной базе? (Я не вижу значение tbn на выходе). И исправляю ли я его таким же образом?
Временные базы аудио обычно совпадают с частотой дискретизации. Вы можете запустить ffprobe -select_streams a -show_entries stream=time_base -of compact=p=0 video.mp4, чтобы получить значение. Для аудио я бы просто рекомендовал перекодировать с явно заданной частотой дискретизации, -ar 48000т.е.