Buscar en la colección de mp3 canciones con una duración determinada

Buscar en la colección de mp3 canciones con una duración determinada

¿Cómo puedo buscar en un directorio de archivos mp3 canciones de cierta duración? Ex:

findmp3 -min=03:00 -max=03:15 /music/mp3/ebm/

Devolvería todos los archivos mp3 en el emb/directorio que tengan una duración de canción de entre 3:00 y 3:15 minutos.

Utilizo Linux Mint, Ubuntu y CentOS.

Respuesta1

Primero instálalo mp3info, debería estar en los repositorios de tu distribución (no lo has dicho, así que supongo que estás usando algún tipo de Linux). Si tienes una distribución basada en Debian, puedes hacerlo con

sudo apt-get install mp3info

Una vez mp3infoinstalado, puedes buscar en el directorio musiccanciones de cierta duración con este comando:

find music/ -name "*mp3" | 
  while IFS= read -r f; do 
   length=$(mp3info -p "%S" "$f"); 
   if [[ "$length" -ge "180" && "$length" -le "195" ]]; then 
     echo "$f"; 
   fi;  
done

El comando anterior buscará music/archivos mp3 e imprimirá su nombre y longitud si esa duración es mayor o igual a 180 segundos (3:00) y menor o igual a 195 segundos (3:15). Consulte man mp3infopara obtener más detalles sobre su formato de salida.

Si desea poder ingresar horas en formato MM:SS, se vuelve un poco más complejo:

#!/usr/bin/env bash

## Convert MM:SS to seconds.
## The date is random, you can use your birthday if you want.
## The important part is not specifying a time so that 00:00:00
## is returned.
d=$(date -d "1/1/2013" +%s);

## Now add the number of minutes and seconds
## you give as the first argument
min=$(date -d "1/1/2013 00:$1" +%s);
## The same for the second arument
max=$(date -d "1/1/2013 00:$2" +%s);

## Search the target directory for files
## of the correct length.
find "$3" -name "*mp3" | 
  while IFS= read -r file; do 
   length=$(mp3info -p "%m:%s" "$file"); 
   ## Convert the actual length of the song (mm:ss format)
   ## to seconds so it can be compared.
   lengthsec=$(date -d "1/1/2013 00:$length" +%s);

   ## Compare the length to the $min and $max
   if [[ ($lengthsec -ge $min ) && ($lengthsec -le $max ) ]]; then 
       echo "$file"; 
   fi; 
done

Guarde el script anterior como findmp3y ejecútelo así:

findmp3 3:00 3:15 music/

Respuesta2

Dudo que exista una findmp3herramienta. Siguiendo la filosofía de Unix, se puede construir a partir findde archivos para buscar .mp3, otra herramienta para informar la longitud de cada archivo que findse encuentra y algo de pegamento para procesamiento de texto/shell.

SoXes una utilidad comúnmente disponible para trabajar con archivos de sonido (sox es para sonar lo que sed o awk son para archivos de texto). El comandosoximuestra información sobre un archivo de sonido. En particular, soxi -Dimprime la duración en segundos.

Para cada .mp3archivo, el siguiente fragmento llama soxiy analiza su salida. Si la duración está dentro del rango deseado, la shllamada devuelve un estado exitoso, por lo que -printse ejecuta la acción para imprimir el nombre del archivo.

find /music/mp3/ebm -type f -name .mp3 -exec sh -c '
    d=$(soxi -D "$0")
    d=${d%.*} # truncate to an integer number of seconds
    [ $((d >= 3*60 && d < 3*60+15)) -eq 1 ]
' {} \; -print

En bash, ksh93 o zsh, puedes usar globbing recursivo en lugar de find. En ksh, ejecute set -o globstarprimero. En bash, ejecuta shopt -s globstarprimero. Tenga en cuenta que en bash (pero no en ksh o zsh), **/se recurre a través de enlaces simbólicos a directorios.

for f in /music/mp3/ebm/**/*.mp3; do
  d=$(soxi -D "$0")
  d=${d%.*} # truncate to an integer number of seconds (needed in bash only, ksh93 and zsh understand floating point numbers)
  if ((d >= 3*60 && d < 3*60+15)); then
    echo "$f"
  fi
done

Respuesta3

Usando ffmpeg:

find . -name \*.mp3|while IFS= read -r l;do ffprobe -v 0 -i "$l" -show_streams|awk -F= '$1=="duration"&&$2>=180&&$2<=195'|read&&echo "$l";done

mp3infoun trazador de líneas:

find . -name \*.mp3 -exec mp3info -p '%S %f\n' {} +|awk '$1>=180&&$1<=195'|cut -d' ' -f2-

O en OS X:

mdfind 'kMDItemDurationSeconds>=180&&kMDItemDurationSeconds<=195&&kMDItemContentType=public.mp3' -onlyin .

Respuesta4

ffmpeg -i  yourmp3.mp3  2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'  |awk {'print $1'}

Con el comando anterior, puede obtener su duración, por lo que puede crear una secuencia de comandos para especificar un dominio para la duración. También puedes usar:

find yourPath -iname "*mp3" -exec ffmpeg -i  {}   2>&1 | grep Duration | sed 's/Duration: \(.*\), start/\1/g'  |awk {'print $1'}

Reemplace yourPath con la raíz de su repositorio de mp3.

información relacionada