Linux: Como listar todos os arquivos de vídeo com resolução exata de 720p?

Linux: Como listar todos os arquivos de vídeo com resolução exata de 720p?

Tenho vários arquivos de vídeo com resoluções diferentes. Agora quero listar apenas os nomes dos arquivos de vídeo com, por exemplo, resolução de 720p. Eu prefiro um liner na linha de comando do bash e posso receber informações úteis de vídeo, incluindo resolução, quando executo:

avconv -i video.mp4

mas esta combinação:

find -exec sh -c 'if [[ "$(avconv -i {}") == *720* ]] ; then echo 720 found; fi;'

produz o erro: exec - argumento ausente.

Para ser sincero, quase não brigo com estruturas de comando bash, especialmente comandos combinados. Então, o que há de errado na minha sequência de comandos combinada?

Obrigado.

Responder1

Talvez este comando cumpra o que você está procurando:

for i in *.mp4; do if [[ $(avconv -i $i) =~ .*720.* ]]; then echo $i; fi; done

Responder2

Pode ser surpreendente, mas -execpode ser usado como teste na findinvocação:

find -type f -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

O comando acima descerá para subdiretórios. Para pesquisar apenas no diretório atual use -maxdepth 1, ou seja:

find -maxdepth 1 -type f -exec …

Observe que isso ffprobetestará todos os arquivos. Obviamente, falhará em arquivos que não sejam de mídia, mas você poderá obter mídia que não seja de vídeo (como .jpg) na saída final. Para evitar isso, alguns testes adicionais finddevem ser usados ​​antes -exec, por exemplo:

find -maxdepth 1 -type f \( -iname "*.avi" -o -iname "*.mp4" -o -iname "*.mkv" \) -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Ou melhor, você pode testar o tipo MIME com file:

find -maxdepth 1 -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'ffprobe -show_streams 2>/dev/null "$1" | grep -q coded_height=720' sh {} \; -print

Leia man findpara saber mais.


EDITAR:

Este comando (mal) usa avconv, conforme você solicitou:

find -exec sh -c 'file --mime-type "$1" | grep -q "video/"' sh {} \; -exec sh -c 'avconv 2>&1 -i "$1" | grep -q "Stream.*x720"' sh {} \; -print

O problema é que cada invocação avconvgera um erro. Nós simplesmente ignoramos e extraímos as informações de que precisamos. Esta é uma solução um tanto feia. Não tenho certeza se você avconvse comporta como o meu; pode ser necessário substituí-lo Stream.*x720por algum outro regex.


o que há de errado na minha string de comando combinada?

  • find -execrequer fechar com \;ou +,
  • existe $(sem) depois que você editou a pergunta, há ""intercalação (não aninhada) com $(),
  • *720*pode desencadear o globbing do shell, deveria ser "*720*"(estou falando sh, não do shell externo),
  • a saída que avconvvocê tenta analisar vai para stderr, acho que você precisa redirecioná-la antes de poder analisá-la,
  • e talvez outra coisa.

Responder3

Não conheço avconv, costumo usar ffmpeg. Se você instalá-lo, você pode usar este script

#!/bin/bash
OIFS="$IFS"
IFS=$'\n'

files=$(find ./ -type f -exec ls {} + | grep ".*\.mpg$\|.*\.avi$\|.*\.mkv$\|.*\.mp4$"| cut -c3-)

for f in ${files}
do
resolution=$(ffprobe -v error -select_streams v:0 -show_entries 
stream=height -of csv=s=x:p=0 ${f})
printf "%-100s %-10s\n" $f $resolution
done

Responder4

No momento, encontrei uma solução utilizável:

 for i in ls *.m??; do sm=$(mediainfo $i | grep Height | sed 's/  //g');if [[ "$sm" == *720* ]]; then printf "Video: %-s $i %-s $sm \n"; fi; done

Aqui eu posso fazer um loop em todos os m?? arquivos de vídeo e imprima seu nome incluindo a condição "720". Sem a parte if eu poderia deixar me mostrar todos os vídeos e suas resoluções.

Eu resolvi isso com a ajuda de outras respostas aqui.

Quando tento combinar find e exec e a parte do da solução acima, recebo apenas mensagens "E: Erro de leitura de arquivo" como resultado do mediainfo para cada assunto:

 find -exec mediainfo "{}" \; -exec bash -c 'sm=$(mediainfo ${} | grep 720) : ; echo $sm' \;

Como eu disse, a construção 'if' funciona (para o diretório real), mas tentarei fazê-la funcionar com find também.

informação relacionada