web-dev-qa-db-fra.com

FFmpeg: Comment diviser une vidéo efficacement?

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

Une façon 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 créer plusieurs fichiers 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: l'approche ultérieure permet-elle de gagner du temps de calcul et de la mémoire?

90
Antony

Le wiki ffmpeg renvoie à cette page en référence à "Comment fractionner une vidéo efficacement". Je ne suis pas convaincu que cette page réponde à cette question. J'ai donc suivi les suggestions de @AlcubierreDrive…

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 ...

Two commands
real    0m16.201s
user    0m1.830s
sys 0m1.301s

real    0m43.621s
user    0m4.943s
sys 0m2.908s

One command
real    0m59.410s
user    0m5.577s
sys 0m3.939s

J'ai testé un fichier SD & HD, après quelques essais et un peu de maths.

Two commands SD 0m53.94 #2 wins  
One command  SD 0m49.63  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.60 #2 wins  
One command  SD 0m58.61 

Two commands SD 0m54.60  
One command  SD 0m50.51 #1 wins 

Two commands SD 0m53.94  
One command  SD 0m49.63 #1 wins  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.71  
One command  SD 0m58.61 #1 wins

Two commands SD 0m54.63  
One command  SD 0m50.51 #1 wins  

Two commands SD 1m6.67s #2 wins  
One command  SD 1m20.18  

Two commands SD 1m7.67  
One command  SD 1m6.72 #1 wins

Two commands SD 1m4.92  
One command  SD 1m2.24 #1 wins

Two commands SD 1m1.73  
One command  SD 0m59.72 #1 wins

Two commands HD 4m23.20  
One command  HD 3m40.02 #1 wins

Two commands SD 1m1.30  
One command  SD 0m59.59 #1 wins  

Two commands HD 3m47.89  
One command  HD 3m29.59 #1 wins  

Two commands SD 0m59.82  
One command  SD 0m59.41 #1 wins  

Two commands HD 3m51.18  
One command  HD 3m30.79 #1 wins  

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 utilisez HD, elle est conforme aux commentaires des manuels 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 la recherche rapide suivie de la recherche lente plus précise.

74
user2867531

Voici un script utile, il vous aide à scinder automatiquement: Un script pour scinder des vidéos avec ffmpeg

#!/bin/bash
 
# Written by Alexis Bezverkhyy <[email protected]> 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
19
Marco C.

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

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

5
rogerdpack

D'après mon expérience, n'utilisez pas ffmpeg pour scinder/rejoindre. MP4Box, est plus rapide et léger que ffmpeg. S'il vous plaît tryit . Par exemple, si vous voulez diviser un fichier MP4 1400mb en deux parties un 700mb vous pouvez utiliser le cmdl suivant: MP4Box -splits 716800 input.mp4eg pour concaténer deux fichiers que vous pouvez utiliser:

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4

Ou si vous avez besoin d'une division par heure, utilisez -splitx StartTime:EndTime:

MP4Box -add input.mp4 -splitx 0:15 -new split.mp4

5
Classsic

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

Il n'y a pas de grande différence entre ces deux exemples que vous avez fournis. Le premier exemple coupe la vidéo séquentiellement, en 2 étapes, tandis que le deuxième 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éer plusieurs sorties avec FFmpeg

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

les flux de sortie vers un certain nombre de fichiers distincts d’une durée presque fixe. Le modèle de nom de fichier de sortie peut être défini de la même manière que image2 .

1
Mladen B.

Voici un fichier de batte Windows simple pour scinder le fichier entrant en 50 parties. Chaque partie dure 1 minute. Désolé pour ce script stupide. J'espère qu'il est préférable d'avoir un script Windows stupide plutôt que de ne pas l'avoir du tout. Peut-être que cela aidera quelqu'un . (Basé sur "bat file for loop" de ce site.)

set var=0
@echo off
:start
set lz=
if %var% EQU 50 goto end
if %var% LEQ 9 set lz=0
echo part %lz%%var%
ffmpeg -ss 00:%lz%%var%:00 -t 00:01:00 -i %1 -acodec copy -vcodec copy %2_%lz%%var%.mp4
set /a var+=1
goto start

:end
echo var has reached %var%.
exit
1
Alex Bor

Voici un moyen idéal pour diviser la vidéo. Je l'ai déjà fait et ça marche bien pour moi.

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (pour cmd) .Shell_exec('ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4') (pour php).

Veuillez suivre ceci et je suis sûr que cela fonctionnera parfaitement.

0
Atul Upadhyay

Je n'ai pas testé, mais cela semble prometteur:

segmenteur de flux de base

Il s'agit évidemment de diviser 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 la copie de codec - cela signifie-t-il qu'il peut gérer des flux très volumineux? Parce que c'est mon problème, je veux décomposer mon avi afin que je puisse utiliser un filtre pour se débarrasser de la distorsion. Mais tout un avi dure des heures.

0
Mathias Weitz