Для того чтобы с комфортом перекодировать музыку в формате
FLAC в MP3 вам понадобятся:* MP3-кодер LAME: http://lame.sourceforge.net/
* FLAC-кодер: http://flac.sourceforge.net/
* Скрипт flac2mp3.sh: http://entropyware.info/soft/flac2mp3.shОтличительные особенности скрипта flac2mp3.sh:
* Рекурсивная обработка нескольких альбомов сразу
* Создание ID3 тегов на основе мета-информации во FLAC-файлах
* Сохранение mp3-файлов в отдельной директорииИспользование:
flac2mp3.sh <input_dir> <output_dir> [lame_opts]
Пример:
flac2mp3.sh /tmp/my/flac/albums /tmp/my/mp3 "-b 320 -h"
Вот как могут выглядеть директории input_dir и output_dir после вызова скрипта:
tree /tmp/my/flac/albums
/tmp/my/flac/albums
`-- album1
|-- track1.flac
`-- track2.flac
1 directory, 2 filestree /tmp/my/mp3
/tmp/my/mp3
`-- albums
`-- album1
|-- track1.mp3
`-- track2.mp32 directories, 2 files
Все необходимые директории при этом создаются скриптом автоматически.
Текст скрипта:
#!/bin/bash
# flac2mp3.sh --- скрипт для конвертации FLAC файлов в MP3
# Александр Симаков, <xdr (тчк) box на Google Mail>
# http://alexander-simakov.blogspot.com/
## Какие программы где находятся
LAME=lame
FLAC=flac
METAFLAC=metaflac# Настройки LAME по-умолчанию
DEFAULT_LAME_OPTS="-b 256 -h"# Эта функция извлекает из FLAC-файла мета-информацию
# и формирует соответствующую последовательность
# опций для LAME.
function get_id3_opts()
{
flac_file="$1"$METAFLAC --export-tags-to - "$flac_file" | while read -d $'\n' tag; do
tag_name=$(echo "$tag" | awk -F= '{ print $1 }')
tag_value=$(echo "$tag" | awk -F= '{ print $2 }' | sed 's/"/\\"/g')case "$tag_name" in
TITLE)
echo -n "--tt \"$tag_value\" "
;;
ARTIST)
echo -n "--ta \"$tag_value\" "
;;
ALBUM)
echo -n "--tl \"$tag_value\" "
;;
GENRE)
echo -n "--tg \"$tag_value\" "
;;
DATE)
echo -n "--ty \"$tag_value\" "
;;
TRACKNUMBER)
echo -n "--tn \"$tag_value\" "
;;
esac
done
}# Эта функция формирует имя mp3-файла и создает
# необходимые директории.
function make_mp3_file_name()
{
input_dir=$1
output_dir=$2
flac_file=$3album_dir=$(basename "$input_dir")
mp3_file=${flac_file/%flac/mp3}
mp3_file=${mp3_file/#${input_dir}/${output_dir}/${album_dir}/}
mp3_dir=$(dirname "$mp3_file")
$(mkdir -p "$mp3_dir")echo "$mp3_file"
}# Эта функция рекурсивно конвертирует FLAC-файлы из
# директории input_dir в директорию output_dir.
# Директория output_dir создается автоматически.
function main()
{
input_dir=$1
output_dir=$2
lame_opts=$3if [[ -z "$input_dir" || -z "$output_dir" ]]; then
echo "Usage: $0 <input_dir> <output_dir> [lame_opts]"
echo "Example: $0 /tmp/my/flac/albums /tmp/my/mp3 \"-b 320 -h\""
exit 1
fiif [[ -z "$lame_opts" ]]; then
lame_opts=$DEFAULT_LAME_OPTS
fiOIFS=$IFS; IFS=$'\n'
# Рекурсивно обрабатываем все FLAC-файлы
for flac_file in $(find "$input_dir" -name "*.flac" | sort); do
flac_base=`basename "$flac_file"`
echo "Processing '$flac_base'..."id3_opts=$(get_id3_opts "$flac_file")
mp3_file=$(make_mp3_file_name "$input_dir" "$output_dir" "$flac_file")
cmd="$FLAC -sdc \"$flac_file\" | $LAME --quiet $lame_opts $id3_opts - \"$mp3_file\""eval $cmd
done
}main "$@"
URL: http://alexander-simakov.blogspot.com/2009/01/flac-mp3-id3.html
Обсуждается: https://www.opennet.ru/tips/info/1910.shtml
И где здесь собственно рекурсия?
Файлы обрабатываются в цикле, но никак не рекурсивно.
Рекурсия в вызове find. Если передать скрипту директорию в которой лежат альбомы музыки в формате flac, то скрипт обработает все эти альбомы независимо от того как глубоко они закопаны.
>Рекурсия в вызове find.А где в рекурсивном find -- _перекодирование_? Ну, Вы поняли...
http://ru.wikipedia.org/wiki/Рекурсия
Программа find - производит рекурсивный поиск в поддиректориях; программы flac & lame производят перекодирование. Таким образом, директория с альбомами кодируется рекурсивно, в смысле семантики команды find. Что тут непонятного?http://ru.wikipedia.org/wiki/Пуризм
РИКУРСИЯ МЛЯ!!!#!/bin/bash
function recoder(){
dir=`ls -p | grep "/"`
for i in $dir
do
pushd . > /dev/null 2>&1;
cd $i
if [ \"*.mp3\" ]
then
echo 'pwd'/*.mp3; # Тута можно перекодировать
fi
recoder; # рекурснём...
popd > /dev/null 2>&1;
done
}cd $1;
recoder;# EOF
Да, но тут не извлекаются теги из flac-файлов, нет
возможности указать отдельную директорию для mp3-файлов
и, собственно, нет самого перекодирования! Зачем нужен
этот скрипт? Обойти все mp3 файлы и вывести их имена?
К тому-же обходить flac-файлы а не mp3.ИМХО, _однострочный_ вариант с find-ом для этой цели
куда проще и понятнее.
А тут вообще ничего не извлекается, я показал как работает find и где рекурсия.
>я показал как работает
>где рекурсия.Ждём рекурсивного перекодирования. _Одного_ .flac-а. На bash-e. :-P
А как быть, если в имени исходного файла есть пробел? Например, в каталоге, содержащем
01 - The Great Marsh.flac
02 - Rhayader.flac
скрипт
for i in $(find . -name "*.flac" |sort); do echo $i; done
выводит
./01
-
The
Great
Marsh.flac
./02
-
Rhayader.flac
Решил эту проблему заменой пробела на '_' sed'ом, но это изврат, имхо. Может, кто подскажет более элегантное решение?
Обратите внимание на строкуOIFS=$IFS; IFS=$'\n'
Это означает что разделителем полей является символ перевода
на новую строку, а не пробел. Я сам наступал на эти "грабли"
и поэту в скрипте учел возможность имен файлов с пробелами.
Вот полезная ссылка по этой теме:
http://www.cyberciti.biz/tips/handling-filenames-with-spaces...
>for i in $(find . -name "*.flac" |sort); do echo $i; donefind . -name "*.flac" -print0 |sort -z |xargs -0 -n1
:-P
find ... | while read n; do ...; done
while read n; do ...; done <( find ... )
Спасибо автору. Большая экономия времени и удобство! Коментаторы срач устроили.
Сделайте лучше.
Если в mp3-файлах на выходе скрипта не появились тэги, то вот в этом месте:>case "$tag_name" in
> TITLE)
> echo -n "--tt \"$tag_value\" "
> ;;надо название тэгов или исправить на нижний регистр или в нижнем регистре прописать через "|", т.е. так:
case "$tag_name" in
TITLE|title )
echo -n "--tt \"$tag_value\" "
;;Судя по всему, с момента написания Александром Симаковым замечательно скрипта, который здесь обсуждается, произошли изменения в выводе команды metaflac.
За сам скрипт автору глубочайший респект!
Для тех, кто не силен в скриптинге, забыл добавить, что менять надо не только тэг TITLE но и все остальные до конца цикла case (т.е. до слова esec)
Огромное спасибо! Те, кому рекурсивность кажется не рекурсивной, пусть используют свою сверхдо''бчивую до''бчивость на своей несмышленной смышленности.