GNU/Linux → Впорядкування музичної бібліотеки з linux

iriver E150

В зв’язку з обставинами, нещодавно став власником плеєра iriver E150. Після покупки постало завдання перекодувати всі теги так, щоб вони читались плеєром і заповнити тег обкладинка альбому (красиво виглядає з нею). Що з того вийшло — описано далі.

Уся історія доволі довга, але я її максимально скорочу.

Отож, для перекодування тегів використав перевірений часом EasyTAG. Програма доволі зручна, має пакетну обробку і широкі можливості. Експериментально встановив, що плеєр чудово працює з тегеми в форматі id3v2.3, текст кодується UTF-16 LE. Спершу заповнив відсутні теги з імені файлу, потім перейменував файли згідно тегів (трохи багато нудної, ручної роботи).

Завантаживши музику в E150 — був розчарований, частина композиції з кириличними тегами відображалась китайськими ієрогліфами. Програми на комп’ютері (EasyTag, Totem, Banshe і ін.) вперто показували, що все гаразд. Не розібравшись з проблемою наскоком, відклав її на потім, взявшись за обкладинки альбомів.

Першим ділом увімкнув Україну логіку. На комп’ютері слухаю музику через Banshee, а він автоматично завантажує обкладинки і показує їх в процесі програвання треків. Натрапив на інформацію, що плеєр вміє оновлювати теги файлів.. довго і вперто намагався заставити його зробити це, але марно.

Що ж, якщо гора не іде до Магомета.. Banshee кешує завантажені картинки, гугл підказав куди: ~/.cache/media-art/. Тут я знайшов багато файлів, імена яких були приблизно отакі: album-aaec54dc25571917373ae0131b85a883.jpg.

З картинки зрозуміло, що це Scorpions, альбом Humanity – Hour I, після «album-» іде md5 хеш певного рядка. Спроби підібрати хеш md5(‘Scorpions Humanity – Hour I’), md5(‘Scorpions – Humanity – Hour I’) не дали результату, знову гугл =)

* For album covers, the hashed string is in this format: ‘\t’.
If we used a space, for the string “foo bar baz” we wouldn’t be able to tell whether it’s album “bar baz” by “foo” or album “baz” by “foo bar”.

* Strings are normalised to NFKD before hashing.

Те що треба, перевірив, все сходиться. Далі, я уже хотів братися до написання безпосередньо скріпта, але подумав, що поточний варіант не надто зручний. Нові треки слід буде спочатку закидати в Banshee, прослуховувати їх (лише тоді завантажиться обкладинка), а потім запускати свій скріпт.

Було прийняте рішення, самостійно завантажувати обкладинки для альбомів, допоможе нам в цьому Last.fm, який надає API для роботи зі своєю базою. Для початку вартує зареєструватися й отримати API Key, потім курити мани читати документацію.

Сам скріпт, писав на python. На жаль, я не надто добре знаю дану мову, хоч уже й не раз її використовував (навіть запрограмив Simple Images Converter, яким користуюся й по сьогодні). Тому щоразу приходилось гуглити, і загалом код мені не подобається, але працює.

Алгоритм:

  1. Зчитуємо теги з файлу.
  2. На їх основі (Artist + Title) генеруємо запит на Last.fm.
  3. Отримуємо відповідь в XML, та опрацьовуємо її.
  4. Якщо опція дозволена, перезаписуємо теги новими (Artist, Album, Title, trackNum).
  5. Якщо знайдена обкладинка, завантажуємо і встановлюємо.

Запит робимо через urllib2.urlopen, рядок вигладяє так:

http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key="+ \
API_Key+"&autocorrect=1&artist="+urllib.quote(trackArtist)+"&track="+ urllib.quote(trackTitle)

API_Key — код, який нам видав Last.fm
trackArtist і trackTitle — відповідні id3 теги
autocorrect=1 — дуже хороша опція, вона дозволяє сервісу спробувати розпізнати запит з помилками. Наприклад, у мене була композиція з тегами Artist: Massive Attack, Title: Tear Drop. Без autocorrect=1 сервіс видавав, що композиція не знайдена, ібо правильна назва Teardrop. У відповіді повертаються уже правильні теги, і їх можна записати у наш файл.

Через незнання, дуже багато часу потратив на парсинг XML відповіді, нервувався, мало не матюкав пітона 🙂 поки не дізнався про xpath (для роботи з XML використовував модуль lxml), з ним все зробив швидко. Кусок коду:

res = urlopen(url)
tree = etree.parse(res)
lfm = tree.xpath('/lfm')
status = str(lfm[0].attrib["status"])
title = tree.xpath('/lfm/track/name/text()')
trackTitle = str(title[0].encode('utf-8'))

Ще більше часу боровся з кодуваннями. Вартує почитати щось толкове і зрозуміти логіку того всього, ібо зараз воно працює на основі експериментів, а не знань.

Робота з тегами велась через модуль eyeD3, приклади можна глянути в архіві, що в кінці нотатки (слід дивитися файл tags.py).

Прогнавши всю не сортовану музику через скріпт, отримав 121 нову обкладинку (загалом 355 треків, частина з них уже мала обкладинки й не опрацьовувалася), скільки виправлених тегів — не відомо =)

Повертаючись до наших баранів, крякозяби в кирилиці теж вдалося побороти. Для початку задав питання на хабрі, але хабралюди в вихідні не надто активні, тому (а може й зовсім не тому) отримав не багато підказок. Далі довго сидів і порівнював два одинакові треки, один з проблемними тегами, а в іншому теги видалив і заповнив такими ж, але з нуля. Дійшов до HEX редактора.., але відповідь знайшов не там, запустив eyeD3 з опцією –debug і помітив, що у всіх проблемних файлах є рядок De-unsynching xx bytes at once (<= 2.3 tag). Все інше було уже ділом техніки.

Поточні проблеми:
– малий період тестування (як наслідок, можуть бути глюки)
– «поганий» код
– обкладинки в png займають багато місця (400-500Кб), вартувало б переконвертовувати

Завантаження обкладинок та оновлення тегів з Last.fm
tar.gz track-cover-art.tar.gz

Перезапис проблемних кириличних тегів (увага, зберігаються лише теги: Artist, Album, Title, Year, Genre, trackNumber)
tar.gz tags.tar.gz

18.04.2011 11:10 Автор: Strange_V Хіти: 1588

Коментарів 2

Напишіть відгук