Audio FFMPEG tidak sinkron saat transcoding (demuxing) dari DV

3

Saya sudah terjebak dengan masalah ini selama berbulan-bulan. Saya memiliki lebih dari 50 kaset DV (dari dan camcorder Sony lama) untuk dikonversi ke format yang lebih modern dan bermanfaat (kemungkinan besar H264). Saya sudah mulai dengan menarik file ke PC saya (melalui firewire) menggunakan DVGRAB. Di sana saya memiliki dua opsi: menarik data RAW dari kaset dv, menghasilkan file yang di-mux atau mendemuksikannya dan menyimpannya ke file DVI.

Di situlah masalah dimulai. Menyimpannya ke file DVI mengakibatkan audio menjadi tidak sinkron. Saya pikir ini masalah dengan DVGRAB jadi saya menyimpan file RAW (yang disinkronkan dengan benar) dan ingin memprosesnya dengan ffmpeg.

Ternyata bagaimanapun saya demux, audionya selalu tidak sinkron. SEBELUM Anda mengatakan apa pun tentang frekuensi pengambilan sampel - perbedaan audionya sangat panjang acak. Rekaman satu jam dapat memiliki antara 0,1 dan 4 detik audio lag pada akhirnya.

Berikut ini contoh file yang telah saya bagi menjadi file audio dan video terpisah untuk memeriksa perbedaannya.

# 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

Yang satu ini berbeda dengan 1,448 detik. Seperti yang saya katakan perbedaannya sangat bervariasi.

Adapun solusinya. Saya hanya bisa meregangkan audio dan menggabungkannya dengan video (saya sudah mengujinya), tapi saya tidak bisa memastikan apakah audio akan disinkronkan di suatu tempat di tengah rekaman.

Saya pikir saya sudah menunjukkan sumber perilaku ini. Setiap kali saya menghidupkan atau mematikan kamera (untuk memulai dan berhenti merekam) video mulai sedikit lebih cepat daripada audio. Jadi semakin banyak "fragmen" yang ada di rekaman, semakin banyak perbedaan ini bertambah.

Bagaimana saya bisa memperbaikinya? Apakah ada cara untuk mendemosikan audio dan video dengan cap waktu, sehingga setelah konversi mereka akan bertambah dengan benar? Atau apakah ada cara untuk mengisi celah ini dalam audio, sehingga kedua aliran memiliki ukuran yang sama untuk memulai?

Wojciech
sumber
Apa perintah untuk mendemux file mentah?
Gyan
File .dv mentah di-multiplex oleh sifatnya. FFMPEG mendemosikannya secara default saat mengonversinya ke wadah apa pun.
Wojciech
Oke, lebih tepatnya, apa perintah konversi Anda? Saya lupa Anda melakukan transkode.
Gyan
Saya sudah mencoba selusin kombinasi. Tidak ada yang istimewa: avconv -f dv -i ./46raw.dv -f mp4 -acodec libvo_aacenc -b: a 256k -vcodec libx264 -b: v 4000k -y ./46raw.aac.mp4
Wojciech
1
avconv! = ffmpeg. Jika ini hanya masalah offset, Anda dapat menggunakan di -af adelay=1000|1000mana 1000 adalah keterlambatan dalam ms.
Gyan

Jawaban:

10

Berikut adalah tiga upaya wildcard untuk memecahkan masalah ini:

Metode 1a Gunakan waktu sistem sebagai cap waktu

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

Metode 1b Gunakan resampler dengan flag yang diatur untuk menyuntikkan keheningan ketika cap waktu audio input memiliki celah

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

Metode 2 Menggabungkan dengan audio boneka

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

Metode 3 dari 3: Kombinasi di atas

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

Anda dapat menguji masing-masing untuk jangka waktu pendek dengan memasukkan -t Nmis -t 20untuk tes 20 detik.

Jika ada yang berfungsi, kita dapat melanjutkan untuk membungkus hasilnya sebagai MP4.

Gyan
sumber
Opsi 2: Filtergraph sederhana 'amerge' diharapkan memiliki tepat 1 input dan 1 output. Namun, ia memiliki> 1 input dan 1 output. Silakan sesuaikan, atau gunakan filtergraph yang kompleks (-filter_complex) sebagai gantinya. Opsi 1. Memberikan banyak kesalahan: [aac @ 0x9160040] Input antrian mundur dalam waktu [mp4 @ 0x915e1c0] DTS yang tidak monoton dalam aliran output 0: 1; sebelumnya: 70000289337917, saat ini: 70000289337250; mengubah ke 70000289337918. Ini dapat menghasilkan cap waktu yang tidak benar dalam file output. Dan berhenti setelah sekitar 90MB dari file output yang tidak dapat dimainkan.
Wojciech
Sekarang, coba 3 perintah. Juga, uji pemutaran dengan ffplay yaituffplay method1.ts
Gyan
Opsi 1a dan 3 masing-masing menghasilkan 90MB dan 20MB file dengan sedikit atau tanpa video. Pilihan 1b dan 2 menghasilkan keseluruhan video, tetapi tidak membantu sehubungan dengan penundaan :(
Wojciech
Melakukan ini secara membabi buta adalah sia-sia. Bisakah Anda mengirim sedikit file mentah, katakanlah, 20 detik, atau cukup untuk mengamati hilangnya sinkronisasi dengan perintah asli Anda?
Gyan
0

Saya akhirnya memecahkan masalah - ini adalah pembunuhan yang berlebihan, tetapi berhasil.

Saya menyadari bahwa jika saya menyalin .dv ke wadah lain, audio dan video jelas tidak sinkron. Lalu saya ingin memotong file itu ke segmen 1 menit mulai dari menit ke-51 (-ss 51:00 -t 60), itu jelas masih tidak sinkron.

Namun, ketika saya menggunakan potongan yang sama (-ss 51:00 -t 60) pada .dv yang asli, file itu sinkron! Jadi apa yang akhirnya saya lakukan adalah saya menulis sebuah skrip yang memotong file .dv menjadi segmen 1 detik setiap detik dan menyimpannya ke file yang terpisah (ya lebih dari 3.600 file per .dv). Tanpa pengodean, cukup streaming salinan ke wadah baru (avi). Lalu saya menggunakan -f concat, untuk meletakkan file-file kecil ke dalam satu file avi, yang sudah disinkronkan sekarang! Setiap celah tidak terdengar! Semua yang tersisa adalah pengkodean H264 dan AAC ke MP4.

Saya menjalankan skrip di server rumah saya yang sedang menggiling 50 file .dv selama beberapa hari, tetapi sekarang sudah selesai!

TERIMA KASIH SEMUA UNTUK ANDA BANTUAN! Saya telah belajar banyak tentang ffmpeg dan a / v secara umum.

Wojciech
sumber
Ini adalah solusi yang baik tetapi tidak benar-benar menyelesaikan masalah sinkronisasi karena setiap pembungkus DV ke AVI mengalami kesalahan yang sama dengan yang Anda miliki saat menyalin seluruh .dv ke .avi. Apa solusi ini lakukan adalah mencegah perbedaan kecil, jika ada, di setiap segmen 1 detik mengalir dan terakumulasi karena setiap detik adalah file yang terpisah. Anda masih memiliki beberapa AVI di mana ada async yang terlihat, tetapi itu tidak mempengaruhi segmen AVI yang tersisa. Jika Anda bisa, saya masih terbuka untuk mengerjakan segmen pendek dari .dv mentah untuk melihat apakah ini dapat diselesaikan secara akurat, dan dalam satu langkah.
Gyan
Saya sadar bahwa celah masih ada, tetapi meregangkan audio akan cukup mengunyah solusi yang sama. Ini cukup baik untukku. Tentang sampel - ada sedikit akal mengirim sampel kecil, karena kesalahan paling banyak 3s dalam 1 jam dan itu kurang dari 0,1%. Saya tidak dapat mengirimi Anda seluruh file karena ini adalah video keluarga kakak saya (dia tidak akan menyetujuinya). Jika saya berhasil mendapatkan kaset kosong, saya bisa membuat sampel baru untuk Anda kerjakan (memfilmkan film di TV akan memberi Anda referensi sinkronisasi yang baik).
Wojciech
Solusi yang saya inginkan tidak akan melibatkan peregangan audio. Raw DV tidak memiliki stempel waktu, tetapi audionya disisipkan dalam sinkronisasi, jadi pemutaran saya akan ditujukan untuk menjaga hubungan kronologis itu. Jika Anda pernah mendapatkan waktu, saya siap bekerja dengan sampel.
Gyan
0

Saya memiliki pengaturan serupa dengan audio yang sama dari masalah sinkronisasi. Saya juga berhasil mereproduksi klip dengan audio yang tidak sinkron. Jika ada yang mau sampel, silakan tanyakan.

Saya mungkin telah menemukan solusi untuk masalah ini. Kino sudah sangat tua dan tidak lagi menggunakan perangkat lunak yang memiliki kemampuan untuk memuat .dv dari dvgrab (mentah) dan mengekspor lagi sebagai file .dv atau dv1 / avi (atau dv2 / avi) dengan "sampel ulang" audio. . Nah, hasilnya adalah file yang diperbaiki yang akan disinkronkan dengan baik sebelum dan sesudah transcode 'ffmpeg'.

Ada beberapa kelemahan. Kino dapat berhenti bekerja atau bahkan tidak akan bekerja sama sekali karena ini sudah tua. Saya baru saja menginstalnya dari 'aur' (Arch linux) dan saya dapat menggunakannya secara langsung. Tidak ada antarmuka baris perintah. Saya tidak dapat menemukan cara untuk mengotomatisasi ini.

SUNTING:

Mungkin ada solusi lain. Saya pikir masalahnya adalah bit mulai dan berhenti aliran entah bagaimana rusak, dan kode waktu semakin buruk. Saya memiliki beberapa klip tampaknya memiliki tanggal dari tahun '2068'. Bagaimanapun, Anda dapat menggunakan 'dvgrab' lagi untuk memisahkan klip setiap kali ia berpikir ada aliran rekaman baru:

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

'-a' melakukan pemisahan otomatis, '-srt' dan '-t' membantu melacak file (membangun srt dengan tanggal dan menambahkan tanggal ke file, masing-masing). Ini akan membuat file baru untuk setiap aliran baru . Karena setiap awal aliran disinkronkan, Anda dapat 'ffmpeg' secara individual. Tampaknya setiap file berisi kode waktu dari "sesi" asli (seperti dvgrab menyebutnya) jadi, jika Anda menyatukan semua file langsung dengan ffmpeg Anda masih mendapatkan sinkronisasi yang sama.

Noeljunior
sumber