FFmpeg: come dividere i video in modo efficiente?


103

Desidero dividere un video avi di grandi dimensioni in due video consecutivi più piccoli. Sto usando ffmpeg.

Un modo è eseguire ffmpeg due volte:

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

Ma secondo la manpage di ffmpeg, posso creare più di un file di output da un file di input usando solo una riga:

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

La mia domanda è: l'approccio successivo consente di risparmiare tempo e memoria di calcolo?


3
quando si utilizza "-vcodec copy -acodec copy" è molto veloce :))
Savas Adar

@ Antonio, perché non cronometri entrambe le versioni (e guardi il monitor della memoria come htop) e ci dici qual è la risposta?
AlcubierreDrive

Il primo esempio lo fa in modo sequenziale, mentre il secondo esempio utilizza i thread. Entrambi faranno la stessa cosa, non dovrebbero verificarsi accelerazioni evidenti. Ma per semplificare le cose, potresti usare ffmpeg stream segmenter muxer: ffmpeg.org/…
Mladen B.

1
Questo esempio sembra molto sbagliato! La documentazione di ffmpeg dice dell'opzione -ss: "Quando viene utilizzata come opzione di input (prima di -i), cerca la posizione in questo file di input. Quando viene utilizzata come opzione di output (prima di un nome di file di output), decodifica ma scarta l'input fino a quando il i timestamp raggiungono la posizione. " Lo stai usando nella posizione di uscita, quindi la tua seconda riga spreca sforzi per decodificare e scartare i primi 30 minuti.
Lucian Wischik

1
@LucianWischik ma l'utilizzo -sscome opzione di input nella seconda divisione potrebbe non essere accurato, quindi potresti non ottenere una divisione pulita. IMO l'esempio di OP è più corretto.
jiggunjer

Risposte:


82

Il wiki ffmpeg si collega a questa pagina in riferimento a "Come dividere i video in modo efficiente". Non sono convinto che questa pagina risponda a questa domanda, quindi ho fatto come suggerito da @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

Quali uscite ...

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

Ho testato un file SD e HD, dopo alcune corse e un po 'di matematica.

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  

File SD = flusso di trasporto DVB da 1,35 GB
File HD = flusso di trasporto DVB da 3,14 GB

Conclusione

Il comando singolo è migliore se stai gestendo HD, è d'accordo con i commenti del manuale sull'uso di -ss dopo il file di input per fare una "ricerca lenta". I file SD hanno una differenza trascurabile.

La versione a due comandi dovrebbe essere più veloce aggiungendo un altro -ss prima del file di input per una "ricerca rapida" seguita dalla ricerca lenta più accurata.


Se TS contiene più programmi (programmi TV catturati da DVB-T), come è possibile dividerli? Ad esempio, ho un file TS che contiene football + cooking + cartoon. Come posso dividere questo file TS in 3 file mpg?
Dr.jacky

Ho usato la tua risposta nella mia domanda qui ( stackoverflow.com/questions/41983940/… ) ma non ha funzionato, cosa pensi che stia facendo di sbagliato?
utdev

1
Il file del risultato era senza video (solo audio) nel mio caso. Dopo alcuni esperimenti ho trovato l'anima. È necessario specificare la chiave per "non modificare la qualità" in questo modo -q:v 0.
oklas

19

Ecco uno script utile, che ti aiuta a dividere automaticamente: uno script per dividere i video usando 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

2
Lo stesso commento vale per te come per SEARAS. Scrivere file batch è utile quando è assolutamente necessario e quando non hai altre opzioni disponibili, perché non è portabile. Ad esempio, non sarai in grado di eseguire lo stesso script su Windows. Quando ci sono modi più generici / portabili, gli script batch dovrebbero essere evitati, per risparmiare il tempo necessario per portarli. Poiché ffmpeg ha diversi modi per risolvere questo problema, il modo corretto sarebbe usare ffmpeg da solo, senza l'aiuto di script.
Mladen B.

Bella sceneggiatura. L'hai scritto tu? È su GitHub? Vorrei dare alcuni suggerimenti :)
voci

per mp4, le scene sono danneggiate. meglio sostituire la copia con: -vcodec libx264 -acodec aac
kishu

8

Nella mia esperienza, non usare ffmpeg per dividere / unire. MP4Box, è più veloce e leggero di ffmpeg. Per favore provalo. Ad esempio, se si desidera dividere un file MP4 da 1400 MB in due parti a 700 MB, è possibile utilizzare il seguente cmdl: MP4Box -splits 716800 input.mp4 ad esempio, per concatenare due file è possibile utilizzare:

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

O se hai bisogno di una suddivisione in base al tempo, usa -splitx StartTime:EndTime:

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


Questo era esattamente ciò di cui avevo bisogno! Quando stavo tagliando con ffmpeg, le clip non si avviavano sui fotogrammi chiave e presentavano strani blocchi alle estremità. Usare MP4Box -splitz ha funzionato!
matt

1
come posso tagliare il video utilizzando Mp4Box con più numeri? per esempio ho bisogno di sub clip in pochi secondi sono: 5 - 8, 21 - 30, 12 - 18 quindi ho bisogno di tre file video di output.
mhndev

Ed è molto più facile da usare EndTimerispetto a -t.
vmassuchetto


2

l'approccio successivo fa risparmiare tempo e memoria di calcolo?

Non c'è grande differenza tra questi due esempi che hai fornito. Il primo esempio taglia il video in sequenza, in 2 passaggi, mentre il secondo esempio lo fa contemporaneamente (usando i thread). Non si noterà alcuna accelerazione particolare. Puoi leggere di più sulla creazione di più output con FFmpeg

Inoltre, quello che puoi usare (nel recente FFmpeg) è il muxer del segmentatore di flusso che può:

flussi di output in un numero di file separati di durata quasi fissa. Il modello del nome del file di output può essere impostato in modo simile a image2 .


2

Ecco un semplice file bat di Windows per dividere il file in arrivo in 50 parti. Ogni parte ha durata 1 minuto. Ci scusiamo per una sceneggiatura così stupida. Spero sia meglio avere uno stupido script di Windows invece di non averlo affatto. Forse aiuta qualcuno. (Basato su "bat file for loop" da questo sito.)

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

Questo è essenzialmente il primo frammento di codice nella domanda ( ffmpegcomandi consecutivi ) riscritto come un ciclo. Questo non risponde alla domanda se quell'approccio o un singolo comando "farà risparmiare tempo e memoria di calcolo".
BACON

1

Non è stato testato, ma sembra promettente:

Segmentatore di stream di base

Ovviamente sta dividendo AVI in segmenti della stessa dimensione, il che implica che questi pezzi non perdono qualità o aumentano la memoria o devono essere ricalcolati.

Utilizza anche la copia del codec: significa che può gestire flussi molto grandi? Poiché questo è il mio problema, voglio abbattere il mio avi in ​​modo da poter utilizzare un filtro per eliminare la distorsione. Ma un intero avi funziona per ore.


-1

Ecco un modo perfetto per dividere il video. L'ho fatto in precedenza e sta funzionando bene per me.

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (Per 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')(per php).

Per favore, segui questo e sono sicuro che funzionerà perfettamente.


Perché questo è il "modo perfetto" per dividere il video? Come la riga di comando nella domanda, stai passando -iseguito da -sse -t. La domanda è su come estrarre in modo efficiente più segmenti dallo stesso file di input, mentre stai estraendo solo un singolo segmento. Non vedo come questo risponda alla domanda.
BACON

-2

un modo semplice è usare l'opzione trim con l' API basata sull'URL di pubbl .

una volta caricato il video, imposta l'offset iniziale e l'offset finale nell'URL (so_2, eo_2) in questo modo:

    https://media.publit.io/file/so_2,eo_2/tummy.mp4

questo creerà istantaneamente nuovi video a partire dal 2 ° secondo e 2 secondi di lunghezza. puoi dividere i video in questo modo come preferisci.


La domanda è chiedere quale sia il più efficiente tra due approcci per estrarre più segmenti da un file di input con ffmpeg. A meno che tu non abbia una connessione Internet molto, molto veloce, penso che dover caricare l'intero video su un servizio cloud e quindi scaricare i risultati aumenterà in modo significativo il tempo di elaborazione. Anche così, questo continua a non rispondere alla domanda di quale approccio conffmpeg è più efficiente.
BACON
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.