На сайте DaveParillo предположил, что я нашел проект BpmDj . У него есть bpmcount
исполняемый файл, который очень хорошо вычисляет bpm: он обрабатывает mp3 и flac:
161.135 Metallica/2008 - Death Magnetic/01-That Was Just Your Life.flac 63.5645 Doom3.mp3
Осталось только пометить коллекцию. Я буду обновлять этот ответ всякий раз, когда мне удастся. Спасибо! :)
Шаг 1
Запустите bpmcount
всю коллекцию и сохраните результаты в текстовый файл. Проблема заключается в том, что bpmcount
время от времени происходит сбой, и он пытается использовать до 2 ГБ памяти, когда обрабатывает несколько файлов, поэтому мы должны передавать его с именами файлов по одному. Как это:
musicdir='/home/ootync/music' find "$musicdir" -iregex ".*\.\(mp3\|ogg\|flac\|ape\)" -exec bpmcount {} \; \ | fgrep "$musicdir" > "$musicdir/BPMs.txt"
Шаг 2
Нам понадобятся некоторые дополнительные пакеты: apt-get install vorbis-tools flac python-mutagen
. Теперь посмотрим, как можно добавить тег 'bpm':
mid3v2 --TBPM 100 doom3.mp3 vorbiscomment -a -t "BPM=100" mother.ogg metaflac --set-tag="BPM=100" metallica.flac
Увы, у меня нет * .ape треков
Теперь у нас есть BPM, и вся коллекция должна быть переназначена. Вот сценарий:
cat "$musicdir/BPMs.txt" | while read bpm file ; do bpm=`printf "%.0f" "$bpm"` ; case "$file" in *.mp3) mid3v2 --TBPM "$bpm" "$file" > /dev/null ;; *.ogg) vorbiscomment -a -t "BPM=$bpm" "$file" ;; *.flac) metaflac --set-tag="BPM=$bpm" "$file" ;; esac done
Шаг 2.1. Пересмотр. Вот скрипт, который добавит BPM-теги в вашу коллекцию.
Он запускает один процесс на ядро процессора, чтобы ускорить процесс. Кроме того, он не использует временные файлы и способен определять, был ли файл уже помечен.
Кроме того, я обнаружил, что FLAC иногда имеет внутри ID3 и VorbisComment. Этот скрипт обновляет оба.
#!/bin/bash function display_help() { cat <<-HELP Recursive BPM-writer for multicore CPUs. It analyzes BPMs of every media file and writes a correct tag there. Usage: $(basename "$0") path [...] HELP exit 0 } [ $# -lt 1 ] && display_help #=== Requirements requires="bpmcount mid3v2 vorbiscomment metaflac" which $requires > /dev/null || { echo "E: These binaries are required: $requires" >&2 ; exit 1; } #=== Functions function bpm_read(){ local file="$1" local ext="$" declare -l ext # Detect { case "$ext" in 'mp3') mid3v2 -l "$file" ;; 'ogg') vorbiscomment -l "$file" ;; 'flac') metaflac --export-tags-to=- "$file" ;; esac ; } | fgrep 'BPM=' | cut -d'=' -f2 } function bpm_write(){ local file="$1" local bpm="$" local ext="$" declare -l ext echo "BPM=$bpm @$file" # Write case "$ext" in 'mp3') mid3v2 --TBPM "$bpm" "$file" ;; 'ogg') vorbiscomment -a -t "BPM=$bpm" "$file" ;; 'flac') metaflac --set-tag="BPM=$bpm" "$file" mid3v2 --TBPM "$bpm" "$file" # Need to store to ID3 as well :( ;; esac } #=== Process function oneThread(){ local file="$1" #=== Check whether there's an existing BPM local bpm=$(bpm_read "$file") [ "$bpm" != '' ] && return 0 # there's a nonempty BPM tag #=== Detect a new BPM # Detect a new bpm local bpm=$(bpmcount "$file" | grep '^[0-9]' | cut -f1) [ "$bpm" == '' ] && { echo "W: Invalid BPM '$bpm' detected @ $file" >&2 ; return 0 ; } # problems # Write it bpm_write "$file" "$" >/dev/null } NUMCPU="$(grep ^processor /proc/cpuinfo | wc -l)" find $@ -type f -regextype posix-awk -iregex '.*\.(mp3|ogg|flac)' \ | while read file ; do [ `jobs -p | wc -l` -ge $NUMCPU ] && wait echo "$file" oneThread "$file" & done
Наслаждайтесь! :)