Quiero cortar un video en partes de unos 10 minutos como esta.
ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 01.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 02.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 03.mp4
Con for
él será así.
for i in `seq 10`; do ffmpeg -i video.mp4 -ss 00:${i}0:00 -t 00:10:00 -c copy ${i].mp4; done;
Pero sólo funciona si la duración es inferior a una hora. ¿Cómo puedo convertir un número a formato de hora en bash shell?
Respuesta1
BASH no es tan malo para este problema. Sólo necesitas usar el date
comando muy poderoso, pero infrautilizado.
for i in {1..10}; do
hrmin=$(date -u -d@$(($i * 10 * 60)) +"%H:%M")
outfile=${hrmin/:/-}.mp4
ffmpeg -i video.mp4 -ss ${hrmin}:00 -t 00:10:00 -c copy ${outfile}
done
date
Comando explicado
date
con -d
banderas te permite configurarcualfecha que desea que se muestre (en lugar de la fecha y hora actuales, que son las predeterminadas). En este caso, lo estoy configurando en una hora UNIX anteponiendo el @
símbolo antes de un número entero. El número entero en este caso es el tiempo en incrementos de diez minutos (calculado por la calculadora incorporada de BASH:) $((...))
.
El +
símbolo indica date
que desea especificar un formato para mostrar los resultados. En nuestro caso, sólo nos importa la hora ( %H
) y los minutos ( %M
).
Y finalmente, -u
se mostrará como hora UTC en lugar de local. Esto es importante en este caso porque especificamos la hora como UTC cuando le dimos la hora UNIX (la hora UNIX siempre es UTC). Lo más probable es que los números no comiencen desde 0 si no especificas -u
.
Sustitución de variables BASH explicada
El date
comando nos dio justo lo que necesitábamos. Pero los dos puntos en un nombre de archivo pueden ser problemáticos o no estándar. Entonces, sustituimos ':' por '-'. Esto se puede hacer con el comando sed
o cut
o tr
, pero debido a que es una tarea tan simple, ¿por qué generar una nueva subcapa cuando BASH puede hacerlo?
Aquí utilizamos la sustitución de expresiones simples de BASH. Para hacer esto, la variable debe estar contenida entre llaves ( ${hrmin}
) y luego usar la notación de barra diagonal estándar. La primera cadena después de la primera barra es el patrón de búsqueda. La segunda cadena después de la segunda barra es la sustitución.
La sustitución de variables BASH y más se pueden encontrar enhttp://tldp.org/LDP/abs/html/parameter-substitution.html.
Respuesta2
Es un poco más complicado pero puedes hacerlo en bash con bastante facilidad. El siguiente ejemplo es para un vídeo de 2 horas; puede establecer los límites ( n<=11
) en consecuencia:
k=0;
i=00;
for ((n=0;n<=11;n++)); do
if [ $i -ge 60 ]; then
let k++; i=00;
fi;
ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4;
let i+=10;
done
Puedes ver lo que esto hace agregando un echo
a la ffmpeg
línea:
echo "ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4";
que imprimirá:
ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 000.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 010.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 020.mp4
ffmpeg -i video.mp4 -ss 00:30:00 -t 00:10:00 -c copy 030.mp4
ffmpeg -i video.mp4 -ss 00:40:00 -t 00:10:00 -c copy 040.mp4
ffmpeg -i video.mp4 -ss 00:50:00 -t 00:10:00 -c copy 050.mp4
ffmpeg -i video.mp4 -ss 01:00:00 -t 00:10:00 -c copy 100.mp4
ffmpeg -i video.mp4 -ss 01:10:00 -t 00:10:00 -c copy 110.mp4
ffmpeg -i video.mp4 -ss 01:20:00 -t 00:10:00 -c copy 120.mp4
ffmpeg -i video.mp4 -ss 01:30:00 -t 00:10:00 -c copy 130.mp4
ffmpeg -i video.mp4 -ss 01:40:00 -t 00:10:00 -c copy 140.mp4
ffmpeg -i video.mp4 -ss 01:50:00 -t 00:10:00 -c copy 150.mp4
Respuesta3
Es una matemática sencilla: la hora es $((i%3600)
, los minutos son $((i/60%60))
, los segundos son $((i%60))
. Para agregar un cero inicial donde sea necesario, un truco simple es sumar 100 y luego quitar el cero inicial 1
. Haga lo mismo con el nombre del archivo si desea evitar los ceros a la izquierda.
for i in $(seq 10); do
minutes=$((i / 60 % 60 + 100)); minutes=${minutes#1}
seconds=$((i%60)); seconds=${seconds#1}
i=$((i+100)); i=${i#1}
ffmpeg -i video.mp4 -ss $((i%3600):$minutes:$seconds -t 00:10:00 -c copy ${i}.mp4
done
Respuesta4
Descubrí que ffmpeg acepta como formato de marca de tiempo no solo [HH:MM:SS], sino también segundos simples.
https://trac.ffmpeg.org/wiki/Seeking%20with%20FFmpeg
Entonces puedo escribir así.
for i in `seq 10`; do ffmpeg -i video.mp4 -ss $((i*10*60)) -t 00:10:00 -c copy ${i].mp4; done;