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 for
isso 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 date
comando 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
sinalizadores 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 date
que 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, -u
deve 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 date
comando 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 sed
or cut
ou 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
à ffmpeg
linha:
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;