На сайті 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="${file##*.}"
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="${2%%.*}"
local ext="${file##*.}"
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" "${bpm%%.*}" >/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
Насолоджуйтесь! :)