web-dev-qa-db-fra.com

FFmpeg concat vidéo et audio désynchronisés

La jonction de plusieurs fichiers à l'aide de ffmpeg concat semble entraîner une incompatibilité des horodatages ou des décalages pour l'audio. J'ai essayé avec plusieurs vidéos et j'ai remarqué le même problème pour h.264/MP4.

En utilisant concat et l'encodage , la vidéo semble fonctionner correctement. L'audio reste synchronisé car ffmpeg effectue les calculs de conversion complets et semble tout faire correctement.

Cependant, la simple concaténation des vidéos sans aucune transformation ou encodage entraîne un problème de synchronisation qui augmente lentement. De toute évidence, encoder les vidéos plutôt que de simplement les rejoindre entraînera une perte d'informations/de qualité, je préfère donc trouver un moyen de contourner ce problème.

J'ai essayé plusieurs drapeaux pour régler ce problème qui semble être basé sur les horodatages. Aucun de ceux-ci ne semble cependant résoudre le problème.

ffmpeg -f concat -fflags +genpts -async 1 -i segments.txt test.mov
ffmpeg -auto_convert 1 -f concat -fflags +genpts -async 1 -i segments.txt -c copy test2.mov
ffmpeg -f concat -i segments.txt -c copy -fflags +genpts test3.mp4
ffmpeg -f concat -fflags +genpts -async 1 -i segments.txt -copyts test4.mov
ffmpeg -f concat -i segments.txt -copyts test5.mov
ffmpeg -f concat -i segments.txt -copyts -c copy test6.mov
ffmpeg -f concat -fflags +genpts -i segments.txt -copyts -c copy test7.mov

Remarque: toutes les autres questions que j'ai pu trouver sur SO semblent "résoudre" le problème en recodant simplement les vidéos. Ce n'est pas une bonne solution.

Mise à jour

J'ai réalisé que le concat n'était pas le problème. L'ensemble d'origine des clips avait des horodatages mal assortis. D'une certaine manière, concat + encodage a résolu le problème, mais je ne veux pas ré-encoder les vidéos et perdre la qualité à chaque fois.

ffmpeg -y -ss 00:00:02.750 -i input.MOV -c copy -t 00:00:05.880 output.MOV

Ce qui a donné les données suivantes

ffprobe -v quiet -show_entries stream=start_time,duration output.MOV

start_time=-0.247500
duration=6.131125
start_time=-0.257333
duration=6.155333

Depuis lors, j'ai essayé d'utiliser -tom et -t à différents endroits avec -af apad -c:v copy et je n'ai toujours pas réussi à obtenir la même durée.

Voici la sortie ffprobe complète

Voici l'original (rouge) vs le segment (vert)

Fichiers d'exemples détaillés

J'ai enregistré un exemple de vidéo, ajouté les commandes pour le découper, puis le concaténer. http://davidpennington.me/share/audio_sync_test_video.Zip

21
Xeoncross

Ce processus en deux étapes devrait fonctionner

Étape 1 Supprimez l'audio dans chaque segment

ffmpeg -i segment1.mov -af apad -c:v copy <audio encoding params> -shortest -avoid_negative_ts make_zero -fflags +genpts padded1.mov

Ou

Générez des segments avec des flux synchronisés

ffmpeg -y -ss 00:00:02.750 -i input.MOV -c copy -t 00:00:05.880 -avoid_negative_ts make_zero -fflags +genpts segment.MOV

Étape 2 Concat

ffmpeg -f concat -i segments.txt -c copy test.mov

segments.txt se compose des noms des fichiers remplis.

14
Gyan

Je lutte avec celui-ci depuis un certain temps également. En particulier lorsque vous travaillez avec des fichiers MTS Panasonic AVCHD. Ma solution actuelle est de les concaténer au niveau du système d'exploitation et non ffmpeg. Je le fais sur Windows et ça ressemble à ceci:

COPY /b input_1.mts + input_2.mts + input_3.mts output.mts

Sous Linux, cela devrait ressembler à:

$ cat input_1.mts input_2.mts input_3.mts > output.mts

Vous pouvez rechercher de la documentation pour la concaténation binaire windows et linux .

Cette méthode de concaténation telle qu'apposée au transcodage est la voie à suivre si le format d'origine fonctionne pour vous. Cette méthode n'utilise pratiquement aucun traitement CPU et préserve la qualité d'origine. Un gagnant-gagnant lorsqu'il s'agit de médias en vrac de haute qualité.

4
salmore

vous pouvez utiliser filter_complex pour concaténer différentes options en une seule fois

fmpeg -i input1.mp4 -i input2.webm \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" <encoding options> output.mkv
2
flower

J'ai rencontré un problème similaire et j'ai trouvé une solution qui fonctionnait, du moins pour moi. Dans mon cas, je concaténais également des fichiers et j'ai trouvé des problèmes de synchronisation audio/vidéo avec iOs, mais pas avec Windows (par exemple, le lecteur multimédia VLC n'a montré aucun problème de synchronisation en utilisant le même fichier mp4). Le symptôme pour les iOs jouant ce mp4 concaténé était initialement une bonne synchronisation suivie d'une perte croissante de synchronisation pendant la lecture du film, avec un son plus rapide que la vidéo. Fait intéressant, la synchronisation pourrait être restaurée temporairement en déplaçant le curseur de progression du film à n'importe quel point du film, mais la synchronisation serait à nouveau perdue au fur et à mesure que le film continuerait à jouer dans iOs. En lisant le même film simultanément dans iOs et Windows VLC, et initialement synchronisé aussi bien que possible, en observant l'évolution de l '"écho" entre eux, j'ai conclu que l'audio iOs allait trop vite (en supposant que Le lecteur Windows est correct).

Pour moi, la solution était d'ajouter l'option de filtre audio -af aresample=async=1000 à la commande ffmpeg, que j'ai trouvée comme exemple dans la documentation en ligne de ffmpeg et utilisée textuellement. Je ne sais pas si ce paramètre est optimal, mais le résultat a été un mp4 avec l'audio et la vidéo restant synchronisés lorsqu'ils sont joués à la fois par iOs et VLC. Cette option ffmpeg a permis une synchronisation iOs appropriée à la fois pendant la concaténation et après lors du recodage du fichier déjà concaténé.

1
Paul

Si les vidéos d'entrée ont été encodées avec les mêmes paramètres, vous pourrez peut-être utiliser mkvmerge de mkvtoolnix à la place:

mkvmerge -o output.mkv file1.mkv + file2.mkv + file3.mkv

J'avais besoin de concaténer des vidéos de différentes sources qui étaient encodées avec différents paramètres, j'ai donc utilisé une commande comme celle-ci pour redimensionner et ré-encoder les vidéos d'entrée en premier:

for f in *.mp4;do width=1280;height=720;ffmpeg -i $f -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" -c:v libx264 -crf 22 -preset slow -pix_fmt yuv420p -c:a libfdk_aac -vbr 3 -ac 2 -ar 44100 ${f%mp4}mkv;done

Certaines vidéos n'avaient pas de canal audio, j'ai donc dû utiliser une commande comme celle-ci pour leur ajouter un canal audio silencieux:

for f in *.mkv;do ffprobe $f|&grep -q '1: Audio'||{ ffmpeg -i $f -f lavfi -i anullsrc -c:a libfdk_aac -shortest -c:v copy temp-$f;mv temp-$f $f; };done

J'ai ensuite concaténé les vidéos en utilisant une commande comme celle-ci:

mkvmerge -o output.mkv $(printf %s\\n *.mkv|sed '1!s/^/+/')
0
nisetama