108 votes

FFmpeg : Comment diviser efficacement une vidéo ?

Je souhaite diviser une grande vidéo avi en deux petites vidéos consécutives. J'utilise ffmpeg.

Une façon de procéder est d'exécuter ffmpeg deux fois :

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

Mais selon la page de manuel de ffmpeg, je peux faire plus d'un fichier de sortie à partir d'un fichier d'entrée en utilisant seulement un ligne :

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi \
   -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

Ma question est la suivante : cette dernière approche permet-elle de gagner du temps de calcul et de la mémoire ?

87voto

user2867531 Points 121

Le wiki de ffmpeg renvoie à cette page en référence à "Comment diviser efficacement une vidéo". Je ne suis pas convaincu que cette page réponde à cette question, alors j'ai fait ce que @AlcubierreDrive a suggéré

echo "Two commands" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 -sn test1.mkv
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test2.mkv
echo "One command" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 \
  -sn test3.mkv -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test4.mkv

Quelles sorties Deux commandes real 0m16.201s user 0m1.830s sys 0m1.301s

réel 0m43.621s utilisateur 0m4.943s sys 0m2.908s

Une commande real 0m59.410s user 0m5.577s sys 0m3.939s

J'ai testé un fichier SD et HD, après quelques essais et quelques calculs.

Deux commandes SD 0m53.94 #2 gagne
Une commande SD 0m49.63

Deux commandes SD 0m55.00
Une commande SD 0m52.26 #1 gagne

Deux commandes SD 0m58.60 #2 gagne
Une commande SD 0m58.61

Deux commandes SD 0m54.60
Une commande SD 0m50.51 #1 gagne

Deux commandes SD 0m53.94
Une commande SD 0m49.63 #1 gagne

Deux commandes SD 0m55.00
Une commande SD 0m52.26 #1 gagne

Deux commandes SD 0m58.71
Une commande SD 0m58.61 #1 gagne

Deux commandes SD 0m54.63
Une commande SD 0m50.51 #1 gagne

Deux commandes SD 1m6.67s #2 gagne
Une commande SD 1m20.18

Deux commandes SD 1m7.67
Une commande SD 1m6.72 #1 gagne

Deux commandes SD 1m4.92
Une commande SD 1m2.24 #1 gagne

Deux commandes SD 1m1.73
Une commande SD 0m59.72 #1 gagne

Deux commandes HD 4m23.20
Une commande HD 3m40.02 #1 gagne

Deux commandes SD 1m1.30
Une commande SD 0m59.59 #1 gagne

Deux commandes HD 3m47.89
Une commande HD 3m29.59 #1 gagne

Deux commandes SD 0m59.82
Une commande SD 0m59.41 #1 gagne

Deux commandes HD 3m51.18
Une commande HD 3m30.79 #1 gagne

Fichier SD \= 1,35 Go de flux de transport DVB
Fichier HD \= 3,14 Go de flux de transport DVB

Conclusion

La commande unique est préférable si vous manipulez de la HD, cela correspond aux commentaires du manuel sur l'utilisation de -ss après le fichier d'entrée pour effectuer une "recherche lente". Les fichiers SD ont une différence négligeable.

La version à deux commandes devrait être plus rapide en ajoutant un autre -ss avant le fichier d'entrée pour une "recherche rapide" suivie d'une recherche lente plus précise.

21voto

Marco C. Points 136

Voici un script utile, il vous aide à diviser automatiquement : Un script pour diviser les vidéos en utilisant ffmpeg

#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
 
function usage {
        echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
        echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
        echo -e "\t - chunk duration must be in seconds"
        echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
        echo -e "\t - if no output filename format is given, it will be computed\
 automatically from input filename"
}
 
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
 
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
 
if [ "$DURATION" = '0' ] ; then
        echo "Invalid input video"
        usage
        exit 1
fi
 
if [ "$CHUNK_LEN" = "0" ] ; then
        echo "Invalid chunk size"
        usage
        exit 2
fi
 
if [ -z "$OUT_FILE_FORMAT" ] ; then
        FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
        FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
        OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
        echo "Using default output file format : $OUT_FILE_FORMAT"
fi
 
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
 
while [ "$OFFSET" -lt "$DURATION" ] ; do
        OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
        echo "writing $OUT_FILE ($N/$N_FILES)..."
        ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
        let "N = N + 1"
        let "OFFSET = OFFSET + CHUNK_LEN"
done

6voto

rogerdpack Points 12806

http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg peut également vous être utile. De plus, ffmpeg possède un muxer de segment qui pourrait fonctionner.

Quoi qu'il en soit, je pense que les combiner en une seule commande permettrait de gagner du temps.

2voto

Mladen B. Points 547

la dernière approche permet-elle de gagner du temps de calcul et de la mémoire ?

Il n'y a pas de grande différence entre les deux exemples que vous avez fournis. Le premier exemple coupe la vidéo de manière séquentielle, en 2 étapes, alors que le second exemple le fait en même temps (en utilisant des threads). Aucune accélération particulière ne sera perceptible. Vous pouvez en savoir plus sur création de sorties multiples avec FFmpeg

De plus, ce que vous pouvez utiliser (dans le récent FFmpeg) est la fonction segmenteur de flux muxer qui peut :

les flux de sortie vers un certain nombre de fichiers séparés de durée presque fixe. Le modèle de nom de fichier de sortie peut être défini de façon similaire à image2 .

1voto

Mathias Weitz Points 101

Je ne l'ai pas testé, mais ça semble prometteur :

Segmenteur de flux de base

Il divise évidemment l'AVI en segments de même taille, ce qui implique que ces morceaux ne perdent pas en qualité, n'augmentent pas la mémoire ou doivent être recalculés.

Il utilise également le codec copy - cela signifie-t-il qu'il peut gérer de très gros flux ? Parce que c'est mon problème, je veux décomposer mon avi pour pouvoir utiliser un filtre pour me débarrasser de la distorsion. Mais un avi entier tourne pendant des heures.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X