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

2

Eu quero cortar um vídeo em partes de 10 minutos como este.

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 for 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 funciona apenas se a duração for inferior a uma hora. Como posso converter o formato de número para hora no bash shell?

    
por ironsand 06.10.2013 / 05:02

4 respostas

5

BASH não é tão ruim para esse problema. Você só precisa usar o comando date 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

date comando explicado

date com -d flags permite que você defina qual data que deseja exibir (em vez da data e hora atuais, que é o padrão). Neste caso, estou configurando-o para uma hora do UNIX, prefixando o símbolo @ antes de um inteiro. O inteiro neste caso é o tempo em incrementos de dez minutos (calculado pela calculadora interna BASH: $((...)) ).

O símbolo + informa ao date que você gostaria de especificar um formato para exibir os resultados. No nosso caso, nos preocupamos apenas com a hora ( %H ) e os minutos ( %M ).

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

Substituição de variável BASH explicada

O comando date nos deu exatamente o que precisávamos. Dois pontos em um nome de arquivo podem ser problemáticos / não padronizados. Então, nós substituímos o ':' por um '-'. Isso pode ser feito pelo comando sed ou cut ou tr , mas como essa é uma tarefa tão simples, por que gerar um novo subshell quando o BASH pode fazer isso?

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

A substituição de variáveis BASH e muito mais pode ser encontrada no link .

    
por 06.10.2013 / 06:40
2

É um pouco mais complicado, mas você pode fazê-lo facilmente facilmente. 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 à linha ffmpeg :

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

que será impresso:

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
    
por 06.10.2013 / 06:01
1

É uma matemática simples: o valor da hora é $((i%3600) , os minutos são $((i/60%60)) , os segundos são $((i%60)) . Para adicionar um zero à esquerda, onde necessário, um truque simples é adicionar 100 e, em seguida, despir o primeiro1. 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
    
por 07.10.2013 / 00:42
0

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

link

Então eu 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;
    
por 07.10.2013 / 09:21