Couper les vidéos en fonction de l'heure de début et de fin à l'aide de ffmpeg

513

J'ai essayé de couper la vidéo en utilisant l'heure de début et de fin de la vidéo en utilisant la commande suivante

ffmpeg -ss 00:00:03 -t 00:00:08 -i movie.mp4 -acodec copy -vcodec copy -async 1 cut.mp4

En utilisant la commande ci-dessus, je veux couper la vidéo de 00:00:03à 00:00:08. Mais il ne coupe pas la vidéo entre ces moments au lieu de cela, il coupe la vidéo avec les 11 premières secondes. quelqu'un peut-il m'aider à résoudre ce problème?

Modifier 1:

J'ai essayé de couper en utilisant la commande suivante qui est suggérée par mark4o

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Mais il a été montré l'erreur suivante.

l'encodeur 'aac' est expérimental mais les codecs expérimentaux ne sont pas activés

donc j'ai ajouté le -strict -2dans la commande, c'est-à-dire

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -strict -2 cut.mp4

Maintenant ça fonctionne bien.

Kalai
la source
3
Votre sortie de console ffmpeg complète et non coupée est manquante. Veuillez toujours l'inclure lors de la demande. Merci.
slhck
3
D'où avez-vous obtenu -strict 2? Juste curieux car ce n'est pas dans les documents: ffmpeg.org/ffmpeg.html
StackOverflowed
C'est pour la qualité après l'installation de ffmpeg, Dans l'aide de ffmpeg, vous pouvez trouver cette option
Kalai
1
superuser.com/questions/138331/using-ffmpeg-to-cut-up-video
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Je pense que le problème ici était en fait juste le fait que vous ayez mis le de et vers AVANT le -i movie.mp4. Les arguments pour ce flux vont après, non? Voilà pourquoi l'autre façon a fonctionné. = /
Brent Rittenhouse

Réponses:

576

Vous n'avez probablement pas d'image clé à la marque des 3 secondes. Étant donné que les images non clés codent les différences par rapport aux autres images, elles nécessitent toutes les données à partir de l'image clé précédente.

Avec le conteneur mp4, il est possible de couper sur une image non clé sans ré-encodage à l'aide d'une liste d'édition. En d'autres termes, si l'image clé la plus proche avant 3 s est à 0, elle copiera la vidéo à partir de 0 et utilisera une liste d'édition pour dire au lecteur de commencer à jouer 3 secondes.

Si vous utilisez la dernière ffmpeg de git master, elle le fera à l'aide d'une liste d'édition lorsqu'elle sera invoquée à l'aide de la commande que vous avez fournie. Si cela ne fonctionne pas pour vous, vous utilisez probablement une ancienne version de ffmpeg ou votre lecteur ne prend pas en charge les listes de modifications. Certains joueurs ignoreront la liste d'édition et liront toujours tous les médias du fichier du début à la fin.

Si vous souhaitez couper précisément à partir d'une image non clé et que vous souhaitez qu'il démarre à partir du point souhaité sur un lecteur qui ne prend pas en charge les listes d'édition, ou si vous voulez vous assurer que la partie coupée ne se trouve pas réellement dans le fichier de sortie (par exemple s'il contient des informations confidentielles), vous pouvez le faire en recodant afin qu'il y ait une image clé précisément à l'heure de début souhaitée. Le recodage est la valeur par défaut si vous ne spécifiez pas copy. Par exemple:

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Lors du réencodage, vous pouvez également souhaiter inclure des options supplémentaires liées à la qualité ou un encodeur AAC particulier. Pour plus de détails, consultez le Guide d'encodage x264 de ffmpeg pour la vidéo et le Guide d'encodage AAC pour l'audio.

En outre, l' -toption spécifie une durée, pas une heure de fin. La commande ci-dessus encodera 8 secondes de vidéo à partir de 3 secondes. Pour commencer à 3 s et terminer à 8 s, utilisez -t 5. Si vous utilisez une version actuelle de ffmpeg, vous pouvez également remplacer -tpar -todans la commande ci-dessus pour terminer à l'heure spécifiée.

mark4o
la source
4
Existe-t-il un raccourci à spécifier jusqu'à la fin de la vidéo?
Jikku Jose
20
@JikkuJose: Omettez le -t/ -toet son argument pour continuer jusqu'à la fin.
mark4o
41
Remarque: il est plus rapide de fournir -ssAVANT le fichier d'entrée (avant -i), car de cette façon, ffmpeg sautera directement à l'emplacement. Cependant, cela mettra également le temps "zéro" à cet endroit, ce qui signifie qu'il -topointera au mauvais moment. Source: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia
4
J'obtiens un problème de synchronisation audio et vidéo après avoir utilisé cela ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, bien que le fichier d'origine n'ait pas un tel problème.
user2002522
6
@ user2002522: Essayez sans le -async 1.
mark4o
433

Essayez d'utiliser ceci. C'est la méthode ffmpeg la plus rapide et la meilleure que j'ai trouvée:

 ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4

Cette commande coupe votre vidéo en quelques secondes!

Je l'ai expliqué sur mon blog ici :

-i: cela spécifie le fichier d'entrée. Dans ce cas, c'est (input.mp4).
-ss: Utilisé avec -i, ceci cherche dans le fichier d'entrée (input.mp4) à se positionner.
00:01:00: il s'agit de l'heure de début de la vidéo découpée.
-to: Ceci spécifie la durée du début (00:01:40) à la fin (00:02:12).
00:02:00: C'est la fin de votre vidéo découpée.
-c copie: il s'agit d'une option pour couper via la copie de flux. (NB: très rapide)

Le format de synchronisation est: hh: mm: ss

Veuillez noter que la réponse actuelle, très appréciée, est obsolète et que le découpage serait extrêmement lent. Pour plus d'informations, consultez cet article officiel de ffmpeg .

George Chalhoub
la source
9
cela a traité mon fichier 45 min 720p en 3s. Ce devrait être la bonne réponse.
Dheeraj Bhaskar
7
Cependant, vous pouvez toujours souffrir d'un manque d'images clés. J'ai adopté votre approche de la découpe, puis réencodé conformément à la réponse acceptée pour m'assurer de minimiser le temps dont j'avais besoin pour passer un nouvel encodage.
pelson
7
Comme le dit @pelson, cela supprimera les images clés et laissera les premières secondes vides (si le temps de découpe se situe entre les images clés). Il est intéressant de changer l'ordre des paramètres résout le problème: ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Maintenant, cependant, le saut est cassé et l'heure de fin n'est pas correcte (dans mon cas).
Raphael
6
Vous devez utiliser cette réponse si vous n'avez pas besoin de couper à une milliseconde exacte, donc elle sélectionnera l'image clé la plus proche disponible. C'est pourquoi il est si rapide qu'il sélectionne les images clés les plus proches et supprime l'extrait de code sans avoir besoin de le réencoder. Cependant, si vous avez besoin d'une heure précise, la prise de l'image clé la plus proche n'est pas suffisante, car elle ne correspondra certainement pas exactement. La seule solution disponible est de recoder la vidéo, et c'est pourquoi c'est si lent. C'est la seule solution, cependant, si vous en avez besoin. C'est pourquoi l'autre réponse devrait être celle qui est acceptée, car c'est le problème d'OP.
Yamaneko
4
Je ne sais pas pourquoi, mais cela ne semble pas être plus correct que la réponse acceptée, car cela entraîne des problèmes avec des images clés manquantes. Pour les courts clips vidéo, l'effet est inacceptable. Un réencodage lent semble être la seule solution dans de tels cas.
icarus74
91
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4 

Utilisez la copie -c pour créer instantanément. Dans ce cas, ffmpeg ne ré-encodera pas la vidéo, il sera juste coupé à la taille appropriée.

Vlad Hudnitsky
la source
2
de la copie -c fonctionne très bien, mais seulement si je supprime -async 1
dorien
2
Cela finit par échouer lors de l'écriture en raison d'en-têtes invalides dans le cas de différents conteneurs d'entrée et de sortie, par exemple l'entrée .mkv et la sortie .mp4.
Assil Ksiksi
1
D'accord, pour convertir .mkv en .mp4, vous devez utiliser une autre commande: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4et
vice
Quels sont les avantages du ré-encodage? Est-il utile si nous voulons simplement une vidéo plus petite dans le même format?
Harsha
29
    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Déposez tout sauf du deuxième 3 au deuxième 8.

JFMD
la source
4
J'obtiens les 8 premières secondes avec cela, avec les 3 premières secondes figées sur la première image. Fixé en enchaînant le setpts=PTS-STARTPTSfiltre après le filtre de rognage.
jiggunjer
Cela dit "L'encodeur 'aac' est expérimental mais les codecs expérimentaux ne sont pas activés, ajoutez '-strict -2' si vous voulez l'utiliser." L'ajout de -strict -2 n'aide pas. Le résultat est un fichier de longueur nulle.
Ivan
4
@Ivan, avez-vous essayé d'ajouter -strict -2avant cut.mp4(par opposition à la fin de la ligne de commande)?
Jan Gondol
Hé, pouvez-vous me dire si je veux seulement une vidéo sans 3 à 8 secondes?
Parth Solanki
1
C'est super lent
Tessaracter
21

Pour couper en fonction de l'heure de début et de fin de la vidéo source et éviter d'avoir à faire des calculs, spécifiez l'heure de fin comme option d'entrée et l'heure de début comme option de sortie.

ffmpeg -t 1:00 -i input.mpg -ss 45 output.mpg

Cela produira une coupe de 15 secondes de 0:45 à 1:00.

En effet, lorsque -ss option est donnée comme option de sortie, le temps ignoré est toujours inclus dans le temps total lu à partir de l'entrée, qui permet -tde savoir quand s'arrêter. Alors que si -ssest donné comme option d' entrée , l'heure de début est recherchée et non comptée , d'où la confusion.

C'est plus lent que de chercher car le segment omis est toujours traité avant d'être supprimé, mais c'est la seule façon de le faire à ma connaissance. Si vous découpez du plus profond d'un gros fichier, il est plus prudent de faire le calcul et de l'utiliser -sspour l'entrée.

RY
la source
4
lent, mais la seule chose a fonctionné pour moi (sans perdre les cadres des autres réponses)
techkuz
8

Voici ce que j'utilise:

ffmpeg -i input.mkv -ss 00:01:00 -to 00:02:00 -c:v copy -c:a copy output.mp4

Les mp4fichiers générés peuvent également être utilisés dans iMovie.

Référence: https://www.arj.no/2018/05/18/trimvideo


Si vous souhaitez concaténer plusieurs scènes de coupe, vous pouvez utiliser le script suivant:

#!/usr/bin/env python3

import subprocess

name = "batman.mp4"

times = []
times.append(["01:06:00", "01:07:00"])
times.append(["01:08:00", "01:09:00"])

open('concatenate.txt', 'w').close()
for idx, time in enumerate(times):
    output_filename = f"output{idx}.mp4"
    cmd = ["ffmpeg", "-i", name, "-ss", time[0], "-to", time[1], "-c:v", "copy", "-c:a", "copy", output_filename]
    subprocess.check_output(cmd)
    with open("concatenate.txt", "a") as myfile:
        myfile.write(f"file {output_filename}\n")

cmd = ["ffmpeg", "-f", "concat", "-i", "concatenate.txt", "-c", "copy", "final.mp4"]
output = subprocess.check_output(cmd).decode("utf-8").strip()
alper
la source
Cela a déjà été répondu cependant
Tessaracter
1
Mon approche est différente des réponses acceptées. J'ai essayé ceux qui ont plus de temps pour construire le fichier mp4. @Tessaracter
alper
1
C'est la SEULE réponse ici qui a fonctionné pour moi pour couper un petit clip d'une grande vidéo. Cela fonctionne et RAPIDE !!! Merci
lacostenycoder
1
Je vous en prie, je suis heureux de pouvoir vous aider. J'ai pu trouver cette réponse après avoir essayé de nombreuses approches. La plupart d'entre eux étaient assez lents. @lacostenycoder
alper
Cela ne pourrait-il pas simplement utiliser "-c" avec "copier" au lieu de séparer -c: v et -c: a?
nstenz
-3

Même si j'ai 6 ans de retard, mais je pense que toutes les réponses ci-dessus n'ont pas correctement répondu à la question de @kalai . Le script bash ci-dessous traitera un fichier texte au format suivant:

URL | start_time | end_time | filename

par exemple

https://www.youtube.com/watch?v=iUDURCrvrMI|00:02:02|00:03:41|1

et parcourir le fichier, télécharge le fichier qui youtube-dlprend en charge, en calculant la durée entre start_timeet end_timeet en le passant ffmpeg, car -tc'est en fait la durée , pas la vraieend_time

Frappez-moi si vous avez des questions.

    for i in $(<video.txt);
    do
        URL=`echo $i | cut -d "|" -f 1`;
        START=`echo $i | cut -d "|" -f 2`;
        END=`echo $i | cut -d "|" -f 3`;
        FILE=`echo $i | cut -d "|" -f 4`;

        SEC1=`echo $START | sed 's/^/((/; s/:/)*60+/g' | bc`
        SEC2=`echo $END | sed 's/^/((/; s/:/)*60+/g' | bc`

        DIFFSEC=`expr ${SEC2} - ${SEC1}`

        ffmpeg $(youtube-dl -g $URL | sed "s/.*/-ss $START -i &/") -t $DIFFSEC -c copy $FILE".mkv";
        ffmpeg -i $FILE".mkv" -f mp3 -ab 192000 -vn $FILE".mp3";
        rm $FILE".mkv";
    done;
rolodex
la source
Cela ne produit qu'un fichier audio mp3 et PAS une vidéo.
lacostenycoder
Ouais ... changez simplement le format de sortie.
rolodex