dr_magnus 07.06.2010 01:32
Скрипты на bash — Перекодирование аудиокниг
Я уже рассуждал на тему аудиокниг.Кратко поясню для тех, кто пропустил - я не понимаю, зачем хранить аудиокниги в битрейте более 128. На слух ведь всё равно не различишь, а места занимает больше. Вот я и решил свою коллекцию перегнать в битрейт 96.
И заодно я решил проблему с переносом тегов (большое спасибо Iliander'у).
Кому интересно - под кат.
Я написал небольшой скрипт, который, если запустить его в папке с аудиокнигой, создает в ней директорию 96 и перекодирует туда найденные МР3-файлы с сохранением тегов.
Сам скрипт:
И немного пояснений:
mid3v2 (входит в пакет mutagen) умеет показывать МР3-теги в таком виде:
IDv2 tag info for b01_00_00.mp3:
TPE1=Сергей Лукьяненко
TALB=Ночной дозор
TPE1=Сергей Лукьяненко
TALB=Ночной дозор
grep'ом мы выдергиваем отсюда нужный нам тег, а sed'ом отрубаем ненужную часть.
Буду признателен, за любые дополнения. У меня не реализованы следующие вещи:
- Передача каталога как аргумента (никак не могу побороть проблемы с пробелами в именах);
- Удаление файлов после перекодирования (ну это не сложно);
- Переименование файлов согласно тегам (смотрю в сторону eyeD3)
UPD:
Немного подправил скрипт (спасибо за подсказки в коментариях), теперь умеет принимать имя каталога и не боится пробелов.
ну если бы речь шла именно о паре дестяков мегабайт, то можно было бы не заморачиваться. но даже пережатие 128 в 96 уже экономит раза в полтора-два места, а это пара сотен мегобайт. для меня это все еще актуально.
какой-то бредовый спор: автор поставил задачу и решил ее, не нравится - не пользуй, надо-не-надо это уж каждый сам для себя решит :)
А у меня на нетбуке 4 гига памяти постоянной. И SD-карточка на два гига. И тоскать с собой террабайтный внешний винт я не хочу. А послушать иногда чего-нибудь, сидя в кафешке с вайфаем за чашечкой кофе можно. Так что, автору таки респект.
Иногда, да. Заливаю, к примеру, цикл книг какой-нибудь целиком и пока не прослушаю, валяется. Ну и плюс, кроме аудиокниг у меня есть ещё много разных вещей, чтобы туда складывать.
а по моему очень даже. иногда нет возможности добраться до основного хранилища, а так - цикл всегда под рукой.
Вы серьёзно? Когда винты на терабайты стоят сущие копейки перегонять 128 в 96? :D
Но дело полезное вот в чем. Можно хранить музыку в lossless или mp3 с битрейтом 320, но для переносного плеера (который не понимает всякие .ape, .flac) перекодировать.
Но дело полезное вот в чем. Можно хранить музыку в lossless или mp3 с битрейтом 320, но для переносного плеера (который не понимает всякие .ape, .flac) перекодировать.
если все место под музыку уйдет на террабайтном винте, где же тогда порнуху хранить?!
Аж чаем подавился, когда свой ник в RSS увидал.
А скрипт, кстати, хороший, полезный. Помимо, собственно, аудиокниг (которые я слушаю весьма редко, читать больше нравится), помнится, пока не убил свой MP4-плеер, возился с перекодировкой аудио под него. На тот момент так и не решил, как можно сохранять теги — опыта недоставало.
А скрипт, кстати, хороший, полезный. Помимо, собственно, аудиокниг (которые я слушаю весьма редко, читать больше нравится), помнится, пока не убил свой MP4-плеер, возился с перекодировкой аудио под него. На тот момент так и не решил, как можно сохранять теги — опыта недоставало.
Музыку с компьютера перекидываю на плеер таким вот скриптом на питоне (lame_tag):
Копируются теги и даже альбомная картинка.
Запускаю в папке с нужной музыкой командой:
Думаю немного переделать и все ваши задачи решаться
#!/usr/bin/env python
import os
import eyeD3
import optparse
outdir = "/media/T10/"
parser = optparse.OptionParser()
(options, args) = parser.parse_args();
for f in args:
dname = os.path.dirname(f)
bname = os.path.basename(f)
if not os.path.exists(outdir+dname):
os.makedirs(outdir+dname)
print "Imput file = " , f
outF = outdir + dname + "/" + bname
print "Output file = ", outF
if os.path.isfile(f) and not os.path.isfile(outF):
if eyeD3.isMp3File(f):
tag = eyeD3.Tag()
tag.link(f)
tnum = tag.getTrackNum()
trackNum = tag.getTrackNum()<0>;
trackTotal = tag.getTrackNum()<1>;
artist = tag.getArtist()
album = tag.getAlbum()
title = tag.getTitle()
genre = tag.getGenre()
date = tag.getYear()
images = tag.getImages()
for img in images:
img.writeFile(outdir + dname, bname + ".jpg")
print "Tags =", trackNum, trackTotal, artist, album, title, genre, date, images
print "Start lame"
os.spawnv('P_WAIT','/usr/bin/lame',<'lame','-V5',f,outF>)
print "Tagging..."
tag2 = eyeD3.Tag()
tag2.link(outF,eyeD3.ID3_V2)
tag2.setVersion(eyeD3.ID3_V2_3)
tag2.do_tdtg=False
tag2.setTextEncoding(eyeD3.UTF_16_ENCODING)
tag2.setTrackNum((trackNum, trackTotal));
tag2.setTitle(title)
tag2.setArtist(artist)
tag2.setAlbum(album)
tag2.setGenre(genre)
tag2.setDate(date)
if os.path.exists(outdir+dname+"/"+bname+".jpg"):
tag2.addImage(3,outdir+dname+"/"+bname+".jpg", u"")
os.remove(outdir+dname+"/"+bname+".jpg")
tag2.update(eyeD3.ID3_V2_3)
print "OK"
Копируются теги и даже альбомная картинка.
Запускаю в папке с нужной музыкой командой:
find . -name "*.mp3" -exec lame_tag {} \;
Думаю немного переделать и все ваши задачи решаться
имхо, логичнее использовать -iname. Разве только всегда следить за регистром.
Буду признателен, за любые дополнения. У меня не реализованы следующие вещи:
- Передача каталога как аргумента (никак не могу побороть проблемы с пробелами в именах);
- Передача каталога как аргумента (никак не могу побороть проблемы с пробелами в именах);
используй экранирование или же заключай путь в кавычки
- Переименование файлов согласно тегам (смотрю в сторону eyeD3)
mv "$input_file" "$ARTIST - $TITLE.mp3"
mv "$input_file" "$ARTIST - $TITLE.mp3"
спасибо
а вот с пробелами никак не получается - find постоянно ругается на пробелы
эм…
if << -n "$1" >> ; then
WHERE="${1}"
else
WHERE="."
fi
mkdir "${WHERE}/96"
find "${WHERE}" -iname '*.mp3' | while read input_file;
do
TITLE=$(mid3v2 -l "$input_file" | grep TIT2 | sed s/^TIT2=//)
ARTIST=$(mid3v2 -l "$input_file" | grep TPE1 | sed s/^TPE1=//)
ALBUM=$(mid3v2 -l "$input_file" | grep TALB | sed s/^TALB=//)
lame -b 96 --cbr --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" "$input_file" "${WHERE}/96/$ARTIST - $TITLE.mp3";
done
Может и не одному, но я ничего такого тут не вижу, что можно было бы оборачивать в функцию и в этом был бы смысл. :)
не совсем - теперь уже косяк проявился в этой конструкции:
Can't init outfile '/media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/96//media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/00_00_04.mp3'
а использовать переименование выходного файла не стал, т.к. нету тега TITLE.
выкрутился следующим образом
а все остальное без изменений
lame -b 96 --cbr --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" "$input_file" "${WHERE}/96/$ARTIST - $TITLE.mp3";
Can't init outfile '/media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/96//media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/00_00_04.mp3'
а использовать переименование выходного файла не стал, т.к. нету тега TITLE.
выкрутился следующим образом
dir_name="${1}"
cd "${dir_name}"
а все остальное без изменений
Can't init outfile '/media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/96//media/sdc1/Music/Audio Books/Лукьяненко Сергей/Цикл "Дозоры"/02 - Дневной дозор/00_00_04.mp3'
гм… Так и думал, что там без косяков не обойдется, но т.к. тестил его по-быстрому на альбоме из своей дискографии с аккуратными тегами — результатом удовлетворился и оставил.
выкрутился следующим образом
Тогда вставь хотя бы проверку на наличие "$1", чтобы скрипт был немного более универсальным. А то ругаться в консоль будет.
А так, в принципе, решение хорошее, даже лучше моего — KISS в действии :-)
не знала, что в XXI веке сарказм променяют на кавычки. верните мне время назад!
Я дописал это так ( чтобы работала с кучей папок )
#!/bin/sh
dir_name="${1}"
cd "${dir_name}"
# необходимый битрейт
bit=64
mkdir $bit
find -iname '*.mp3' | while read input_file;
do
TITLE=$(mid3v2 -l "$input_file" | sed -n 's/^TIT2=//p')
ARTIST=$(mid3v2 -l "$input_file" | sed -n 's/^TPE1=//p')
ALBUM=$(mid3v2 -l "$input_file" | sed -n 's/^TALB=//p')
# куда будет сохранять пережатый файл
output_file="./$bit/$input_file"
#если папок много то создать подпапки . / - больше 1
if < `$input_file | grep -o "/" | wc -l` -lt 1 >
then
#длина исходного файла
if_len=${#input_file}
#длина имени файла
name=`readlink -e $input_file`
#выкидываем имя файла
fname=${name##*/}
#считаем его длину
name_len=${#fname}
#отбрасываем из пути первые два символа и длину имени файла
length_without_name=$if_len-$name_len-2
my_path=${input_file:1:length_without_name}
if < ! -d "./$bit$my_path" > ; then
#если нет такой папки то создаем ее
mkdir -p ./$bit$my_path
fi
fi
# echo $my_path >>1
lame -b $bit --cbr --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" "$input_file" "$output_file";
done
дружэ, а ты ничего не упустил?
ну и на всякий случай:
использование:
./audio_script.sh /папка/где/у_тебя/лежат/аудиокниги
в любом случае - спасибо.
ну и на всякий случай:
#!/bin/sh
dir_name="${1}"
cd "${dir_name}"
tmp_dir="$(mktemp -d -p "$dir_name")"
find -iname '*.mp3' | while read input_file; do
base_dir="$(dirname "$input_file")"
base_file="$(basename "$input_file")"
bitrate=$(mp3info -r m -p "%r\n" "$input_file")
if < "$bitrate" -gt 96 >; then
echo "$base_dir"
title=$(mid3v2 -l "$input_file" | sed -n 's/^TIT2=//p')
artist=$(mid3v2 -l "$input_file" | sed -n 's/^TPE1=//p')
album=$(mid3v2 -l "$input_file" | sed -n 's/^TALB=//p')
lame -b 96 --cbr -h --tt "$title" --ta "$artist" --tl "$album" "$input_file" "$tmp_dir/$base_file"
rm "$input_file"
mv "$tmp_dir/$base_file" "$base_dir"
fi
done
rm -r "$tmp_dir"
использование:
./audio_script.sh /папка/где/у_тебя/лежат/аудиокниги
в любом случае - спасибо.
и еще - а что ты там намутил с длиной файлов?
если честно, то я не понял :-(
если честно, то я не понял :-(
длину я считал для того , чтобы из относительного пути выкинуть имя файла + начальные "./" И потом создать в /папка/где/у_тебя/лежат/аудиокниги -
/папка/где/у_тебя/лежат/аудиокниги/$битрейт и соответсвенно создать там всю структуру директорий самих аудиокниг , в которые будут размещены пожатые нами файлы ...
Вторую тему не видел , поэтому правил то , что на глаза попалось .
А там кодятся множество аудиокниг ?
/папка/где/у_тебя/лежат/аудиокниги/$битрейт и соответсвенно создать там всю структуру директорий самих аудиокниг , в которые будут размещены пожатые нами файлы ...
Вторую тему не видел , поэтому правил то , что на глаза попалось .
А там кодятся множество аудиокниг ?
кодятся.
там просто натравливаешь скрипт на папку и он всё приводит к одному битрейту
там просто натравливаешь скрипт на папку и он всё приводит к одному битрейту
Во времена терабайтных ЖД пора уже перестать задумываться о освобождении пары десятков мегабайт.
Если речь идёт про плеер, то не все ли равно сколько там одновременно книг находится?! Ты же их как музыку шафлом не слушаешь. Прочитал\прослушал с десяток - заменил на следующие.
p.s. перенес в скрипты и добавил теги