FFmpeg: ¿Cómo dividir videos de manera eficiente?


103

Deseo dividir un video avi grande en dos videos consecutivos más pequeños. Estoy usando ffmpeg.

Una forma es ejecutar ffmpeg dos veces:

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

Pero de acuerdo con la página de manual de ffmpeg, puedo hacer más de un archivo de salida a partir de un archivo de entrada usando solo una línea:

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

Mi pregunta es, ¿el enfoque posterior ahorra tiempo de cálculo y memoria?


3
cuando se usa "-vcodec copy -acodec copy" es muy rápido :))
Savas Adar

@Antony, ¿por qué no cronometra ambas versiones (y mira el monitor de memoria como htop) y nos dice cuál es la respuesta?
AlcubierreDrive

El primer ejemplo lo hace secuencialmente, mientras que el segundo ejemplo usa hilos. Ambos harán lo mismo, no deberían ocurrir aceleraciones notables. Pero para simplificar las cosas, puede usar ffmpeg stream segmenter muxer: ffmpeg.org/…
Mladen B.

1
¡Este ejemplo se ve muy mal! La documentación de ffmpeg dice sobre la opción -ss: "Cuando se usa como una opción de entrada (antes de -i), busca en este archivo de entrada para posicionar. Cuando se usa como una opción de salida (antes de un nombre de archivo de salida), decodifica pero descarta la entrada hasta que las marcas de tiempo alcanzan la posición ". Lo está utilizando en la posición de salida, por lo que su segunda línea desperdicia esfuerzo decodificando y descartando los primeros 30 minutos.
Lucian Wischik

1
@LucianWischik, pero usar -sscomo opción de entrada en la segunda división podría no ser exacto, por lo que es posible que no obtenga una división limpia. En mi opinión, el ejemplo de OP es más correcto.
jiggunjer

Respuestas:


82

El wiki de ffmpeg enlaza con esta página en referencia a "Cómo dividir videos de manera eficiente". No estoy convencido de que esta página responda a esa pregunta, así que hice lo que sugirió @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

Qué salidas ...

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

Probé un archivo SD y HD, después de algunas ejecuciones y un poco de matemáticas.

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  

Archivo SD = flujo de transporte DVB de 1,35 GB
Archivo HD = flujo de transporte DVB de 3,14 GB

Conclusión

El comando único es mejor si está manejando HD, está de acuerdo con los comentarios del manual sobre el uso de -ss después del archivo de entrada para hacer una 'búsqueda lenta'. Los archivos SD tienen una diferencia insignificante.

La versión de dos comandos debería ser más rápida agregando otro -ss antes del archivo de entrada para una 'búsqueda rápida' seguida de una búsqueda lenta más precisa.


Si TS contiene varios programas (programas de TV capturados por DVB-T), ¿cómo se pueden dividir? Por ejemplo, tengo un archivo TS que contiene fútbol + cocina + dibujos animados. ¿Cómo puedo dividir este archivo TS en 3 archivos mpg?
Dr.jacky

Usé tu respuesta en mi pregunta aquí ( stackoverflow.com/questions/41983940/… ) pero no funcionó, ¿qué crees que estoy haciendo mal?
utdev

1
El archivo de resultado no tenía video (solo audio) en mi caso. Después de algunos experimentos encontré soultion. Es necesario especificar la clave para "no modificar la calidad" de esta manera -q:v 0.
oklas

19

Aquí hay un guión útil que le ayuda a dividir automáticamente: Un guión para dividir videos 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
El mismo comentario va para ti que para SEARAS. Escribir archivos por lotes es útil cuando es absolutamente necesario y cuando no tiene otra opción disponible, porque no es portátil. No podrá ejecutar el mismo script en Windows, por ejemplo. Cuando hay formas más genéricas / portátiles, se deben evitar los scripts por lotes, para ahorrar el tiempo necesario para portarlos. Dado que ffmpeg tiene varias formas de resolver este problema, la forma correcta sería usar ffmpeg solo, sin la ayuda de scripts.
Mladen B.

Buen guión. ¿Lo escribiste tú? ¿Está en GitHub? Me gustaría hacer algunas sugerencias :)
voces

para mp4, las escenas están dañadas. mejor reemplace la copia con: -vcodec libx264 -acodec aac
kishu

8

En mi experiencia, no use ffmpeg para dividir / unir. MP4Box, es más rápido y ligero que ffmpeg. Por favor pruebalo. Por ejemplo, si desea dividir un archivo MP4 de 1400 MB en dos partes, un archivo de 700 MB, puede usar el siguiente cmdl: MP4Box -splits 716800 input.mp4 por ejemplo, para concatenar dos archivos, puede usar:

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

O si necesita dividir por tiempo, use -splitx StartTime:EndTime:

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


¡Esto era exactamente lo que necesitaba! Cuando estaba cortando con ffmpeg, los clips no comenzaban en fotogramas clave y tenían congelaciones extrañas en los extremos. ¡Usar MP4Box -splitz funcionó!
Matt

1
¿Cómo puedo recortar el video usando Mp4Box con varios números? por ejemplo, necesito tener clips secundarios en segundos: 5 - 8, 21 - 30, 12 - 18, por lo que necesito tres archivos de video de salida.
mhndev

Y es mucho más fácil de usar EndTimeque -t.
vmassuchetto


2

¿El enfoque posterior ahorra tiempo de cálculo y memoria?

No hay una gran diferencia entre los dos ejemplos que proporcionó. El primer ejemplo corta el video de forma secuencial, en 2 pasos, mientras que el segundo ejemplo lo hace al mismo tiempo (usando hilos). No se notará ninguna aceleración en particular. Puede leer más sobre la creación de múltiples salidas con FFmpeg

Además, lo que puede usar (en FFmpeg reciente) es el muxer segmentador de flujo que puede:

flujos de salida a varios archivos separados de duración casi fija. El patrón de nombre de archivo de salida se puede configurar de manera similar a image2 .


2

Aquí hay un simple archivo bat de Windows para dividir el archivo entrante en 50 partes. Cada parte tiene una duración de 1 minuto. Perdón por un guión tan tonto. Espero que sea mejor tener un script de Windows tonto en lugar de no tenerlo en absoluto. Quizás ayude a alguien. (Basado en "archivo bat para bucle" de este sitio).

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

Este es esencialmente el primer fragmento de código de la pregunta ( ffmpegcomandos consecutivos ) reescrito como un bucle. Esto no responde a la pregunta de si ese enfoque o un solo comando "ahorrará tiempo de cálculo y memoria".
BACON

1

No lo probé, pero esto parece prometedor:

Segmentador de flujo básico

Obviamente, está dividiendo AVI en segmentos del mismo tamaño, lo que implica que estos fragmentos no pierden calidad ni aumentan la memoria o deben recalcularse.

También usa la copia del códec, ¿eso significa que puede manejar flujos muy grandes? Debido a que este es mi problema, quiero descomponer mi avi para poder usar un filtro para deshacerme de la distorsión. Pero todo un avi funciona durante horas.


-1

Esta es una forma perfecta de dividir el video. Lo he hecho anteriormente y me está funcionando bien.

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

Siga esto y estoy seguro de que funcionará perfectamente.


¿Por qué es esta la "manera perfecta" de dividir el video? Como la línea de comando en la pregunta, está pasando -iseguido de -ssy -t. Sin embargo, la pregunta es cómo extraer de manera eficiente varios segmentos del mismo archivo de entrada, mientras que solo extrae un solo segmento. No veo cómo esto responde a la pregunta.
BACON

-2

una forma sencilla es utilizar la opción de recorte con la API basada en URL de publitio .

una vez que haya subido su video, simplemente configure el desplazamiento de inicio y el desplazamiento final en la url (so_2, eo_2) así:

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

esto creará instantáneamente nuevos videos a partir del segundo segundo y 2 segundos de duración. puedes dividir videos de esta manera como quieras.


La pregunta es cuál es más eficiente de dos enfoques para extraer múltiples segmentos de un archivo de entrada con ffmpeg. A menos que tenga una conexión a Internet realmente rápida, creo que tener que cargar el video completo en un servicio en la nube y luego descargar los resultados aumentará significativamente el tiempo de procesamiento. Aún así, esto todavía no responde a la cuestión de qué enfoque con elffmpeg que es más eficiente.
BACON
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.