Linux: ¿Cómo enumerar todos los archivos de vídeo con una resolución exacta de 720p?

Linux: ¿Cómo enumerar todos los archivos de vídeo con una resolución exacta de 720p?

Tengo varios archivos de video con diferentes resoluciones. Ahora quiero enumerar sólo los nombres de archivos de vídeo con, por ejemplo, una resolución de 720p. Prefiero una línea en la línea de comando de bash y puedo recibir información de video útil, incluida la resolución, cuando ejecuto:

avconv -i video.mp4

pero esta combinación:

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

produce el error: ejecutivo: falta argumento.

Soy honesto, apenas tengo peleas con las estructuras de comando de bash, especialmente con los comandos combinados. Entonces, ¿qué hay de malo en mi cadena de comando combinada?

Gracias.

Respuesta1

Quizás este comando logre lo que buscas:

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

Respuesta2

Puede resultar sorprendente, pero -execse puede utilizar como prueba en findla invocación:

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

El comando anterior descenderá a los subdirectorios. Para buscar en el directorio actual utilice únicamente -maxdepth 1, es decir:

find -maxdepth 1 -type f -exec …

Tenga en cuenta que ffprobeprobará todos los archivos. Obviamente fallará con archivos que no sean multimedia, pero es posible que obtenga medios que no sean de video (como .jpg) en la salida final. Para evitar esto, findse deben realizar algunas pruebas adicionales antes -exec, por ejemplo:

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

O mejor, puedes probar el tipo mime con 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

Lea man findpara obtener más información.


EDITAR:

Este comando usa (mal) avconv, como usted solicitó:

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

El problema es que cada invocación del avconvmismo arroja un error. Simplemente lo ignoramos y extraemos la información que necesitamos. Esta es una solución algo fea. No estoy del todo seguro de que avconvse comporte como el mío, es posible que deba reemplazarlo Stream.*x720con alguna otra expresión regular.


¿Qué hay de malo en mi cadena de comando combinada?

  • find -execrequiere cerrar con \;o +,
  • hay $(sin) después de editar la pregunta, están ""intercalados (no anidados) con $(),
  • *720*puede desencadenar el globalización de la capa, debería ser "*720*"(estoy hablando de sh, no de la capa exterior),
  • el resultado de avconvtu intento de analizar va a stderr, creo que necesitas redirigirlo antes de poder analizarlo.
  • y tal vez algo más.

Respuesta3

No conozco avconv, normalmente uso ffmpeg. Si lo instalas podrías 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

Respuesta4

Por el momento he encontrado una solución utilizable:

 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

¿Aquí puedo repetir todos los m? archivos de vídeo e imprima su nombre, incluida la condición "720". Sin la parte if podría mostrarme todos los videos y sus resoluciones.

Resolví esto con la ayuda de otras respuestas aquí.

Cuando intento combinar find y exec y la parte do de la solución anterior, solo recibo mensajes "E: Error de lectura de archivo" como resultado de mediainfo para cada tema:

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

Como dije, la construcción 'si' funciona (para el directorio real), pero intentaré ejecutarla también con buscar.

información relacionada