Скрипт для рекурсивного перекодирования lossless-файлов во FLAC
Материал из Linux Wiki
Перейти к навигацииПерейти к поиску
Скрипт, представленный ниже, предназначен для рекурсивной конвертации APE, ALAC, Wav и WavPack-файлов в формат FLAC внутри каталога, где он был запущен. При нахождении одного из указанных форматов и отсутствии соответствующих утилит для работы с ним, скрипт пропускает файл и выдает предупреждающее сообщение.
Для поддержки всех перечисленных форматов в системе должны быть установлены следующие утилиты:
- mac из пакета monkeys-audio для поддержки формата APE
- alac, который можно загрузить с http://crazney.net для поддержки формата Apple Lossless (файлы m4a)
- wvunpack из пакета wavpack для декодирования WavPack-файлов
- mp4info из пакета mpeg4ip-utils для работы с тегами в ALAC-файлах
- ffmpeg для работы с тегами в WavPack и APE
- и, естественно, утилиты для работы с FLAC-форматом.
Для использования просто запустить команду внутри нужного каталога.
Предупреждение: Для обработки не-FLAC-файлов, представляющих собой целый альбом в одном файле, лучше сразу воспользоваться этим скриптом.
#!/bin/bash
chkdec() {
test $(which "${1}") || {
echo -e "[\e[5;31mW\e[0;0m] Decoder $1 not found, skipping $3"
continue
}
test $(which "${2}") || {
echo -e "[\e[5;31mW\e[0;0m] Tag tool $2 not found, skipping $3"
continue
}
}
say_work() {
echo -ne "[\e[5;36mW\e[0;0m] Processing: $file"
}
say_complete() {
echo -e "\r[\e[0;32mV\e[0;0m] Decoding complete: $file"
}
say_failed() {
echo -e "\r[\e[5;31mF\e[0;0m] Decoding FAILED: $file"
}
say_exist() {
echo -e "[\e[0;33mE\e[0;0m] Already done: $file"
}
m4atags_convert() {
mp4info "${1}" | awk '
/^ Name:/{
gsub(/^ Name: /, "TITLE=", $0)
print
}
/^ Artist:/{
gsub(/^ Artist: /, "ARTIST=", $0)
print
}
/^ Year:/{
gsub(/^ Year: /, "DATE=", $0)
print
}
/^ Album:/{
gsub(/^ Album: /, "ALBUM=", $0)
print
}
/^ Genre:/{
gsub(/^ Genre: /, "GENRE=", $0)
print
}
/^ Track:/{
gsub(/^ Track: /, "TRACKNUMBER=", $0)
split($0, track)
print track[1], "\nTRACKTOTAL="track[3]
}
/^ Disk:/{
gsub(/^ Disk: /, "DISCNUMBER=", $0)
print $1
}
/^ Comment:/{
gsub(/^ Comment: /, "COMMENT=", $0)
print
}
/^ Writer:/{
gsub(/^ Writer: /, "COMPOSER=", $0)
print
}
/^ Album Artist:/{
gsub(/^ Album Artist: /, "PERFORMER=", $0)
print
}' | metaflac --import-tags-from=- "${2}"
}
apetags_convert() {
ffmpeg -i "${1}" 2>&1 | sed -n '/Metadata:/,/Duration:/p' |
awk 'BEGIN {
IGNORECASE=1
}
/^ +Year +:/{
print "YEAR="$3
}
/^ +Genre +:/{
gsub(/^ +Genre +: /, "GENRE=", $0)
print
}
/^ +Album +:/{
gsub(/^ +Album +: /, "ALBUM=", $0)
print
}
/^ +Comment +:/{
gsub(/^ +Comment +: /, "COMMENT=", $0)
print
}
/^ +Title +:/{
gsub(/^ +Title +: /, "TITLE=", $0)
print
}
/^ +Composer +:/{
gsub(/^ +Composer +: /, "COMPOSER=", $0)
print
}
/^ +Artist +:/{
gsub(/^ +Artist +: /, "ARTIST=", $0)
print
}
/^ +Part +:/{
gsub(/^ +Part +: /, "DISCNUMBER=", $0)
print
}' | metaflac --import-tags-from=- "${2}"
}
find . -type f ! -iname "*.flac" |
while read file
do
[ -e "${file%.*}.flac" ] && say_exist || {
ext="$(basename "${file}")"
ext="${ext##*.}"
case "${ext}" in
m4a)
chkdec alac mp4info "$file" && {
say_work
{
alac "${file}" | flac --best - --totally-silent -Vo "${file%.m4a}.flac" &&\
m4atags_convert "${file}" "${file%.m4a}.flac" && rm -f "${file}"
} && say_complete || say_failed
}
;;
wav)
say_work
{
flac --best "${file}" --totally-silent -Vo "${file%.wav}.flac" && rm -f "${file}"
} && say_complete || say_failed
;;
ape)
chkdec mac ffmpeg "$file" && {
say_work
{
mac "${file}" - -d 2>/dev/null | flac --best - --totally-silent -Vo "${file%.ape}.flac" &&\
apetags_convert "${file}" "${file%.ape}.flac" && rm -f "${file}"
} && say_complete || say_failed
}
;;
wv)
chkdec wvunpack ffmpeg "${file}" && {
say_work
{
wvunpack "${file}" -qo - | flac --best - --totally-silent -Vo "${file%.wv}.flac" &&\
apetags_convert "${file}" "${file%.wv}.flac" && rm -f "${file}"
} && say_complete || say_failed
}
;;
esac
}
done