¿Cómo convertir un número a formato de hora en un script de Shell?

¿Cómo convertir un número a formato de hora en un script de Shell?

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

dateComando explicado

datecon -dbanderas 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 dateque desea especificar un formato para mostrar los resultados. En nuestro caso, sólo nos importa la hora ( %H) y los minutos ( %M).

Y finalmente, -use 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 datecomando 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 sedo cuto 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 echoa la ffmpeglí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;

información relacionada