J'essaye de concaténer deux fichiers MP4 en utilisant ffmpeg. J'ai besoin que ce soit un processus automatique, c'est pourquoi j'ai choisi ffmpeg. Je convertis les deux fichiers en fichiers .ts, puis je les concatène et j'essaie ensuite de coder ce fichier .ts concaténé. Les fichiers sont encodés en h264 et aac et j'espère pouvoir conserver la même qualité ou être aussi proche que possible de l'original.
ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4
Malheureusement, je reçois le message d'erreur suivant renvoyé par ffmpeg lors de l'encodage:
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s
av_interleaved_write_frame(): Error while opening file
Cela se produit à peu près à mi-chemin de l'encodage, ce qui me fait penser que vous ne pouvez pas concaténer deux fichiers .ts ensemble et le faire fonctionner.
J'ai fini par utiliser le format intermédiaire mpg et cela a fonctionné (NOTE: ceci est un exemple dangereux, -qscale 0 réencodera la vidéo ...)
ffmpeg -i 1.mp4 -qscale 0 1.mpg
ffmpeg -i 2.mp4 -qscale 0 2.mpg
cat 1.mpg 2.mpg | ffmpeg -f mpeg -i - -qscale 0 -vcodec mpeg4 output.mp4
FFmpeg a trois méthodes de concaténation.
ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
-filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mkv
Notez que cette méthode effectue un ré-encodage.
$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'
$ ffmpeg -f concat -i mylist.txt -c copy output
Pour les fenêtres:
(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4
ffmpeg -i "concat:input1|input2" -codec copy output
Cette méthode ne fonctionne pas pour de nombreux formats, y compris MP4, en raison de la nature de ces formats et de la concaténation simpliste effectuée par cette méthode.
concat filter: utilisez-le si vos entrées n'ont pas les mêmes paramètres (largeur, hauteur, etc.), ou ne sont pas les mêmes formats/codecs, ou si vous souhaitez effectuer un filtrage. (Vous pouvez uniquement ré-encoder les entrées qui ne correspondent pas afin de partager le même codec et d'autres paramètres, puis utilisez le démultiplexeur concat pour éviter de ré-encoder les autres entrées).
concat demuxer: à utiliser lorsque vous souhaitez éviter un réencodage et que votre format ne prend pas en charge la concaténation au niveau fichier (la plupart des fichiers utilisés par les utilisateurs généraux ne prennent pas en charge la concaténation au niveau fichier).
concat protocol: à utiliser avec les formats qui prennent en charge la concaténation de fichiers .__ (MPEG-1, MPEG-2 PS, DV). Ne pas utiliser avec MP4.
En cas de doute, essayez le démultiplicateur concat.
Voici un moyen rapide (prend moins de 1 minute) et sans perte de le faire sans avoir besoin de fichiers intermédiaires:
ls Movie_Part_1.mp4 Movie_Part_2.mp4 | Perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4
Le "ls" contient les fichiers à joindre Le "Perl" crée le fichier de concaténation à la volée dans un tube La partie "-i -" indique à ffmpeg de lire le tube
(Remarque: mes fichiers ne contenaient ni espaces ni éléments étranges. Vous aurez besoin de la possibilité d’échapper à Shell si vous souhaitez utiliser cette idée avec des fichiers "durs").
POUR LES FICHIERS MP4
Pour les fichiers .mp4 (que j’ai obtenus de DailyMotion.com: un épisode télévisé de 50 minutes téléchargeable en trois parties, sous forme de trois fichiers vidéo .mp4), voici une solution efficace pour Windows 7, et est-ce que NOT implique le réencodage des fichiers.
J'ai renommé les fichiers (file1.mp4, file2.mp4, file3.mp4) de sorte que les parties soient dans le bon ordre pour visionner l'épisode complet de tv.
Ensuite, j'ai créé un fichier batch simple (concat.bat), avec le contenu suivant:
:: Create File List
echo file file1.mp4 > mylist.txt
echo file file2.mp4 >> mylist.txt
echo file file3.mp4 >> mylist.txt
:: Concatenate Files
ffmpeg -f concat -i mylist.txt -c copy output.mp4
Le fichier de commandes et ffmpeg.exe doivent tous deux être placés dans le même dossier que les fichiers .mp4 à joindre. Ensuite, exécutez le fichier de commandes. Cela prend généralement moins de dix secondes pour s'exécuter.
.
Addendum (2018/10/21) -
Si ce que vous recherchiez est une méthode pour spécifier tous les fichiers mp4 du dossier actuel sans beaucoup de retaper, essayez ceci dans votre fichier de commandes Windows batch (DOIT inclure l'option -safe 0):
:: Create File List
for %%i in (*.mp4) do echo file '%%i'>> mylist.txt
:: Concatenate Files
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
Cela fonctionne sur Windows 7, dans un fichier de commandes. Ne pas essayez de l'utiliser sur la ligne de commande, car cela ne fonctionne que dans un fichier batch!
S'ils ne sont pas exactement les mêmes (fichiers codés à 100%, même résolution, même type), vous devez d'abord les transcoder en flux intermédiaires:
ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts
ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts
// now join
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
REMARQUE! : Le résultat sera comme le premier fichier (et non le second)
J'essayais de concaténer trois fichiers audio .mp3
dans un fichier .m4a
et cette commande ffmpeg fonctionne.
Commande d'entrée:
ffmpeg -i input1.mp3 -i input2.mp3 -i input3.mp3 -filter_complex concat=n=3:v=0:a=1 -f MOV -vn -y input.m4a
Signification de: "-filter_complex concat = n = 3: v = 0: a = 1" :
concat signifie que la fonction de jonction (Media) est utilisée.
n signifie que le nombre total de fichiers en entrée est confirmé.
v signifie a la vidéo? utilisez 0 = pas de vidéo, 1 = contient de la vidéo.
a signifie a l'audio? utilisez 0 = pas d'audio, 1 = contient de l'audio.
-f signifie que le format de fichier est forcé (pour voir tous les formats supportés, utilisezffmpeg -formats
)
-vn signifie que la vidéo est désactivée (et que-an
désactive le son si non voulu)
-y signifie écraser les fichiers de sortie (si le fichier de sortie existe déjà).
Pour plus d'informations: utilisez ffmpeg -h full
Affichez toutes les options (y compris toutes les options spécifiques au format et au codec, très long)
sur la base des réponses de rogerdpack et Ed999, j'ai créé ma version .sh
#!/bin/bash
[ -e list.txt ] && rm list.txt
for f in *.mp4
do
echo "file $f" >> list.txt
done
ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt
il joint tous les fichiers *.mp4
du dossier en cours à joined-out.mp4
testé sur mac.
la taille du fichier résultant est la somme exacte de mes 60 fichiers testés. Ne devrait pas être une perte. Juste ce dont j'avais besoin
Voici un script que j'ai créé pour concaténer plusieurs MP4 GoPro en un MP4 720p. J'espère que c'est utile.
#!/bin/sh
cmd="( "
for i; do
cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}
De la documentation ici: https://trac.ffmpeg.org/wiki/Concatenate
Si vous avez des fichiers MP4, vous pouvez les concaténer sans perte en les transcodant d’abord en flux de transport MPEG-2. Avec la vidéo H.264 et le son AAC, vous pouvez utiliser les éléments suivants:
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
Cette approche fonctionne sur toutes les plateformes.
J'avais besoin de la capacité d'encapsuler cela dans un script multi-plateforme, alors j'ai utilisé fluent-ffmpeg
et j'ai mis au point la solution suivante:
const unlink = path =>
new Promise((resolve, reject) =>
fs.unlink(path, err => (err ? reject(err) : resolve()))
)
const createIntermediate = file =>
new Promise((resolve, reject) => {
const out = `${Math.random()
.toString(13)
.slice(2)}.ts`
ffmpeg(file)
.outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
.output(out)
.on('end', () => resolve(out))
.on('error', reject)
.run()
})
const concat = async (files, output) => {
const names = await Promise.all(files.map(createIntermediate))
const namesString = names.join('|')
await new Promise((resolve, reject) =>
ffmpeg(`concat:${namesString}`)
.outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
.output(output)
.on('end', resolve)
.on('error', reject)
.run()
)
names.map(unlink)
}
concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
console.log('done!')
)
Personnellement, j'aime bien ne pas créer de fichier externe que je dois supprimer par la suite; ma solution a donc été la suivante: la liste de numérotation des fichiers (comme file_1_name, file_2_name, file_10_name, file_20_name, file_100_name
, ...)
#!/bin/bash
filesList=""
for file in $(ls -1v *.mp4);do #lists even numbered file
filesList="${filesList}${file}|"
done
filesList=${filesList%?} # removes trailing pipe
ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4
Cela a fonctionné pour moi (sur Windows)
ffmpeg -i "concat:input1|input2" -codec copy output
en particulier
ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4
Utiliser du code python pour le faire avec autant de MP4 qu'il y a dans un dossier Import glob Import os
stringa = ""
for f in glob.glob("*.mp4"):
stringa += f + "|"
os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
ffmpeg \
-i input_1.mp4 \
-i input_2.mp4 \
-filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
-map [vid] \
-c:v libx264 \
-crf 23 \
-preset veryfast \
output.mp4
Le protocole de concat décrit ici; https://trac.ffmpeg.org/wiki/Concatenate#protocol
Lorsque implémenté en utilisant des canaux nommés pour éviter les fichiers intermédiaires
Est très rapide (lu: instantané), n’a pas de cadres perdus et fonctionne bien.
N'oubliez pas de supprimer les fichiers de canal nommés et de vérifier si la vidéo est H264 et AAC, ce que vous pouvez faire uniquement avec ffmpeg -i filename.mp4
(recherchez les mentions h264 et aac).
Voici ma méthode pour rejoindre un répertoire plein de fichiers MP4 en utilisant la substitution de commande et le filtre vidéo concat (ceci ré-encodera) - imaginé que quelqu'un d'autre puisse utiliser quelque chose de ce one-liner, surtout si vous avez beaucoup de fichiers rejoint 17 dossiers en un seul coup):
ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4
N.B. cette commande joint vos fichiers dans l’ordre dans lequel ils sont nommés (c’est-à-dire le même ordre dans lequel ils sont présentés si vous exécutez ls *.mp4
) - dans mon cas, ils avaient chacun un numéro de piste, ce qui a bien fonctionné.
Pour les fichiers .mp4
, j’ai constaté que l’outil de ligne de commande opensource fonctionnait mieux et plus rapidement: mp4box
. Ensuite, vous pouvez l'utiliser de cette façon:
mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4
Téléchargez-le ici pour la plupart des plateformes: https://gpac.wp.imt.fr/mp4box/
Après divers essais, le script ci-dessous a fonctionné pour moi sous Windows 10 PowerShell.
$files=Get-ChildItem -path e:\ -Filter *.mp4
$files| ForEach-Object {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII
if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}
E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4
# Conversion Cleanup
Remove-Item e:\temp.txt
Ici les deux premières lignes créent un fichier texte temp.txt qui a le contenu suivant
file 'e:\first.mp4'
file 'e:\second.mp4'
3ème, 4ème lignes vérifie si ffmpeg est disponible sur chemin et crée le "join.mp4"
Les principales différences par rapport aux autres réponses sont les suivantes
usage of -bsf:v hevc_mp4toannexb -an
pour mon fichier mp4 ci-dessus travaillé, vous devrez peut-être utiliser d'autres alternatives comme ci-dessous en fonction de votre encodage vidéo.
h264_mp4toannexb
Tous ces filtres possibles sont disponibles à l’adresse https://ffmpeg.org/ffmpeg-bitstream-filters.html