La reconnaissance musicale en Python

Posté le 2 septembre 2016 dans Développement

Vaste sujet que nous attaquons aujourd’hui qu’est la reconnaissance musicale, et plus particulièrement à l’aide de Python. Parce que ça déchire la race de sa maman, Python.

J’avais twitté il y a quelques temps à ce propos : la raison était que je développais un service de reconnaissance musicale 100% web-based, sans rien à installer à part un navigateur web moderne - mais une connexion internet est nécessaire tout de même.

Ce service est maintenant accessible publiquement : ça s’appelle WAR (Web Audio Recognizer), vous pouvez lire l’article de lancement pour plus d’infos.

J’écris cet article comme une sorte de retour d’expérience avec un tour d’horizon des solutions disponibles.

Logo de WAR

Afin de créer WAR, j’ai évidemment dû faire appel à des services tiers afin d’effectuer ce qui s’appelle de l’ACR audio (Automatic Content Recognition), car je n’allais quand même pas développer mon propre algo de reconnaissance musicale (on est pas à la NASA ici 😄). Et même si je réussissais à en développer un, encore faut-il populariser une base de données de référence : c’est à dire analyser tout pleins de musiques et les associer aux métadonnées qui vont bien (titre, artiste, etc) afin de pouvoir comparer les échantillons musicaux à quelque chose.

Bref, mon but était d’intégrer un maximum de ces services afin d’obtenir les résultats en provenance de plusieurs sources, histoire d’éviter les erreurs de reconnaissance. Je vais maintenant faire le point sur les différentes solutions qui existent d’après mes recherches.

Gracenote MusicID

Cette boîte basée en Californie, fondée en 1998 (respect), rachetée par Sony 10 ans plus tard, offrent un SDK (GNSDK) codé en C avec des wrappers C++, Java, C#, Java Android, Objective C et Python. Il semble être accessible par n’importe quel développeur. Enfin, sauf les développeurs Python car bien que le wrapper Python soit mentionné dans la doc, ce n’est qu’un sous-menu sans rien d’écrit derrière. J’ai essayé de faire un wrapper Python moi-même avec ctypes, échec. Des autres ont fait des bidouilles énormissimes pour arriver à en tirer quelque chose mais je refuse de passer par là.

Les plus :

  • Ont de la bouteille (+15 ans d’expérience et de données accumulées) ;
  • Sony (y’a des thunes derrière, donc longévité et moyens) ;
  • Accessible par n’importe quel développeur (comme vous et moi) ;
  • Community plan gratuit dispo.

Les moins :

  • Je n’ai jamais lu une documentation aussi à chier ;
  • Le fonctionnement de leur système est incroyablement compliqué (du moins, tant qu’un wrapper Python officiel n’est pas dispo ; je pleins également les développeurs C / C++) ;
  • (Quasi) aucune communauté. S’il y en a une (j’ai vu qu’il y a un forum officiel), elle est en état de mort cérébrale ;
  • Aucun tuto nulle part. Juste quelques questions de paumés sur Stackoverflow.

Appréciation finale : impossible à utiliser (du moins en Python). Frustration extrême.

AudibleMagic

Fondée en 1999 (respect aussi) et basée en Californie et à Londres, elle fait également partie des vieux de la vieille en matière d’ACR (même si elle ne fait pas que ça). Leur SDK est codé en C.

Les plus :

  • Ont de la bouteille également ;
  • Et du pognon (plus de 30 brevets déposés partout).

Les moins :

  • Leur site pour les développeurs est super mal branlé ;
  • Aucun wrapper Python (même pas une seule mention) ;
  • Pas de “community plan” (et les tarifs sont chers, ça commence à $1000 par mois). Donc clairement pas pour vous et moi.

Appréciation finale : impossible à utiliser tout court. Fuck.

Mufin AudioID

Fondée en 2005 à Berlin. A part le bla-bla de marketeux sur leur site, il n’y a absolument aucune infos. Rien d’accessible publiquement.

Appréciation finale : impossible à utiliser tout court.

Doreso

Une boîte chinoise fondée en 2012, elle est spécialisée dans la technologie ACR. Elle a apparemment coulé car seul leur site principal est encore accessible (leur site pour les développeurs a, semblerait-il, été stoppé net en 2015).

Extrêmement dommage car d’après Archive.org, on apprends que cela semblait être très intéressant. Ils ont même un package Python officiel qui traîne encore sur Github. RIP.

Appréciation finale : impossible à utiliser tout court. Fuuuuuuuuu

Enswers ACR Dev Kit

Fondée en je ne sais quelle année, et basée en Corée du Sud, ils se vantent d’être les meilleurs dans le domaine de l’ACR. Sauf que - comme Mufin cité plus plus haut : à part le bla-bla de marketeux sur leur site, il n’y a absolument aucune infos. Rien d’accessible publiquement.

Appréciation finale : impossible à utiliser tout court.

AcoustID.org

Solution accessible par tout le monde pour des projets non-commerciaux, utilisée par des projets connus dont VLC ou MusicBrainz. Ils ont une base de données de 30 millions de titres (ou juste d’empreintes audio, je sais pas trop. Les stats sont ici si vous aimez les chiffres). Pour les pros, il y a aussi AcoustID.biz. Leur SDK est codé en C, et est ce qu’il se fait de plus simple de tout ce que j’ai vu.

Les plus :

Vous l’aurez compris, AcoustID c’est de la bombe. Mais. Mais…

Les moins :

  • Ne permet de reconnaître que des fichiers musicaux entiers (donc pas d’extraits, et encore moins des enregistrements via micro).

Appréciation finale : facilité d’utilisation accrue, mais n’entre pas dans mes critères. ARGH. Exemple :

import acoustid

for score, recording_id, title, artist in acoustid.match('<la clé API>', 'whololo.wav'):
    print('{:40} {}'.format(title, artist))

ACRCloud

Société basée à Beijin, c’est la seule que je puisse utiliser et qui corresponde à mes besoins à l’heure actuelle (voyez la maigre page des stats sur WAR). Leur base de données est apparemment forte de plus de 40 millions de titres. Leur SDK est développé en C et des wrappers iOS, Android, Python et Java sont disponibles.

Les plus :

  • Un plan Basic (gratuit) est disponible ;
  • Une doc compréhensible ;
  • Un wrapper Python officiel qui fonctionne sur tous les OS majeurs ;
  • Possibilité d’affiner leur algo en précisant si ce qu’on leur envoie a été enregistré via un micro ou si c’est de l’audio pur.

Les moins :

  • J’en ai pas encore trouvé.

Appréciation finale : nickel. Exemple :

from acrcloud.recognizer import ACRCloudRecognizer

config = {
    'host': 'eu-west-1.api.acrcloud.com',
    'access_key': '<la clé d accès>',
    'access_secret': '<la clé secrète>',
    'debug': True,
    'timeout': 10
}

acrcloud = ACRCloudRecognizer(config)

print(acrcloud.recognize_by_file('whololo.wav', 0))

Je suis grand, je peux le faire moi-même

Croyez-moi, vous n’avez pas envie de coder l’algo et tout ce qu’il y a derrière vous-même depuis zéro. Heureusement qu’il existe des solutions open-source, bordel ! Je ne les connais évidemment pas toutes, mais je peux vous citer dejavu et AcoustID (oui, le même site dont j’ai parlé plus haut est entièrement open-source).

Je vous laisse regarder en détail AcoustID. Je vais plutôt vous parler de dejavu - que je n’ai pas testé - mais qui a l’air d’être bigrement bien foutu et surtout qui est codé 100% en Python. Si vous souhaitez avoir une vue théorique sur la reconnaissance musicale en générale et des détails sur le fonctionnement de dejavu, un bel article vous attends ici.

Après l’avoir installé, il faut d’abord remplir sa base de données. Pour ce faire :

from dejavu import Dejavu

config = {
    "database": {
        "host": "127.0.0.1",
        "user": "root",
        "passwd": '<mot de passe de la bdd>', 
        "db": '<nom de la base de données>',
    }
}

djv = Dejavu(config)

# Va générer les empreintes musicales de tous les fichiers .mp3
# dans le répertoire "chemin/vers/musiques", à l'aide de 3 processus.
djv.fingerprint_directory('chemin/vers/musiques', ['.mp3'], 3)

Quand ça aura fini et que vous appellerez djv.db.get_num_fingerprints(), cela devrait vous afficher le nombre total d’empreintes générées.

Ensuite, prenez un fichier dans ce répertoire et passez-le à la moulinette histoire de voir si dejavu le reconnaît bien :

from dejavu.recognize import FileRecognizer

# djv est une instance de Dejavu
song = djv.recognize(FileRecognizer, 'chemin/vers/musiques/Puff Daddy - I ll Be Missing You.mp3')

End words

Au final, il existe quand même pas mal de solutions. Les quelques-unes fournies par des services tiers dont il est possible de tirer des infos sont toutes développées en C (certainement pour des raisons de performances et de compatibilité multi-plateforme). Mais seules deux peuvent être effectivement utilisées en Python, ce qui est très désappointant.

Il est également possible, à l’aide de solutions open-source, de mettre en place sa propre base de données audio et tout ce qu’il faut en amont mais qu’il faudra “seeder” soi-même, ce qui est chiant.

Si vous connaissez d’autres services de ce genre, faites moi signe !

Mise à jour 3 juin 2017

WAR a fermé ses portes.