Поиск песен определенной длины в mp3-коллекции

Поиск песен определенной длины в mp3-коллекции

Как мне искать в каталоге mp3-файлов песни определенной длительности. Пример:

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

Возвращает все mp3-файлы в emb/каталоге, длительность песен которых составляет от 3:00 до 3:15 минут.

Я использую Linux Mint, Ubuntu, а также CentOS.

решение1

Сначала установите mp3info, он должен быть в репозиториях вашего дистрибутива (вы этого не сказали, поэтому я предполагаю, что вы используете Linux какой-то из видов). Если у вас дистрибутив на основе Debian, вы можете сделать это с помощью

sudo apt-get install mp3info

После mp3infoустановки вы можете искать в каталоге musicпесни определенной длительности с помощью этой команды:

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

Команда выше будет искать music/файлы mp3 и выводить их имя и длину, если эта длина больше или равна 180 секундам (3:00) и меньше или равна 195 секундам (3:15). man mp3infoПодробнее о формате вывода см. здесь.

Если вы хотите иметь возможность вводить время в формате ММ:СС, все становится немного сложнее:

#!/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

Сохраните скрипт выше findmp3и запустите его следующим образом:

findmp3 3:00 3:15 music/

решение2

Сомневаюсь, что есть существующий findmp3инструмент. Следуя философии unix, его можно построить из findпоиска .mp3файлов, другого инструмента для отчета о длине каждого findнайденного файла и некоторого клея для обработки оболочки/текста.

SoXобщедоступная утилита для работы со звуковыми файлами (sox для звука то же, что sed или awk для текстовых файлов). Командаsoxiотображает информацию о звуковом файле. В частности, soxi -Dвыводит длительность в секундах.

Для каждого .mp3файла фрагмент ниже вызывает soxiи анализирует его вывод. Если длительность находится в желаемом диапазоне, вызов shвозвращает статус успеха, поэтому -printвыполняется действие для печати имени файла.

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

В bash, ksh93 или zsh вместо find. В ksh set -o globstarсначала запустите. В bash shopt -s globstarсначала запустите. Обратите внимание, что в bash (но не в ksh или zsh) **/рекурсия выполняется через символические ссылки на каталоги.

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

решение3

С использованием 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

mp3infoодин лайнер:

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

Или в OS X:

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

решение4

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

С помощью команды выше вы можете получить свою длительность, поэтому вы можете написать скрипт, чтобы указать домен для длительности. Также вы можете использовать:

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

Замените yourPath на корень вашего mp3-репозитория.

Связанный контент