Mucias: a music collecting/tagging daemon

Door stereohead op woensdag 14 oktober 2009 19:22 - Reacties (15)
Categorieën: Muziek, Python, Views: 3.799

Intro

Als sinds jaar en dag ben ik op zoek naar software waarmee ik mijn muziek collectie kan beheren. Onder beheren versta ik twee dingen:
  • De juiste tags koppelen aan de bestanden.
  • Een makkelijke manier om door de collectie te browsen.
Nu zijn er al veel programma's geschreven die deze twee dingen (gedeeltelijk) implementeren, maar geen voldoen aan mijn eisen. Het moet namelijk ook goed werken met grote collecties, het moet automatisch nieuwe bestanden toevoegen, het moet als een daemon draaien op mijn server (zonder GUI), het moet werken op linux, en als het kan open-source zijn.

Aangezien er praktisch geen programma's zijn die aan al deze eisen voldoen, was er nog maar één mogelijkheid: Zelf maken, maar dan wel goed...

Het idee

Allereerst ben ik begonnen met het opstellen van de requirements.
Mijn programma doet dus al zijn werk op de achtergrond, zonder grafische schil. Dat geeft namelijk de mogelijkheid om op (bijvoorbeeld) een fileserver te draaien. Maar natuurlijk moet het wel te besturen zijn, daarom wordt er gebruik gemaakt van XMLRPC daarmee kan ik via sockets (dus in principe ook via het netwerk) het programma stoppen, of andere acties uitvoeren.

Het programma moet automatisch nieuwe bestanden opsporen en verwerken. Nu kan ik periodiek alle bestanden in een map bijlangsgaan en kijken of er nieuwe bestanden zijn bijgekomen. Dit heeft enkel twee nadelen: het doorlopen van veel bestanden kost veel cpu-kracht, en het kost veel tijd. Dat zou dus betekenen dat zodra ik een bestand toevoeg, deze pas een paar minuten later in de database staat. Dat wou ik niet, dus heb ik op het internet gezocht naar een alternatief. Daardoor kwam ik uit op inotify. Inotify is een 'ding´ in de linux kernel wat je kan gebruiken om mappen te monitoren. Zodra er wijzigingen zijn krijg je daar een bericht van in je programma. Klinkt goed toch?

Omdat ook grote collecties vlotjes moeten werken worden alle gegevens opgeslagen in een MySQL database, en niet in (bijvoorbeeld) XML bestanden. In de database worden in eerste instantie alleen de artiest, album, tracknummer, en titel van een track opgeslagen. In de toekomst kan dit nog uitgebreid worden met allerlij overige informatie zoals lyrics en gegevens over de artiesten.

Het analyzeren van de bestanden moet zo goed mogelijk gebeuren, dat wil zeggen: de gevonden tags moeten kloppen. Hiervoor gebruik ik in het begin nog ID3 tags, maar omdat deze lang niet altijd betrouwbaar zijn moet er gezorgd worden voor een flexibel systeem, waarmee dus makkelijk nieuwe (betere) methoden om de bestanden te analyzeren toe te voegen zijn, hierover later meer.

Tenslotte wil ik dus een makkelijke manier manier om door de collectie te browsen. Ha, sukkel hoor ik sommigen al denken: veel succes zonder GUI. Maar gelukkig is ook daarop iets te verzinnen, namelijk het browsen door de collectie overlaten aan anderen :), de bedoeling is om de collectie beschikbaar te stellen via het Digital Audio Access Protocol a.k.a DAAP. Aangezien er al veel mediaplayers zijn die dit protocol ondersteunen leek mij dit een geschikte keuze.

Het idee is geboren, volgende stap is dus de uitvoering.

Mucias

Wat is een programma zonder naam? Precies ik moet dus een naam verzinnen, en dat is makkelijker dan gedacht, een naam moet ergens voor staan, en moet goed klinken. Na enig puzzelen met afkortingen kwam ik op mucias, wat staat voor MUsic Collection Indexer And Server.
Vervolgens moeten we natuurlijk een programmeertaal keizen, ik heb ervaring met PHP, Java en Python, aangezien PHP hoofdzakelijk alleen geschikt is voor websites en Java gewoon kut is (daar nu geen discussie over), blijft Python over. Voordeel is dat er voor Python veel libraries beschikbaar zijn die ik goed kan gebruiken. Voor het de XMLRPC service kan ik namelijk de SimpleXMLRPCServer module, en xmlrpclib gebruiken. Ook voor inotify is een python module: pyinotify. Tenslotte is er nog mutagen, een erg uitgebreide library waarmee metadata (ID3 tags dus) uit bestanden gelezen kan worden.
Opzet
Mucias is verdeeld in twee gedeelten, een gedeelte dat de bestanden opspoort en indexeert, genaamd 'Indexer' en een gedeelte dat de collectie serveert via DAAP genaamd 'Server'. Deze twee delen werken geheel onafhankelijk van elkaar, waardoor er de mogelijheid bestaat om bijvoorbeeld de server te stoppen, maar het indexeren van bestanden gewoon doorgaat.

De indexer draat verschillende threads waarvan één m.b.v. Pyinotify op nieuwe bestanden controleerd, één als XMLRPC server functioneerd, een aantal 'workers' die bestanden analyzeren, en één 'ProcessManager' die de workers aanstuurt. Dit deel van mucias is klaar.

De opzet van de server heb ik nog niet ontworpen, en wordt waarschijnlijk nog een flinke klus. Ik ga zowiezo eerst kijken of er python modules beschikbaar zijn waarmee DAAP makkelijk te implementeren is. Anders wordt het een kwestie van de documentatie uitspitten.
Resultaat
Zoals verteld, draait de indexer onafhankelijk van de server. Hierdoor heb ik de indexer al aardig kunnen testen en de resultaten zijn bevredigend. De volgende stap is het maken van de server, en daarna een betere methode ontwikkelen om bestanden te analyzeren, hiervoor ga ik waarschijnlijk gebruik maken van 'fingerprints' en daarmee de juiste tags ophalen van musicbrainz. Dit is een erg betrouwbare methode, omdat er echt naar de muziek zelf wordt gekeken, en niet alleen naar de tags.

En nu?

Waarom dit verhaal? Omdat ik graag feedback krijg. Wat vinden jullie van het idee? Is de opzet goed gekozen. Is het slim op DAAP te gebruiken? Is een programma als dit nuttig? Wat zouden jullie (anders) doen?

Tot slot:

Open-source is de toekomst. Daarom heb ik op launchpad een project aangemaakt met een bazaar cvs systeem. De code is vrij beschikbaar onder GPLv3. Ik nodig jullie uit om de source te downloaden en het uit te proberen.

Versie 0.1 is hier te downloaden: mucias-0.1.tar.gz
Code is hier te bezichtigen: klik
Om de source te downloaden via bazaar:
bzr branch lp:mucias


Om de indexer te starten doe je:
mucias-indexer.py -c mucias.conf start

Volgende: RE: Klereherrie 03-'10 RE: Klereherrie
Volgende: Het nummer waar ik kippenvel bij krijg 09-'09 Het nummer waar ik kippenvel bij krijg

Reacties


Door Tweakers user SpaceK33z, woensdag 14 oktober 2009 20:00

Leuk idee :).
Maar door je collectie browsen, wat bedoel je daar precies mee? Want dit kan toch ook gewoon met Banshee of elke andere mediaspeler?

Het gene wat ik nog echt mis is een fatsoenlijk programma die controleert of de gegevens van een nummer kloppen (artiest, album enz.) en dit opzoekt via bijvoorbeeld Last.fm.

Door Tweakers user X-DraGoN, woensdag 14 oktober 2009 22:02

xdragon@mythtv:~/mucias-0.1$ python mucias-indexer.py -c mucias.conf start
Traceback (most recent call last):
File "mucias-indexer.py", line 192, in <module>
main()
File "mucias-indexer.py", line 175, in main
start_mucias(options);
File "mucias-indexer.py", line 70, in start_mucias
import mucias.Controller
File "/home/xdragon/mucias-0.1/mucias/Controller.py", line 9, in <module>
import Watcher
File "/home/xdragon/mucias-0.1/mucias/Watcher.py", line 7, in <module>
import pyinotify
ImportError: No module named pyinotify

Dat krijg ik.... als ik je programmaatje probeer uit te voeren
Ik vind het ten andere een SUPER idee!

Door Tweakers user stereohead, woensdag 14 oktober 2009 23:07

ImportError: No module named pyinotify
Waarschijnlijk is pyinotify niet geinstalleerd, zoek in je packet manager naar het pakket 'python-pyinotify' en installeer die eens.
Maar door je collectie browsen, wat bedoel je daar precies mee? Want dit kan toch ook gewoon met Banshee of elke andere mediaspeler?
De meeste mediaspelers doen dat wel ja, maar alleen voor een lokale collectie. Omdat mijn collectie op mijn fileserver staat, en ik die van verschillende pc's en eigenlijk ook vanaf het internet wil benaderen wil ik dat via DAAP doen.
Het gene wat ik nog echt mis is een fatsoenlijk programma die controleert of de gegevens van een nummer kloppen (artiest, album enz.) en dit opzoekt via bijvoorbeeld Last.fm.
Het nadeel van ID3 is dat de gegevens niet echt betrouwbaar zijn, en vaak vervuild met vreemde tekens.

De goede oplossing daarvoor is het gebruiken van fingerprints. hierbij wordt de audio van een bestand via een bepaald algoritme geanalyseerd, en de fingerprint die dat oplevert kan worden gekoppeld aan musicbrainz (een grote online database met erg accurate en uitgebreide informatie over tracks/albums/artiesten)

[Reactie gewijzigd op woensdag 14 oktober 2009 23:19]


Door Tweakers user X-DraGoN, donderdag 15 oktober 2009 08:47

Setting up python-pyinotify (0.7.1-1) ...

xdragon@mythtv:~/mucias-0.1$ python mucias-indexer.py -c mucias.conf start
Configuration Error: Missing section 'database'
xdragon@mythtv:~/mucias-0.1$

Enig idee?

Door Tweakers user Jogai, donderdag 15 oktober 2009 09:08

Mooi idee, en zo ver ik kan zien is de opzet vrij logisch.

Wat ik altijd een nadeel vind van dit soort libraries is het volgende:
Van 1 band heb ik meerdere cd's. De cd's hebben dan weer nummers gemeen. Nu wil ik het fysieke bestand maar 1 keer op de schijf hebben, maar in de library wil ik het nummer bij beide cd's zien.
Als je dat in kan bouwen, wordt ik een gebruiker.

Door Tweakers user stereohead, donderdag 15 oktober 2009 10:46

xdragon@mythtv:~/mucias-0.1$ python mucias-indexer.py -c mucias.conf start
Configuration Error: Missing section 'database'
xdragon@mythtv:~/mucias-0.1$
Controleer even of je de mucias.conf wel in de map staat, of anders het proberen door het absolute pad van mucias.conf mee te geven.
Wat ik altijd een nadeel vind van dit soort libraries is het volgende:
Van 1 band heb ik meerdere cd's. De cd's hebben dan weer nummers gemeen. Nu wil ik het fysieke bestand maar 1 keer op de schijf hebben, maar in de library wil ik het nummer bij beide cd's zien.
Is een CD bij jouw gelijk aan een album?

[Reactie gewijzigd op donderdag 15 oktober 2009 10:47]


Door Tweakers user X-DraGoN, donderdag 15 oktober 2009 12:35

Ik heb nergens een mucias.conf gevonden. Ik heb ze blijkbaar ook niet gevonden in de download, moet ik die ergens vinden/aanmaken?
Ik heb op http://bazaar.launchpad.net/~stereohead/mucias/trunk/files een mucias.conf gevonden, maar die geeft ook errors als ik die run.

xdragon@mythtv:~/mucias-0.1$ python mucias-indexer.py -c mucias.conf start
Traceback (most recent call last):
File "mucias-indexer.py", line 192, in <module>
main()
File "mucias-indexer.py", line 175, in main
start_mucias(options);
File "mucias-indexer.py", line 73, in start_mucias
controller.load_config(options.configfile)
File "/home/xdragon/mucias-0.1/mucias/Controller.py", line 61, in load_config
config.read(file)
File "/usr/lib/python2.5/ConfigParser.py", line 267, in read
self._read(fp, filename)
File "/usr/lib/python2.5/ConfigParser.py", line 462, in _read
raise MissingSectionHeaderError(fpname, lineno, line)
ConfigParser.MissingSectionHeaderError: File contains no section headers.
file: mucias.conf, line: 1
'<?xml version="1.0"?>\n'

Moet ik ook ergens een soort setup vinden waarin ik aangeef welke dirs hij moet indexeren?

[Reactie gewijzigd op donderdag 15 oktober 2009 12:55]


Door Tweakers user stereohead, donderdag 15 oktober 2009 14:04

Ik zie net dat ik mucias.conf niet in de tar.gz heb gestopt 8)7, ik heb nu een nieuwe online gezet, de url blijft hetzelfde.

In het mucias.conf bestand kun je instellen welke mappen geindexeerd moeten worden, onder het kopje [watcher] bij directories.

In dat bestand moet je ook aangeven in welke Mysql database alles opgeslagen moet worden. De structuur van de database kan aangemaakt worden door de volgende SQL uit te voeren:

Je moet wel eerst zelf een database aanmaken.


SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
-- phpMyAdmin SQL Dump
-- version 3.1.2
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Oct 15, 2009 at 02:04 PM
-- Server version: 5.0.51
-- PHP Version: 5.2.6-1+lenny3

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Database: `mucias2`
--

-- --------------------------------------------------------

--
-- Table structure for table `album`
--

CREATE TABLE IF NOT EXISTS `album` (
  `albumid` int(11) NOT NULL auto_increment,
  `name` varchar(200) character set latin1 NOT NULL,
  PRIMARY KEY  (`albumid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=259 ;

-- --------------------------------------------------------

--
-- Table structure for table `artist`
--

CREATE TABLE IF NOT EXISTS `artist` (
  `artistid` int(11) NOT NULL auto_increment,
  `name` varchar(200) character set latin1 NOT NULL,
  PRIMARY KEY  (`artistid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=358 ;

-- --------------------------------------------------------

--
-- Table structure for table `file`
--

CREATE TABLE IF NOT EXISTS `file` (
  `fileid` int(11) NOT NULL auto_increment,
  `filename` varchar(300) character set utf8 collate utf8_unicode_ci NOT NULL,
  `length` int(11) default NULL,
  `trackid` int(11) default NULL,
  `added_at` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `method` varchar(25) NOT NULL,
  `status` varchar(25) NOT NULL,
  PRIMARY KEY  (`fileid`),
  UNIQUE KEY `filename` (`filename`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5499 ;

-- --------------------------------------------------------

--
-- Table structure for table `track`
--

CREATE TABLE IF NOT EXISTS `track` (
  `trackid` int(11) NOT NULL auto_increment,
  `artistid` int(11) NOT NULL default '0',
  `albumid` int(11) NOT NULL default '0',
  `tracknr` int(11) default NULL,
  `title` varchar(200) character set latin1 NOT NULL,
  PRIMARY KEY  (`trackid`)
) ENGINE=MyISAM  DEFAULT CHARSET=binary AUTO_INCREMENT=2680 ;

[Reactie gewijzigd op donderdag 15 oktober 2009 14:06]


Door Tweakers user Orian, donderdag 15 oktober 2009 23:06

Ziet er mooi uit. De technische details heb ik niet doorgekeken, maar het idee komt mij wel mooi over.

Enkele opmerkingspunten:

- Wat is er mis met ID3tags? Ik vind ze persoonlijk erg handig, omdat (vrijwel) alle programma's ze snappen/herkennen, en ook veel mp3spelers dit doen. Daardoor heb je altijd de gegevens, in tegenstelling tot allerlei obscure methoden waarbij slechts een programma ze snapt, en je de rest van je leven daaraan vast zit (bij wijze van spreken).

- Je zegt (in een van je reacties) dat je graag wilt dat ook over het netwerk muziek gestreamt moet kunnen worden. Ik gebruik in ubuntu atm Banshee, geen idee of die dat kan, maar ik weet dat windows media player het in ieder geval wel kan. Gewoon een kwestie van de map op een andere pc aanvinken als "doorzoeken". Wellicht een optie om even te kijken hoe dat werkt?

Succes ermee, ik houd het in de gaten (is er wellicht een optie me te abboneren op je blogs? Anders vind ik ze nooit meer terug ;) )

Door Tweakers user stereohead, vrijdag 16 oktober 2009 11:08

Opzich is er niets mis met ID3, maar deze tags zijn niet 100% betrouwbaar, regelmatig komt het voor dat er tags missen, ook staan er vaak overbodige tekens in (-_./\ e.d.).
Het programma past de tags verder niet aan, de tags worden alleen opgeslagen in de database.

Dat streamen wil ik gaan doen via het DAAP protocol, dat protocol werdt in eerste instantie gebruikt door iTunes om muziek te delen over het netwerk. Tegenwoordig komen er steeds meer plugins beschikbaar voor andere mediaplayers, onder andere rhythmbox en banshee ondersteunen deze al.

De bedoeling is dat het server gedeelte van mucias, ook op een flexibele manier opgebouwd wordt, waardoor het dus mogelijk zou moeten zijn om verschillende soorten servers tegelijkertijd te draaien.

Oh, over dat abboneren, er is een RSS feed beschikbaar Stereohead's Weblog

[Reactie gewijzigd op vrijdag 16 oktober 2009 11:10]


Door Tweakers user X-DraGoN, vrijdag 16 oktober 2009 15:40

Mysql DB created
user + paswd created
conf file aangepast
Proberen te laten lopen als mijn eigen user en als root, geeft dezelfde fout

xdragon@mythtv:~/mucias-0.1$ sudo python mucias-indexer.py -c mucias.conf start
Unable to open log file [opgelost]
Unable to load processor module 'mucias.processors.proc_id3', method: 'id3'
xdragon@mythtv:~/mucias-0.1$

Volgend idee?

[Reactie gewijzigd op vrijdag 16 oktober 2009 15:46]


Door Tweakers user stereohead, vrijdag 16 oktober 2009 18:18

Dat is wel weird, run je um direct na het uitpakken van de .tar, of heb je um eerst geinstalleerd?

Welke versie van Python draai je? Ik heb getest op 2.5 en 2.6

Door Tweakers user disturbedsaint, zondag 18 oktober 2009 10:22

Wat denk je van DLNA/UPnP AV in plaats van DAAP?
http://en.wikipedia.org/wiki/UPnP_AV_MediaServers

Was er geen UPnP AV mediaserver die aan je eisen voldeed?

Er is iig 1 Python framework voor DLNA
http://coherence.beebits.net/


En MusicBrainz ipv ID3 tags is misschien een betere oplossing.
Alleen moet je dan bepalen hoe je gaat handelen als musicbrainz de file niet kan identificeren (user-input nodig?)

http://wiki.musicbrainz.org/PythonMusicBrainz2

Door Tweakers user X-DraGoN, zondag 18 oktober 2009 17:03

xdragon@mythtv:~/mucias-0.1$ python -V
Python 2.5.2

Ik run hem direct na het uitpakken, moet je nog iets installeren dan?
[Misschien is een kleine installatie handleiding geen slecht idee?]

Door Tweakers user stereohead, maandag 19 oktober 2009 08:22

Er zit een setup.py bij, waarmee je um kunt instaleren. Maar dit zou in principe niet nodig zijn.

Instaleren gaat als volgt:
python setup.py build
sudo python setup.py install


Dat zorgt er ook voor dat je mucias-indexer.py gewoon kunt aanroepen, zonder dat je perse in de mucias directory moet zitte.

Wellicht het proberen waard, maar het zou niet nodig moeten zijn.

Reageren is niet meer mogelijk