L'audio FFMPEG n'est pas synchronisé lors du transcodage (démultiplexage) depuis DV

2

Je suis coincé avec ce problème depuis des mois. J'ai plus de 50 cassettes DV (provenant d'un ancien caméscope Sony) à convertir en un format plus moderne et utilisable (très probablement le format H264). J'ai commencé par extraire les fichiers sur mon PC (via Firewire) à l'aide de DVGRAB. J'avais deux options: extraire les données RAW de la bande DV, ce qui donnait un fichier multiplexé OU le démultiplexage et l'enregistrement dans un fichier DVI.

C'est là que les problèmes ont commencé. L'enregistrer dans un fichier DVI entraînait une désynchronisation de l'audio. Je pensais que c’était un problème avec DVGRAB, j’ai donc sauvegardé les fichiers RAW (correctement synchronisés) et j’ai voulu les traiter avec ffmpeg.

Il s'avère que peu importe la façon dont je démultiplexe, l'audio est toujours désynchronisé. AVANT de dire quoi que ce soit à propos de la fréquence d'échantillonnage - les différences audio sont de longueur absolument aléatoire. Une bande d'une heure peut avoir entre 0,1 et 4 secondes de retard audio à la fin.

Voici un exemple de fichier que j'ai divisé en fichiers audio et vidéo distincts pour vérifier les différences.

# 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

Celui-ci diffère de 1,448 secondes. Comme je l'ai dit, les différences varient grandement.

Quant à la solution. Je pourrais simplement étirer l'audio et le combiner avec la vidéo (j'ai déjà testé cela), mais je ne peux pas être certain que l'audio sera synchronisé quelque part au milieu de l'enregistrement.

Je pense avoir identifié la source de ce comportement. À chaque fois que j'allume ou éteint la caméra (pour démarrer et arrêter l'enregistrement), la vidéo commence un peu plus vite que l'audio. Donc, plus il y a de "fragments" sur la bande, plus ces différences s’additionnent.

Comment puis-je réparer cela? Existe-t-il un moyen de démultiplier l'audio et la vidéo avec des horodatages, de sorte qu'après la conversion, ils s'ajoutent correctement? Ou est-il possible de combler ces lacunes dans l'audio afin que les deux flux aient la même taille au départ?

Wojciech
la source
Quelle est la commande pour démultiplier les fichiers bruts?
Gyan
Le fichier .dv brut est multiplexé par nature. FFMPEG le démultiposte par défaut lors de la conversion en un conteneur quelconque.
Wojciech
Ok, plutôt, quelle est votre commande de conversion? J'ai oublié votre transcodage.
Gyan
J'ai essayé une douzaine de combinaisons. Rien de spécial cependant: avconv -f dv -i ./46raw.dv -f mp4 -acodec libvo_aacenc -b: un 256k -vcodec libx264 -b: v 4000k -y ./46raw.aac.mp4
Wojciech
1
avconv! = ffmpeg. Si c'est juste un problème de compensation, vous pouvez utiliser -af adelay=1000|1000 où 1000 est le délai en ms.
Gyan

Réponses:

8

Voici trois tentatives génériques pour résoudre ce problème:

Méthode 1a Utiliser l'heure du système comme horodatage

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

Méthode 1b Utilisez le ré-échantillonneur avec le drapeau pour injecter un silence lorsque les horodatages audio entrants ont des espaces

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

Méthode 2 Fusionner avec un son factice

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

Méthode 3 Combinaison de ce qui précède

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

Vous pouvez tester chacun d’eux pendant une courte durée en insérant -t N par exemple. -t 20 pour un test de 20 secondes.

Si l'un d'entre eux fonctionne, nous pouvons alors encapsuler la sortie au format MP4.

Gyan
la source
Option 2: Le graphique de filtre simple 'amerge' devait avoir exactement 1 entrée et 1 sortie. Cependant, il avait> 1 entrée (s) et 1 sortie (s). Veuillez ajuster ou utiliser un filtre complexe (-filter_complex) à la place. L'option 1. génère beaucoup d'erreurs: [aac @ 0x9160040] L'entrée de la file d'attente est rétablie dans le temps [mp4 @ 0x915e1c0] DTS non monotone dans le flux de sortie 0: 1; précédent: 70000289337917, courant: 70000289337250; changer à 70000289337918. Cela peut entraîner des horodatages incorrects dans le fichier de sortie. Et s’arrête après environ 90 Mo d’un fichier de sortie illisible.
Wojciech
Maintenant, essayez les 3 commandes. En outre, testez la lecture avec ffplay i.e. ffplay method1.ts
Gyan
Les options 1a et 3 produisent des fichiers de 90 Mo et 20 Mo respectivement avec peu ou pas de vidéo. Les options 1b et 2 produisent la totalité de la vidéo, mais n’aident en rien le retard :(
Wojciech
Faire ceci à l'aveuglette est futile. Pouvez-vous envoyer un peu du fichier brut, par exemple, 20 secondes ou suffisamment pour observer une perte de synchronisation avec votre commande d'origine?
Gyan
0

J'ai enfin résolu le problème - c'est un excès, mais ça fonctionne.

J'ai réalisé que si je copie le fichier .dv dans un autre conteneur, l'audio et la vidéo sont évidemment désynchronisés. Ensuite, je voulais couper ce fichier à un segment d’une minute à partir de la 51e minute (-ss de 51h00 à 60 ans), il était évidemment encore désynchronisé.

Cependant, lorsque j'ai utilisé la même coupe (-ss 51:00 -t 60) sur le fichier .dv original, il était synchronisé! J'ai donc écrit un script qui coupait le fichier .dv en un segment d'une seconde par seconde et l'enregistrait dans des fichiers séparés (oui, plus de 3 600 fichiers par .dv). Pas d'encodage, copiez simplement la copie dans un nouveau conteneur (avi). Ensuite, j'ai utilisé -f concat, pour mettre les minuscules fichiers dans un seul fichier avi, qui était synchronisé maintenant! Les lacunes sont inaudibles! Tout ce qui restait était d'encoder H264 et AAC en MP4.

J'ai exécuté le script sur mon serveur domestique qui broyait les 50 fichiers .dv pendant quelques jours, mais c'est terminé!

MERCI A TOUS DE VOUS AIDER! J'ai beaucoup appris sur ffmpeg et a / v en général.

Wojciech
la source
Il s’agit d’une solution de contournement efficace, mais qui ne résout pas le problème de synchronisation, car chaque habillage DV en AVI est soumis à la même erreur que lors de la copie du fichier .dv complet .avi. Cette solution de contournement empêche les minuscules différences, le cas échéant, dans chaque segment d'une seconde de se mettre en cascade et de s'accumuler, chaque seconde constituant un fichier séparé. Vous aurez encore quelques AVI pour lesquels il y a un asynchrone notable, mais ceux-ci n'affectent pas les segments AVI restants. Si vous le pouvez, je suis toujours disposé à travailler sur un court segment du fichier .dv brut pour voir si cela peut être résolu de manière précise, en une seule étape.
Gyan
Je suis conscient que les lacunes sont toujours là, mais étirer l'audio serait un bon choix pour le même type de solution. C'est assez bien pour moi. En ce qui concerne l'échantillon - l'envoi d'un petit échantillon n'a pas de sens, car l'erreur est au maximum de 3 secondes en 1 heure et est inférieure à 0,1%. Je ne peux pas vous envoyer un fichier entier car ce sont les vidéos de la famille de ma soeur (elle n'approuverait pas). Si je réussis à obtenir une cassette vierge, je pourrais vous préparer un nouvel échantillon (filmer un film sur une télévision vous donnerait une bonne référence de synchronisation).
Wojciech
Ma solution souhaitée ne nécessite pas d'étirement de l'audio. Raw DV n'a pas d'horodatage, mais l'audio est entrelacé de manière synchrone. Mon bricolage aurait donc pour but de préserver cette relation chronologique. Si vous avez le temps, je suis prêt à travailler avec un échantillon.
Gyan
0

J'ai une configuration similaire avec le même problème de synchronisation audio non synchro. J'ai également réussi à reproduire un clip avec un son désynchronisé. Si quelqu'un veut des échantillons, s'il vous plaît demander.

J'ai peut-être trouvé une solution à ce problème. Kino est un très vieux logiciel qui ne permet plus de gérer un fichier .dv depuis dvgrab (raw) et de l'exporter à nouveau en tant que fichier .dv ou dv1 / avi (ou dv2 / avi) avec "ré-échantillonnage" de l'audio. Eh bien, la sortie est un corrigée fichier qui sera bien synchronisé avant et après un transcodage 'ffmpeg'.

Il y a des inconvénients. Kino peut arrêter de travailler ou même ne pas travailler du tout, car c'est vieux. Je viens de l'installer à partir de 'aur' (Archi linux) et j'ai pu l'utiliser directement. Il n'y a pas d'interface de ligne de commande. Je ne pouvais pas trouver un moyen d'automatiser cela.

MODIFIER:

Il pourrait y avoir une autre solution. Je pense que le problème est que les bits de démarrage et d'arrêt du flux sont interrompus et que le code temporel se dégrade. J'ai quelques clips qui semblent avoir une date de l'année '2068'. Quoi qu'il en soit, vous pouvez utiliser le "dvgrab" à nouveau pour scinder les clips chaque fois qu'il pense qu'il existe un nouveau flux d'enregistrement:

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

'-a' effectue le fractionnement automatique, '-srt' et '-t' facilitent le suivi des fichiers (construit un srt avec les dates et ajoute la date aux fichiers, respectivement). Cela créera un nouveau fichier pour chaque nouveau courant . Étant donné que le début de chaque flux est synchronisé, vous pouvez les définir individuellement. Il semble que chaque fichier contienne le code temporel de la "session" d'origine (comme l'appelle dvgrab). Par conséquent, si vous concattez tous les fichiers directement avec ffmpeg, vous obtenez toujours le même décalage.

Noeljunior
la source