ffmpeg joint deux fichiers mp4 avec ffmpeg en ligne de commande

29

Je peux joindre avec succès plusieurs fichiers à l'aide de la commande suivante:

ffmpeg -f concat -i input.txt -codec copy output.mp4

Le seul problème avec cette commande est que vous devez lire les chemins de fichier à partir du fichier texte appelé input.txt avec le contenu suivant:

file 'C:\Users\fabio\Downloads\Super\Sharks\01.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\02.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\03.mp4'

Existe-t-il un moyen d'atteindre le même objectif sans avoir à lire les chemins de fichiers à partir d'un fichier? J'ai essayé ce qui suit sans succès:

ffmpeg -f concat -i file "C:\a\b\01.mp4" file "C:\a\b\02.mp4" -codec copy output.mp4
ffmpeg -f concat -i "C:\a\b\01.mp4" "C:\a\b\02.mp4" -codec copy output.mp4

Dois-je utiliser une commande différente?

Fabio Delarias
la source
1
en relation: stackoverflow.com/questions/7333232/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Réponses:

37

Mise à jour 2019:

Comme mentionné dans les commentaires, Stack Overflow a une excellente description des options disponibles pour la concaténation, ainsi qu'une discussion sur la méthode à utiliser en fonction des types de fichiers que vous utilisez:

Comment concaténer deux fichiers MP4 à l'aide de FFmpeg?

Réponse originale de 2016:

Vous devriez pouvoir utiliser la méthode du protocole concat pour combiner les fichiers:

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

De plus, le manuel FFmpeg décrit une méthode spécifique pour les fichiers MP4, afin de les concaténer sans perte, mais nécessite que vous créiez des fichiers temporaires (ou des canaux nommés):

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Carson Darling
la source
1
La première commande a fonctionné pour moi comme un beurre ... il a fallu 2 à 3 secondes pour concaténer mes 6 fichiers mp4 en fichier de sortie (239 Mo environ).
Sachin
22
La première commande n'a pas fonctionné pour moi. Il vient de copier le premier fichier.
Luis A. Florit
3
Cela ne fonctionne pas, il a juste copié le premier fichier dans output.mp4.
crmpicco
2
La concaténation au niveau du fichier ne fonctionne pas pour MP4, donc le protocole de concaténation n'est pas recommandé pour ce format et ne fonctionnera généralement pas.
llogan
1
@brasofilo Merci pour le lien. Cela se fait depuis longtemps, mais j'ai mis à jour la réponse pour pointer les gens dans cette direction.
Carson Darling
5

Vous pouvez remplacer le fichier par liste en sortant la liste stdoutet en lisant la liste par stdinpar ffmpeg:

(echo file 'a.mp4' & echo file 'b.mp4') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "result.mp4"
Qwertiy
la source
En utilisant ffmpeg version 2.4.3-tessus sur Mac OS 10.12.6, cela génère simplement une erreur: "Option non reconnue 'protocol_whitelist'". Sans l'option protocol_whitelist, il semble simplement faire une copie du deuxième fichier MP4.
James
2

Non, il semble qu'il n'y ait aucun moyen d'utiliser le démultiplexeur ffmpeg concat sur une seule ligne de commande sans pirater. Vous devez créer le fichier texte d'entrée avec la liste des fichiers. Je pensais que c'était étrange moi-même, peut-être que quelqu'un l'ajouterait à FFMpeg à une date ultérieure.

La réponse acceptée à cette question utilise le protocole concat, pas le démultiplexeur concat qui est ce que l'OP a demandé.

georgiecasey
la source
1
En fait, il y en a. stdin.
Qwertiy
le protocole concat ne doit pas être utilisé avec MP4 ou tout autre format nécessitant un en-tête global.
llogan
1

Vous pouvez toujours le faire dans un script sans modifier la commande. Quelque chose comme:

echo "file fname1" >$$.tmp    #single redirect creates or truncates file
echo "file fname2" >>$$.tmp   # double redirect appends
echo "file fname3" >>$$.tmp   # do as many as you want.

ffmpeg -f concat -i $$.tmp -codec copy output.mp4

rm $$.tmp  # just to clean up the temp file. 
           # For debugging, I usually leave this out.

Le $$ se développe au pid du shell exécutant la commande, donc le nom du fichier sera différent à chaque fois que vous l'exécuterez. vous pouvez donc utiliser $$. txt si vous préférez. Ou autre chose...

Vous pouvez également utiliser ici des fichiers pour ajouter un tas de données au fichier:

cat <<EOF >$$.tmp
file fname1
file fname2
file fname3
EOF

bash La substitution de variable fonctionne, vous pouvez donc déterminer par programme le contenu du fichier, il n'a pas besoin d'être corrigé. J'intègre ce genre de trucs dans les boucles tout le temps. Enfin, la redirection fonctionne de la même manière que ci-dessus, donc> $$. Tmp tronque puis écrit, >> $$. Tmp ajoute.

Richard Betel
la source
2
La question demande: "existe-t-il un moyen d'atteindre le même objectif sans avoir à lire les chemins de fichier à partir d'un fichier?" Tout ce que vous avez fait est de fournir un moyen d'écrire les chemins de fichier dans un fichier (avant de lire les chemins de fichier à partir du fichier). Cela ne répond pas à la question.
Scott