Eu tenho uma lista de .ts
arquivos:
out1.ts ... out749.ts out8159.ts out8818.ts
Como posso obter a duração total (tempo de execução) de todos esses arquivos?
shell-script
video
k961
fonte
fonte
Respostas:
Eu não tenho
.ts
aqui, mas isso funciona para.mp4
. Useffprobe
(parte deffmpeg
) para obter o tempo em segundos, por exemplo:assim, para todos os
.mp4
arquivos no diretório atual:em seguida, usar
paste
para passar a saída parabc
e obter o tempo total em segundos:Portanto, para
.ts
arquivos, você pode tentar:Outra ferramenta que funciona para os arquivos de vídeo que tenho aqui é
exiftool
, por exemplo:Comprimento total para todos os
.mp4
arquivos no diretório atual:Você também pode canalizar a saída para outro comando para o qual converter o total
DD:HH:MM:SS
, veja as respostas aqui .Ou use
exiftool
internoConvertDuration
para isso (você precisa de uma versão relativamente recente):fonte
ffprobe
antes.paste
ebc
! muito mais limpo do que comawk
, digamos.bc
faça precisão arbitrária, uma desvantagem é que...| paste -sd+ - | bc
atingirá o limite de tamanho da linha em algumasbc
implementações (por exemplo,seq 429 | paste -sd+ - | bc
falha no OpenSolarisbc
) ou terá o potencial de usar toda a memória em outras.avprobe
no repositório do Arch (prolly porque entra em conflito comffmpeg
), portanto, não é possível experimentá-lo em caixas eletrônicos, mas fornece a duração do arquivo se você o executar dessa maneira:avprobe -show_format_entry duration myfile.mp4
ouavprobe -loglevel quiet -show_format_entry duration myfile.mp4
? Eu acho que um desses comandos deve fornecer uma única linha de saída com a duração do arquivo. Não tenho certeza.Isso usa
ffmpeg
e imprime o tempo limite em segundos totais:Explicação:
for f in *.ts; do
itera cada um dos arquivos que termina em ".ts"ffmpeg -i "$f" 2>&1
redireciona a saída para o stderrgrep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' '
isola o tempoawk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
Converte o tempo em segundostimes+=("$_t")
adiciona os segundos a uma matrizecho "${times[@]}" | sed 's/ /+/g' | bc
expande cada um dos argumentos e substitui os espaços e os canaliza parabc
uma calculadora linux comumfonte
Simplificando a resposta de @ jmunsch e usando o
paste
que acabei de aprender com a resposta de @ slm , você pode terminar com algo assim:Assim como jmunsch, estou usando
ffmpeg
para imprimir a duração, ignorando o erro sobre um arquivo de saída ausente e procurando a linha de duração na saída de erro. Chamoffmpeg
com todos os aspectos do código do idioma forçados para o código C padrão, para que não precise me preocupar com mensagens de saída localizadas.Em seguida, estou usando um único em
awk
vez do delegrep | grep | head | tr | awk
. Essaawk
invocação procura a linha (espero que única) que contémDuration:
. Usando dois pontos como separador, esse rótulo é o campo 1, as horas são o campo 2, os minutos são arquivados 3 e o campo de segundos 4. A vírgula final após os segundos não parece incomodar o meuawk
, mas se alguém tiver problemas, ele pode incluir umtr -d ,
no pipeline entreffmpeg
eawk
.Agora vem a parte do slm: estou usando
paste
para substituir novas linhas por sinais de mais, mas sem afetar a nova linha à direita (ao contrário do quetr \\n +
eu tinha na versão anterior desta resposta). Isso fornece a expressão sum que pode ser fornecidabc
.Inspirada na idéia do slm de usar
date
para manipular formatos semelhantes ao tempo, aqui está uma versão que o usa para formatar os segundos resultantes como dias, horas, minutos e segundos com parte fracionária:A parte interna
$(…)
é exatamente como antes. Utilizando o@
caractere como indicação, usamos esse número como o número de segundos desde 1º de janeiro de 1970. A "data" resultante é formatada como dia do ano, hora e nanossegundos. A partir desse dia do ano, subtraímos um, uma vez que uma entrada de zero segundos já leva ao dia 1 daquele ano de 1970. Não acho que haja uma maneira de obter as contagens do dia do ano começando em zero.A final
sed
se livra de zeros à direita extras. ATZ
definição deve esperamos forçar o uso de UTC, de modo que o horário de verão não vai interferir com realmente coleções de vídeo grandes. Se você tiver mais de um ano de vídeo, essa abordagem ainda não funcionará.fonte
Não estou familiarizado com a
.ts
extensão, mas supondo que eles sejam algum tipo de arquivo de vídeo que você possa usarffmpeg
para identificar a duração de um arquivo da seguinte forma:Podemos então dividir essa saída, selecionando apenas o tempo de duração.
Portanto, agora precisamos apenas de uma maneira de percorrer nossos arquivos e coletar esses valores de duração.
NOTA: Aqui para o meu exemplo, eu simplesmente copiou o meu arquivo de amostra
some.mp4
e nomeou-o1.mp4
,2.mp4
e3.mp4
.Convertendo tempos em segundos
O seguinte snippet pega as durações de cima e as converte em segundos.
Isso leva nossas durações e as coloca em uma variável
$dur
, conforme percorremos os arquivos. Odate
comando é então usado para calcular o número de segundos sine a época do Unix (01/01/1970). Aqui está odate
comando acima dividido, para que seja mais fácil ver:NOTA: O uso
Exemplodate
dessa maneira funcionará apenas se todos os seus arquivos tiverem uma duração inferior a 24 horas (ou seja, 86400 segundos). Se você precisar de algo que possa lidar com durações maiores, use-o como uma alternativa:Totalizando os tempos
Podemos então pegar a saída do nosso
for
loop e executá-lo em umpaste
comando que incorporará+
sinais entre cada número, da seguinte forma:Finalmente, executamos isso na calculadora da linha de comando,
bc
para resumir:Resultando na duração total de todos os arquivos, em segundos. Obviamente, isso pode ser convertido para outro formato, se necessário.
fonte
date
choke poder seffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
retorna algo como26:33:21.68
(isto é, duração ≥ 24 horas / 86400 segundos)paste
a atenção. Eu acho quejava -classpath $(find -name \*.jar | paste -sd:)
vai ser muito útil para mim, considerando os hacks que eu usei para isso no passado.paste
is my favorite command 8-)Saindo da resposta aceita e usando a ferramenta clássica de polimento reverso UNIX:
Ou seja: Appening
+
e, emp
seguida, canalizando issodc
e você receberá sua soma.fonte
bc
recebe muito amor. Você é tudo colocando+
sinais entre cada linha (juntando on+
), enquanto que com reverso-polonês você pode simplesmente atirar um+
no fim ep
rint-lo;)Certifique-se de ter o MPlayer instalado.
fonte
Como o ubuntu envia libav em vez de ffmpeg:
Fortemente baseado em idéias MvG
fonte
Bem, todas essas soluções precisam de um pouco de trabalho, o que eu fiz foi muito simples, 1)
foi para a pasta desejada e clique com o botão direito do mouse -> abrir com outro aplicativo
Em seguida, selecione VLC media player,
aqui está um exemplo
1
2)
3)
Você pode ver logo abaixo da barra de ferramentas, a lista de reprodução [10:35:51] gravada, para que a pasta contenha 10 horas e 35 minutos e 51 segundos de duração do total de vídeos
fonte
Eu tinha subdiretórios na pasta atual, então tive que calcular recursivamente a duração:
find . -iname '*.mp4' -print0 | xargs --null exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n1
fonte