-
-
Save rriemann/286dc826b0457fc071fa84faf6a8f6ef to your computer and use it in GitHub Desktop.
#!/bin/sh | |
# | |
# Copyright (C) 2013 Mark Hills <[email protected]> | |
# | |
# This program is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU General Public License | |
# version 2, as published by the Free Software Foundation. | |
# | |
# This program is distributed in the hope that it will be useful, but | |
# WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
# General Public License version 2 for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# version 2 along with this program; if not, write to the Free | |
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
# MA 02110-1301, USA. | |
# | |
# | |
# Analyse an audio file and add BPM metadata | |
# | |
set -e | |
usage() | |
{ | |
cat <<END | |
bpm-tag (C) Copyright 2013 Mark Hills <[email protected]> | |
Usage: bpm-tag [options] <file> | |
Tag an audio file with tempo (in beats-per-minute, BPM) | |
-f Ignore existing BPM value | |
-n Display BPM only, don't tag | |
-m Minimum detected BPM | |
-x Maximum detected BPM | |
-h Display this help message and exit | |
See the bpm-tag(1) man page for more information and examples. | |
END | |
} | |
# Parse command line arguments | |
FORCE=false | |
WRITE=true | |
ARGS="" | |
while getopts "fhnm:x:" OPT; do | |
case "$OPT" in | |
f) | |
FORCE=true | |
;; | |
n) | |
WRITE=false | |
;; | |
m) | |
ARGS="$ARGS -m $OPTARG" | |
;; | |
x) | |
ARGS="$ARGS -x $OPTARG" | |
;; | |
h) | |
usage | |
exit 0 | |
;; | |
?) | |
exit 1 | |
esac | |
done | |
shift $((OPTIND - 1)) | |
if [ -z "$1" ]; then | |
usage >&2 | |
exit 1 | |
fi | |
set -u | |
FILE="$1" | |
shift | |
# Don't overwrite an existing BPM tag | |
case "$FILE" in | |
*.flac) | |
BPM=`metaflac --show-tag=BPM "$FILE" | sed -e 's/BPM=//'` | |
;; | |
*.mp3) | |
BPM=`mid3v2 --list "$FILE" | sed -n 's/^TBPM.*: \([0-9\.]\+\)/\1/p'` | |
;; | |
*.ogg) | |
BPM=`vorbiscomment "$FILE" | sed -n 's/^BPM=//p'` | |
;; | |
*) | |
echo "$FILE: file extension not known" >&2 | |
exit 1 | |
;; | |
esac | |
if [ -n "$BPM" ] && ! $FORCE; then | |
echo "$FILE: already tagged, $BPM BPM" >&2 | |
exit 1 | |
fi | |
# Analyse the BPM | |
BPM=`sox -V1 "$FILE" -r 44100 -e float -c 1 -t raw - | bpm $ARGS` | |
if [ -z "$BPM" ]; then | |
exit 1 | |
fi | |
echo "$FILE: $BPM BPM" >&2 | |
if ! $WRITE; then | |
exit 0 | |
fi | |
# Write a BPM tag | |
case "$FILE" in | |
*.flac) | |
metaflac --remove-tag=BPM --set-tag="BPM=$BPM" "$FILE" | |
;; | |
*.mp3) | |
mid3v2 --TBPM "$BPM" "$FILE" | |
;; | |
*.ogg) | |
vorbiscomment -at "BPM=$BPM" "$FILE" | |
;; | |
*) | |
echo "$FILE: don't know how to tag this type of file" >&2 | |
exit 1 | |
esac |
Hi, I had the exact same trouble as you in using id3v2 (it deleted all other tags!!!), I also followed your train of thought and did a straight swap with mid3v2. I didn't notice until yesterday that mid3v2 has a different output format to id3v2. Because of this the ignore function doesn't initialise and scans all files regardless.
My PC is in bits just now but off the top of my head:
id3v2 output is TBPM (SomeText):
mid3v2 output is TBPM=
I can send the edited line to you if you wish , when my PC is back up and running.
@kennyboy1978 Would be nice to have it here as a reference. Thx!
Edited for being an idiot, I was using the -f command in my script!
Anyway things back together again, the line is.....
BPM=mid3v2 -l "$FILE" | sed -En 's/^TBPM=([[:digit:].]+).*/\1/p'
Once this is all said and done, how do I have a program reference the BPM tag? if, for example, I wanted to change how something functions based on the BPM, how do I write the code to check that?
I used some playback apps that would read this value from files and display it in a bpm column that I can use to filter and sort after bpm.
Of course, you can also use another shell app to retrieve the tag value.
Some of those are listed in the various answers here: https://askubuntu.com/questions/226773/how-to-read-mp3-tags-in-shell
I use the below script (based on bpm-tag itself) to check whether the BPM tag is either 0 or empty and then run bpm-tag to generate the tag. If there is a tag found greater than 0 it prints the value of the tag. I know I've gone the long way around (I could have just edited/branched the bpm-tag script) but I'm attempting to learn basic bash and wanted to create my own using bpm-tag as the main program, if that makes sense.
I presume you could use the variables "$FOUNDBPM" (The BPM in a numercial value) and "${FILE%/*}" (The filename of the file being scanned) in your script ?
#!/bin/bash
find "$1" -type f ( -name ".mp3" -o -name ".flac" ) | while read -r FILE; do
case "$FILE" in
*.flac)
FOUNDBPM=$(metaflac --show-tag=BPM "$FILE" | sed -e 's/BPM=//')
;;
.mp3)
FOUNDBPM=$(mid3v2 -l "$FILE" | sed -En 's/^TBPM=([[:digit:].]+)./\1/p')
;;
esac
if [ 0 == "$FOUNDBPM" ] || [ -z "$FOUNDBPM" ]
then
echo "${FILE%/}" contains a track that is has no BPM set, now running bpm-tag.
bpm-tag -f -m 120 -x 250 "$FILE"
else
echo "${FILE%/}" has already been given the value of "$FOUNDBPM" BPM
fi
done
I changed: