FFMPEG аудио не синхронизируется при перекодировании (демультиплексировании) с DV

12525
Wojciech

Я застрял с этой проблемой в течение нескольких месяцев. У меня есть более 50 DV-кассет (от старой видеокамеры Sony), которые необходимо преобразовать в более современный и удобный формат (скорее всего, H264). Я начал с вытягивания файлов на свой компьютер (через FireWire) с помощью DVGRAB. Там у меня было два варианта: извлечение RAW-данных с DVD-ленты, в результате чего был получен мультиплексированный файл ИЛИ демультиплексировать его и сохранить в DVI-файл.

Вот где начались проблемы. Сохранение его в файл DVI привело к несинхронизации звука. Я думал, что это проблема с DVGRAB, поэтому я сохранил файлы RAW (которые синхронизируются правильно) и хотел обработать их с помощью ffmpeg.

Оказывается, что независимо от того, как я это делюкс, звук всегда не синхронизирован. ДО того, как вы скажете что-нибудь о частоте дискретизации - аудио различия имеют абсолютно случайную длину. Часовая лента может иметь задержку звука от 0,1 до 4 секунд в конце.

Вот пример файла, который я разделил на отдельные аудио и видео файлы, чтобы проверить различия.

# ffprobe -i ./video_conversion/13.dv  ffprobe version 2.8.4 Copyright (c) 2007-2015 the FFmpeg developers built with gcc 5.3.0 (GCC) configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-avresample --enable-fontconfig --enable-gnutls --enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libdcadec --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-shared --enable-version3 --enable-x11grab libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100 [dv @ 0x864f2a0] Detected timecode is invalid [dv @ 0x864f2a0] Estimating duration from bitrate, this may be inaccurate Input #0, dv, from './video_conversion/13.dv': Duration: 01:00:45.80, start: 0.000000, bitrate: 28800 kb/s Stream #0:0: Video: dvvideo, yuv420p, 720x576 [SAR 16:15 DAR 4:3], 28800 kb/s, 25 fps, 25 tbr, 25 tbn, 25 tbc Stream #0:1: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s  # ffprobe -i ./video_conversion/tmp/13.mp4 ffprobe version 2.8.4 Copyright (c) 2007-2015 the FFmpeg developers built with gcc 5.3.0 (GCC) configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-avresample --enable-fontconfig --enable-gnutls --enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libdcadec --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-shared --enable-version3 --enable-x11grab libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from './video_conversion/tmp/13.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf56.40.101 Duration: 01:00:45.80, start: 0.000000, bitrate: 5685 kb/s Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 720x576 [SAR 16:15 DAR 4:3], 5683 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default) Metadata: handler_name : VideoHandler  # ffprobe -i ./video_conversion/tmp/13.mp3 ffprobe version 2.8.4 Copyright (c) 2007-2015 the FFmpeg developers built with gcc 5.3.0 (GCC) configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-avisynth --enable-avresample --enable-fontconfig --enable-gnutls --enable-gpl --enable-ladspa --enable-libass --enable-libbluray --enable-libdcadec --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxvid --enable-shared --enable-version3 --enable-x11grab libavutil 54. 31.100 / 54. 31.100 libavcodec 56. 60.100 / 56. 60.100 libavformat 56. 40.101 / 56. 40.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 40.101 / 5. 40.101 libavresample 2. 1. 0 / 2. 1. 0 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.101 / 1. 2.101 libpostproc 53. 3.100 / 53. 3.100 [mp3 @ 0x954c2a0] Skipping 0 bytes of junk at 237. Input #0, mp3, from './video_conversion/tmp/13.mp3': Metadata: encoder : Lavf56.40.101 Duration: 01:00:44.35, start: 0.023021, bitrate: 128 kb/s Stream #0:0: Audio: mp3, 48000 Hz, stereo, s16p, 128 kb/s Metadata: encoder : Lavc56.60 

Этот конкретный отличается на 1,448 секунды. Как я уже сказал, различия сильно различаются.

Что касается решения. Я мог бы просто растянуть аудио и объединить его с видео (я проверял это), но я не могу быть уверен, будет ли звук синхронизирован где-то в середине записи.

Я думаю, что я точно определил источник этого поведения. Всякий раз, когда я включаю или выключаю камеру (например, чтобы начать и остановить запись), видео начинается чуть-чуть быстрее, чем звук. Таким образом, чем больше «фрагментов» на ленте, тем больше эти различия складываются.

Как я могу это исправить? Есть ли способ демультиплексировать аудио и видео с метками времени, чтобы после конвертации они правильно сложились? Или в любом случае заполнить эти пробелы в аудио, чтобы оба потока были одинакового размера для начала?

2
Какая команда для демультиплексирования сырых файлов? Gyan 8 лет назад 0
Необработанный файл .dv мультиплексируется по своей природе. FFMPEG использует его по умолчанию при преобразовании в любой контейнер. Wojciech 8 лет назад 0
Окей, скорее, какова ваша команда преобразования? Я забыл, что ты транскодируешь. Gyan 8 лет назад 0
Я пробовал дюжину комбинаций. Ничего особенного: avconv -f dv -i ./46raw.dv -f mp4 -acodec libvo_aacenc -b: 256k -vcodec libx264 -b: v 4000k -y ./46raw.aac.mp4 Wojciech 8 лет назад 0
avconv! = ffmpeg. Если это просто проблема смещения, вы можете использовать `-af adelay = 1000 | 1000`, где 1000 - задержка в мс. Gyan 8 лет назад 1
Ошибка ввода. Я использую ffmpeg на одной машине и avconv на другой. В любом случае это не работает. Если бы это была задержка смещения, я бы не стал задавать этот вопрос -_- Разница в длине звуковой дорожки составляет около 0,1-4 с для видео длиной 3600-3700 с. Wojciech 8 лет назад 0
Добавьте `-copyts` в качестве выходного флага и попробуйте. Проверьте с помощью воспроизведения синхронизацию, а не длительность, поскольку этот флаг не будет дополнять аудио для выравнивания длительности. Кроме того, если вы не используете версию старше 15 декабря, внутренний кодировщик AAC теперь стабилен и лучше, чем кодировщик VO. Gyan 8 лет назад 0
Сделано два файла, с и без -copyts. Нет разницы. Все еще отстает. Есть другие идеи? Wojciech 8 лет назад 0
Необработанные файлы имеют хорошую синхронизацию, верно? Как ты играешь в них? Gyan 8 лет назад 0
Очевидно, что сырые файлы хороши. Если бы это было плохо, мой вопрос не имел бы большого смысла. Играл в mplayer они работают нормально. Любая попытка демультиплексировать аудио- и видеопотоки, даже «копировать», и помещать их обратно в любой контейнер приводит к тому, что он не синхронизирован. Ошибка увеличивается по длине видео и достигает смещения 0,1-4 с ближе к концу. Wojciech 8 лет назад 0
Оберните raw в AVI и проверьте: `ffmpeg -f dv -i ./46raw.dv -c copy -map 0 -y. / 46raw.avi` Gyan 8 лет назад 0
Я хотел ответить сразу, но ради честности я проверил это. Извините ... все еще не синхронизировано. Проблема заключается в демультиплексировании потоков. Wojciech 8 лет назад 0
Можете ли вы отрубить первые, скажем, 10 секунд исходного кода и поделиться им? Вам придется использовать `dd` или что-то в этом роде. Gyan 8 лет назад 0
Кроме того, похоже, что демультиплексор DV не играет хорошо с отсутствующим или плохим звуком. Напишите на @rhatr в Твиттере. Он один из кодировщиков кода демультиплексора DV. Gyan 8 лет назад 0
Ну ... Это семейные видео, принадлежащие моей сестре, поэтому мне не очень приятно делиться ими. Может быть, я найду нейтральный фрагмент. Спасибо, что указали на одного из разработчиков. Я не пользуюсь твиттером, но думаю, мне придется. Wojciech 8 лет назад 0
Вы добились прогресса? Gyan 8 лет назад 0
Я связался с Романом (@rhatr) и отправил ему образец видео. Он боролся с этим более недели, но безрезультатно :( Я действительно благодарен за то время, которое он предложил, но это означает, что вопрос сложный: / Я постараюсь проверить, сможет ли это обработать другое программное обеспечение для редактирования видео. Wojciech 8 лет назад 0

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

6
Gyan

Here are three wildcard attempts at solving this issue:

Method 1a Use system time as timestamps

ffmpeg -use_wallclock_as_timestamps 1 -i input.dv \ -c:v libx264 -b:v 4000k -c:a aac -b:a 128k -fflags +genpts method1.ts 

Method 1b Use resampler with flag set to inject silence when input audio timestamps have gaps

ffmpeg -i input.dv -c:v libx264 -b:v 4000k \ -af "aresample=async=1:first_pts=0" -c:a aac -b:a 128k -fflags +genpts method1.ts 

Method 2 Merge with dummy audio

ffmpeg -i input.dv -f lavfi -i "aevalsrc=0:c=2:s=48000" \ -filter_complex "[0:a][1:a]amerge[a]" -map 0:v -map "[a]" -c:v libx264 -b:v 4000k -c:a aac -b:a 128k -ac 2 -shortest method2.ts 

Method 3 Combination of the above

ffmpeg -use_wallclock_as_timestamps 1 -i input.dv -f lavfi -use_wallclock_as_timestamps 1 -i "aevalsrc=0:c=2:s=48000" \ -filter_complex "[0:a][1:a]amerge[a]" -map 0:v -map "[a]" -c:v libx264 -b:v 4000k -c:a aac -b:a 128k -ac 2 -shortest method3.ts 

You can test each of them for a short duration by inserting -t N e.g. -t 20 for a 20 second test.

If any of them work, we can then proceed to wrapping the output as MP4.

Вариант 2: Ожидается, что простой фильтр графа 'amerge' будет иметь ровно 1 вход и 1 выход. Тем не менее, он имел> 1 вход (ов) и 1 выход (ов). Пожалуйста, настройте или используйте сложный фильтр графа (-filter_complex) вместо этого. Вариант 1. Выдает много ошибок: [aac @ 0x9160040] Вход в очередь обратный во времени [mp4 @ 0x915e1c0] Немонотонный DTS в выходном потоке 0: 1; предыдущий: 70000289337917, текущий: 70000289337250; меняется на 70000289337918. Это может привести к неправильным временным меткам в выходном файле. И останавливается после примерно 90 МБ не воспроизводимого выходного файла. Wojciech 8 лет назад 0
Теперь попробуйте 3 команды. Кроме того, протестируйте воспроизведение с помощью ffplay, т.е. `ffplay method1.ts` Gyan 8 лет назад 0
Опции 1a и 3 создают файлы размером 90 МБ и 20 МБ соответственно, практически без видео. Варианты 1b и 2 производят видео целиком, но не помогают в отношении задержки :( Wojciech 8 лет назад 0
Делать это вслепую бесполезно. Можете ли вы отправить немного необработанного файла, скажем, 20 секунд или достаточно, чтобы наблюдать потерю синхронизации с вашей исходной командой? Gyan 8 лет назад 0
0
Wojciech

I've finally solved the issue - it's an overkill, but it works.

I've realized that if I copy the .dv to any other container, the audio and video is obviously out of sync. Then I wanted to cut that file to a 1 minute segment starting at the 51st minute (-ss 51:00 -t 60), it was obviously still out of sync.

However, when I used the same cut (-ss 51:00 -t 60) on the original .dv it was in sync! So what I ended up doing is I wrote a script that cut the .dv file into 1 second segment every second and saved that into separate files (yes over 3600 files per .dv). No encoding, just stream copy to a new container (avi). Then I used -f concat, to put the tiny files into one avi file, that was in sync now! Any gaps are inaudible! All that was left was encoding H264 and AAC into MP4.

I ran the script on my home server that was grinding the 50 .dv files for a couple of days, but now it's done!

THANK YOU ALL FOR YOU HELP! I've learned a lot about ffmpeg and a/v in general.

Это хороший обходной путь, но на самом деле он не решает проблему синхронизации, поскольку при каждом переносе DV в AVI возникает та же ошибка, что и при копировании всего .dv в .avi. Этот обходной путь делает то, что крошечные несоответствия, если таковые имеются, в каждом 1-секундном сегменте от каскадирования и накопления, так как каждая секунда - отдельный файл. У вас все еще будет несколько AVI, где есть заметная асинхронность, но они не влияют на остальные сегменты AVI. Если вы можете, я все еще открыт для работы над коротким сегментом необработанного .dv, чтобы увидеть, может ли это быть точно решено, и в один шаг. Gyan 8 лет назад 0
Я знаю, что промежутки все еще есть, но растягивание звука было бы довольно хорошим решением. Это достаточно хорошо для меня. Насчет выборки - нет смысла посылать небольшую выборку, потому что ошибка составляет не более 3 с за 1 час, а это менее 0,1%. Я не могу отправить вам целый файл, так как это семейное видео моей сестры (она не одобрит). Если мне удастся получить чистую ленту, я мог бы сделать новый образец для работы с вами (съемка фильма по телевизору даст вам хороший синхросигнал). Wojciech 8 лет назад 0
Мое желаемое решение не будет включать растяжение звука. В Raw DV нет меток времени, но звук чередуется синхронно, поэтому моя задача будет направлена ​​на сохранение этой хронологической взаимосвязи. Если у вас когда-нибудь будет время, я готов работать с семплом. Gyan 8 лет назад 0
0
Noeljunior

У меня есть аналогичная установка с той же проблемой аудио из синхронизации. Мне также удалось воспроизвести клип с несинхронизированным звуком. Если кто-то хочет образцы, пожалуйста, спросите.

Возможно, я нашел решение этой проблемы. Kino - очень старое и более не обслуживаемое программное обеспечение, которое может загружать .dv из dvgrab (raw) и снова экспортировать как файл .dv или dv1 / avi (или dv2 / avi) с «повторной выборкой» аудио, Что ж, на выходе получается исправленный файл, который будет хорошо синхронизирован до и после транскодирования ffmpeg.

Есть некоторые недостатки. Кино может прекратить работу или даже вообще не работать, так как она старая. Я только что установил его из 'aur' (Arch linux), и я смог использовать его прямо. Нет интерфейса командной строки. Я не мог найти способ автоматизировать это.

РЕДАКТИРОВАТЬ:

Там может быть другое решение. Я думаю, что проблема в том, что начальные и конечные биты потока каким-то образом нарушаются, а временной код ухудшается. У меня есть несколько клипов с датой 2068 года. В любом случае, вы можете снова использовать 'dvgrab' для разделения клипов каждый раз, когда он думает, что есть новый поток записей:

dvgrab -I input -size 0 -a -format=raw -showstatus -srt -t output 

'-a' выполняет автоматическое разделение, '-srt' и '-t' помогают отслеживать файлы (создает srt с датами и добавляет дату к файлам соответственно). Это создаст новый файл для каждого нового потока . Поскольку начало каждого потока синхронизировано, вы можете «ffmpeg» их по отдельности. Похоже, что каждый файл содержит временный код исходного «сеанса» (как его называет dvgrab), поэтому, если вы объедините все файлы напрямую с помощью ffmpeg, вы все равно не получите синхронизацию.

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