Скрипт для рекурсивного перекодирования 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