/
flac2mp3
executable file
·148 lines (124 loc) · 4.14 KB
/
flac2mp3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/bin/bash
#
# flac2mp3 - a mass conversion utility
# requires: `flac' and `lame'
#
ARG0=${0##*/}
TAGVARS=(album artist date genre title tracknumber)
# runtime options
FORCE=0
LAME_OPTS="-h"
FLAC_OPTS=""
PRESERVE=0
RECURSE=0
VERBOSE=1
QUITONWARN=0
warn() {
local mesg=$1; shift
printf '\e[1;33m:: \e[0m%s\n' "$mesg"
(( QUITONWARN )) && exit 1
} >&2
die() {
local mesg=$1; shift
printf '\e[1;31m:: \e[0m%s\n' "$mesg"
exit 1
} >&2
mkdir_vp() {
mkdir -p "$1" && printf "%s: created directory \`%s'" "$ARG0" "$!"
}
usage() {
printf "usage: $ARG0 [options] SOURCE... DESTINATION\n"
printf " $ARG0 [options] -t DESTINATION SOURCE...\n\n"
printf " -f overwrite existing files\n"
printf " -h display this help message\n"
printf " -l ARGS additional parameters to pass to lame\n"
printf " -q don't print to stdout\n"
printf " -r convert directories recursively (implies -p)\n"
printf " -t PATH use PATH as destination for converted SOURCEs\n"
printf " -w quit on warnings\n\n"
} >&2
# find flac files in a given dir, recursing unless told otherwise
expand_dir() {
for arg in "$@"; do
find "$arg" -type f -name '*.flac'
done
}
# convert with tags (only setting tags if they exist)
convert() {
local input output artist title album date tracknumber genre
input=$1
output=$2
eval $(metaflac --export-tags-to - "$1" | awk -F'=' '!/[ ].*=/{ printf "%s=\"%s\"\n", tolower($1), $2 }')
(( VERBOSE )) || { LAME_OPTS+=" --quiet"; FLAC_OPTS+=" --silent"; }
flac -cd $FLAC_OPTS "$input" | lame --add-id3v2 $LAME_OPTS \
${artist:+--ta "$artist"} \
${title:+--tt "$title"} \
${tracknumber:+--tn "$tracknumber"} \
${genre:+--tg "$genre"} \
${comment:+--tc "$comment"} \
${album:+--tl "$album"} \
- "${output}"
}
while getopts ":fhl:qrt:w" opt; do
case $opt in
f) FORCE=1 ;;
h) usage; exit 1 ;;
l) LAME_OPTS+=" $OPTARG" ;;
q) VERBOSE=0 ;;
r) RECURSE=1 PRESERVE=1 ;;
t) DEST=$OPTARG ;;
w) QUITONWARN=1 ;;
\?) die "$ARG0: invalid option -- '$OPTARG'" ;;
\:) die "$ARG0: option '$OPTARG' requires an argument" ;;
esac
done
shift $(( OPTIND - 1 ))
# basic arg check
(( $# )) || { usage; exit; }
# deal with args in an array rather than as positional params. this will make
# life easier if we need to strip the last param for the destination.
args=("$@")
# if -t wasn't given, strip the last arg for the destination
if [[ -z $DEST ]]; then
DEST=${!#}
args=("${@:1:(( $# - 1 ))}")
fi
# all but the last part of the dest needs to exist
fulldest=$(readlink -f "$DEST")
if [[ -z $fulldest ]]; then
die "error: cannot create directory \`$DEST': No such file or directory"
fi
# main loop
for arg in "${args[@]}"; do
if [[ -d $arg ]]; then
# only handle directories if -r was passed
(( ! RECURSE )) && { warn "warning: omitting directory \`$arg'"; continue; }
IFS=$'\n' read -d'\0' -r -a flacs < <(expand_dir "$arg")
else
flacs=$arg
fi
for flac in "${flacs[@]}"; do
if [[ ! $(file -bi --mime-type "$flac") = audio/x-flac ]]; then
warn "warning: '$flac' is not a valid flac file"
fi
if (( PRESERVE )); then
# use basename(1) instead of a bash PE so we don't need to fight with the
# possibility of a superfluous trailing slash
outfile=$fulldest/$(basename "$arg")/${flac#$arg}
if [[ ! -d ${outfile%/*} ]]; then
mkdir_vp "${outfile%/*}" || die "error: failed to create directory \`${outfile%/*}'"
fi
else
outfile=$DEST/${flac##*/}
fi
# a proper extension please...
outfile=${outfile%.flac}.mp3
# does the outfile exist?
if [[ -f $outfile ]] && (( ! FORCE )); then
warn "warning: file \`$outfile' already exists -- skipping"
continue
fi
# finally, do the conversion
convert "$flac" "$outfile" || warn "warning: failed to convert to mp3"
done
done