como converter número para formato de hora em shell script?

como converter número para formato de hora em shell script?

Quero cortar um vídeo em partes de cerca de 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

Com forisso será assim.

for i in `seq 10`; do ffmpeg -i video.mp4 -ss 00:${i}0:00 -t 00:10:00 -c copy ${i].mp4; done;

Mas só funciona se a duração for inferior a uma hora. Como posso converter o número para o formato de hora no shell bash?

Responder1

BASH não é tão ruim para esse problema. Você só precisa usar o datecomando muito poderoso, mas subutilizado.

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

datecom -dsinalizadores permite que você definaqualdata que você deseja exibir (em vez da data e hora atuais, que é o padrão). Nesse caso, estou configurando para um horário UNIX, acrescentando o @símbolo antes de um número inteiro. O número inteiro, neste caso, é o tempo em incrementos de dez minutos (calculado pela calculadora integrada do BASH:) $((...)).

O +símbolo indica dateque você gostaria de especificar um formato para exibição dos resultados. No nosso caso, nos preocupamos apenas com a hora ( %H) e os minutos ( %M).

E, finalmente, -udeve ser exibido como hora UTC em vez de local. Isso é importante neste caso porque especificamos a hora como UTC quando atribuímos a hora UNIX (a hora UNIX é sempre UTC). Os números provavelmente não começariam em 0 se você não especificasse -u.

Substituição de variável BASH explicada

O datecomando nos deu exatamente o que precisávamos. Mas dois pontos em um nome de arquivo podem ser problemáticos/não padrão. Então, substituímos o ':' por um '-'. Isso pode ser feito pelo comando sedor cutou tr, mas como é uma tarefa tão simples, por que gerar um novo subshell quando o BASH pode fazer isso?

Aqui usamos a substituição de expressão simples do BASH. Para fazer isso, a variável deve estar contida entre chaves ( ${hrmin}) e, em seguida, usar a notação de barra padrão. A primeira string após a primeira barra é o padrão de pesquisa. A segunda string após a segunda barra é a substituição.

Substituição de variável BASH e mais podem ser encontradas emhttp://tldp.org/LDP/abs/html/parameter-substitution.html.

Responder2

É um pouco mais complicado, mas você pode fazer isso no bash com bastante facilidade. O exemplo abaixo é para um vídeo de 2h, você pode definir os limites ( n<=11) de acordo:

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

Você pode ver o que isso faz adicionando um echoà ffmpeglinha:

echo "ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4";

que irá 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

Responder3

É matemática simples: o número das horas é $((i%3600), os minutos são $((i/60%60)), os segundos são $((i%60)). Para adicionar um zero à esquerda quando necessário, um truque simples é adicionar 100 e, em seguida, retirar o zero à esquerda 1. Faça o mesmo com o nome do arquivo se quiser evitar zeros à esquerda.

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

Responder4

Descobri que o ffmpeg aceita como formato de carimbo de data/hora não apenas [HH:MM:SS], mas também segundos simples.

https://trac.ffmpeg.org/wiki/Seeking%20with%20FFmpeg

Então posso escrever assim.

for i in `seq 10`; do ffmpeg -i video.mp4 -ss $((i*10*60)) -t 00:10:00 -c copy ${i].mp4; done;

informação relacionada