84 votes

Comment puis-je supprimer plusieurs segments d'une vidéo en utilisant FFmpeg ?

J'essaie de supprimer quelques sections d'une vidéo en utilisant FFmpeg.

Par exemple, imaginez que vous enregistriez une émission de télévision et que vous vouliez couper les publicités. C'est très simple avec un éditeur vidéo graphique ; il suffit de marquer le début et la fin de chaque clip à supprimer, puis de sélectionner "supprimer". J'essaie de faire la même chose en ligne de commande avec FFmpeg.

Je sais comment couper un seul segment à un nuevo vidéo comme ça :

ffmpeg -i input.avi -ss 00:00:20 -t 00:00:05 -map 0 -codec copy output.avi

Cela permet de couper un clip de cinq secondes et de l'enregistrer dans un nouveau fichier vidéo, mais comment faire l'inverse et enregistrer la vidéo entière ? sans le clip spécifié, et comment puis-je spécifier plusieurs clips à supprimer ?

Par exemple, si ma vidéo peut être représentée par ABCDEFG, j'aimerais en créer une nouvelle qui serait composée de ACDFG.

3voto

detic Points 43

Convertir ABCDEFG a ACDFG consiste essentiellement à couper trois segments de la vidéo, puis à joindre ces trois segments. Si tous les segments sont coupés à partir de la même vidéo et qu'il n'est pas nécessaire de modifier l'encodage de la vidéo (résolution, débit binaire, fréquence d'images, etc.), le ré-encodage n'est pas nécessaire et dégradera la qualité des formats avec perte. Cependant, sans ré-encodage, les positions de coupe ne seront pas exactes mais les images clés les plus proches des moments spécifiés.

Les exemples ci-dessous supposent que vidfull.mp4 es ABCDEFG où chaque lettre représente un segment de cinq minutes.

Sans ré-encodage, le processus est presque instantané, mais la coupure doit être faite explicitement, où des fichiers temporaires sont créés, et la jonction peut être faite soit avec le protocole de concaténation (c'est-à-dire la concaténation au niveau du fichier), et le protocole .ts comme format intermédiaire, qui prend en charge la concaténation au niveau des fichiers :

ffmpeg \
  -to 5:0 -i vidfull.mp4 \
  -ss 10:0 -to 20:0 -i vidfull.mp4 \
  -ss 25:0 -i vidfull.mp4 \
  -map 0:v -map 0:a -c copy part1.ts \
  -map 1:v -map 1:a -c copy part2.ts \
  -map 2:v -map 2:a -c copy part3.ts
ffmpeg -i 'concat:part1.ts|part2.ts|part3.ts' -c copy vidcut.ts
ffmpeg -i vidcut.ts -c copy vidcut.mp4
rm -f part{1..3}.ts vidcut.ts

ou avec le démuxeur de concaténation script :

ffmpeg \
  -to 5:0 -i vidfull.mp4 \
  -ss 10:0 -to 20:0 -i vidfull.mp4 \
  -ss 25:0 -i vidfull.mp4 \
  -map 0:v -map 0:a -c copy -avoid_negative_ts make_non_negative part1.mp4 \
  -map 1:v -map 1:a -c copy -avoid_negative_ts make_non_negative part2.mp4 \
  -map 2:v -map 2:a -c copy -avoid_negative_ts make_non_negative part3.mp4
cat <<- eof > script.txt
    ffconcat version 1.0
    file '/path to/part1.mp4'
    file '/path to/part2.mp4'
    file '/path to/part3.mp4'
eof
ffmpeg -f concat -safe 0 -i script.txt -c copy vidcut.mp4
rm -f part{1..3}.mp4 script.txt

Avec le réencodage, le processus est lent, mais le découpage et l'assemblage se font en une seule commande en utilisant la même vidéo comme entrée d'un filtre concat complexe plusieurs fois après avoir cherché à différentes positions :

ffmpeg \
  -to 5:0 -i vidfull.mp4 \
  -ss 10:0 -to 20:0 -i vidfull.mp4 \
  -ss 25:0 -i vidfull.mp4 \
  -lavfi concat=n=3:a=1 vidcut.mp4

Il n'est pas nécessaire d'étiqueter les blocs d'entrée ou de sortie du filtre concat puisqu'il n'y a pas d'autre filtre que concat dans la chaîne de filtres pour utiliser un flux spécifique d'un bloc spécifique, aucun flux n'est destiné à être exclu de la sortie, et tous les flux des blocs non étiquetés sont ajoutés au premier fichier de sortie automatiquement (le format de sortie doit supporter tous les types de flux pour éviter une erreur fatale). Et, parmi les options du filtre concat, n est le nombre de segments d'entrée, et doit être fixé à 3 puisqu'il s'agit 2 par défaut, et a est le nombre de flux audio de sortie, et doit être fixé à 1 puisqu'il s'agit 0 par défaut.

2voto

Angry Chipmonk Points 1

Bien que la réponse fournie par ptQa semble fonctionner, j'ai développé une autre solution qui s'est avérée efficace.

Essentiellement, ce que je fais est de couper une vidéo pour chaque partie de la vidéo originale que je veux inclure dans mon résultat. Plus tard, je les concatène avec le Concat Demuxer expliqué aquí .

Le résultat est le même que celui que j'ai essayé en premier - mais qui présentait des problèmes de synchronisation. Ce que j'ai ajouté est la commande -éviter_négatif_ts 1 lors de la génération des différentes vidéos. Avec cette solution, les problèmes de synchronisation disparaissent.

0voto

Trey Carroll Points 922

Après avoir utilisé ffmpeg qui fait un bon travail, bien que compliqué, j'ai réalisé que ffmpeg semble être bien configuré pour traiter les fichiers .mp4 et .ts (transport stream format) pour travailler sans perte et éviter le réencodage.

En cherchant à traiter les fichiers au format mkv/webm que je préfère, j'ai réalisé qu'il existe un excellent paquetage open source appelé MKVtoolNix qui inclut mkvmerge, et tant que vous utilisez un seul fichier vidéo ou plusieurs fichiers avec des formats similaires, il fait par défaut le piping et le mapping correctement, et il accepte très simple syntaxe permettant de prendre plusieurs segments de vidéo et de les concaténer parfaitement, même en soutenant les informations du chapitre assez facilement.

Et MKVtoolNix ne fait apparemment aucun transcodage ou réencodage, il est donc intrinsèquement très rapide et sans perte. Les fichiers de sortie semblent petits et optimisés. Les sous-titres et de nombreuses subtilités de ce processus sont gérés par défaut ou avec facilité. Je garderais cependant ffmpeg pour faire un nettoyage rapide de l'indexation par recherche via une option de commande "-c copy".

MKVtoolNix a peut-être la capacité de traiter d'autres formats également, et une version GUI de mkvmerge qui semble très impressionnante.

0voto

Jason Points 125291

Réponse de Shawnblais fonctionne bien, mais j'ai remarqué qu'il était très lent lors de l'extraction de courts fragments d'une longue vidéo. Je soupçonne ffmpeg de décoder la vidéo entière et d'appliquer le découpage en éliminant les images.

Une alternative à l'utilisation d'un seul fichier d'entrée avec plusieurs filtres d'ajustement, est d'utiliser le même fichier comme entrée plusieurs fois. Nous pouvons alors utiliser -ss y -to comme options d'entrée, ce qui permet une recherche rapide. Pour -ss y -to pour être des options d'entrée, elles doivent être soumises à l'examen de la Commission. -i auxquels ils s'appliquent. Le site concat filtre peut ensuite les référencer par numéro de dossier, 0:v , 1:v etc.

Exemple de concaténation de vidéo sans audio :

ffmpeg \
  -ss 10.0 -to 15.0 -i in.mkv \
  -ss 50.0 -to 60.0 -i in.mkv \
  -filter_complex '[0:v][1:v]concat=n=2:v=1[outv]' \
  -map '[outv]' \
  out.mkv

0voto

FarisHijazi Points 101

Dans la continuité de la réponse de shawnblais, voici une fonction Python qui vous aidera à construire les commandes de coupe à partir des heures de début et de fin.

def construct_ffmpeg_trim_cmd(timepairs, inpath, outpath):
  cmd = f'ffmpeg -i "{inpath}" -y -filter_complex '
  cmd += '"'
  for i, (start, end) in enumerate(timepairs):
    cmd += (f"[0:v]trim=start={start}:end={end},setpts=PTS-STARTPTS,format=yuv420p[{i}v]; " +
            f"[0:a]atrim=start={start}:end={end},asetpts=PTS-STARTPTS[{i}a]; ")
  for i, (start, end) in enumerate(timepairs):
    cmd += f"[{i}v][{i}a]"
  cmd += f'concat=n={len(timepairs)}:v=1:a=1[outv][outa]'
  cmd += '"'
  cmd += f' -map [outv] -map [outa] "{outpath}"'
  return cmd

Gist GitHub : https://gist.github.com/FarisHijazi/eff7a7979440faa84a63657e085ec504

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X