Le projet ccmusic-data base propose un système d'intelligence artificielle capable d'identifier automatiquement 16 styles musicaux distincts. En s'appuyant sur l'architecture VGG19_BN et l'extraction de caractéristiques fréquentielles via la transformée à Q constante (CQT), cet outil analyse les empreintes sonores pour fournir une classification précise.
Architecture du système
Le processus de reconnaissance suit un pipeline structuré en trois étapes clés :
- Transformation Spectrale : Le signal audio brut est converti en spectrogramme CQT, agissant comme une signature visuelle de la musique.
- Inférence par Réseau de Neurones : Le modèle VGG19_BN traite cette "image" sonore pour détecter les motifs caractéristiques de chaque genre.
- Calcul de Probabilités : Le système génère un score pour chaque catégorie, affichant les cinq correspondances les plus probables.
Structure du projet
Pour garantir une isolation parfaite et une portabilité maximale, nous utilisons Docker Compose pour orchestrer l'interface utilisateur et le moteur de prétraitement.
.
├── docker-compose.yml
├── app-classifier/
│ ├── Dockerfile
│ ├── main.py
│ └── requirements.txt
├── worker-ffmpeg/
│ ├── Dockerfile
│ ├── processor.py
│ └── requirements-worker.txt
└── data/
├── models/
├── samples/
└── cache/
Configuration de l'orchestration Docker
Le fichier docker-compose.yml définit la communication entre le conteneur applicatif et le microservice de traitement audio.
version: '3.9'
services:
classifier-ui:
build: ./app-classifier
container_name: music-classifier-web
ports:
- "7860:7860"
volumes:
- ./data/models:/app/models
- ./data/cache:/app/audio_cache
environment:
- WORKER_URL=http://audio-processor:8000
- MODEL_FILE=/app/models/weights.pt
depends_on:
- audio-processor
networks:
- internal-net
audio-processor:
build: ./worker-ffmpeg
container_name: ffmpeg-worker-api
volumes:
- ./data/cache:/app/audio_cache
networks:
- internal-net
networks:
internal-net:
driver: bridge
Microservice de prétraitement FFmpeg
Le script suivant (processor.py) utilise FastAPI pour exposer une interface de conversion audio robuste.
from fastapi import FastAPI, UploadFile, File
import subprocess
import os
import uuid
from pathlib import Path
service = FastAPI(title="Audio Worker")
STORAGE = Path("/app/audio_cache")
@service.post("/convert")
async def convert_audio(audio_stream: UploadFile = File(...)):
job_id = uuid.uuid4()
raw_path = STORAGE / f"raw_{job_id}"
out_path = STORAGE / f"norm_{job_id}.wav"
with open(raw_path, "wb") as buffer:
buffer.write(await audio_stream.read())
# Normalisation : 44.1kHz, Mono, PCM 16-bit
ffmpeg_cmd = [
"ffmpeg", "-i", str(raw_path),
"-ar", "44100", "-ac", "1",
"-acodec", "pcm_s16le", "-y",
str(out_path)
]
proc = subprocess.run(ffmpeg_cmd, capture_output=True)
if raw_path.exists():
raw_path.unlink()
if proc.returncode != 0:
return {"status": "error", "log": proc.stderr.decode()}
return {"status": "ready", "filename": out_path.name}
if __name__ == "__main__":
import uvicorn
uvicorn.run(service, host="0.0.0.0", port=8000)
Logique de l'application principale
L'interface Gradio (main.py) gère l'interaction utilisateur et l'appel au modèle Deep Learning.
import torch
import torch.nn as nn
from torchvision import models
import librosa
import numpy as np
import gradio as gr
import requests
import os
from PIL import Image
GENRES = [
"Symphonie", "Opéra", "Solo", "Musique de chambre",
"Pop vocale", "Adulte contemporain", "Teen pop", "Dance pop",
"Indie pop", "Art pop", "Soul/R&B", "Rock alternatif",
"Rock épique", "Soft rock", "Pop acoustique", "Variété"
]
class MusicNet(nn.Module):
def __init__(self, target_classes=16):
super().__init__()
base = models.vgg19_bn(weights=None)
self.features = base.features
self.pool = nn.AdaptiveAvgPool2d((7, 7))
self.head = nn.Sequential(
nn.Linear(512 * 7 * 7, 512),
nn.ReLU(),
nn.Dropout(0.4),
nn.Linear(512, target_classes)
)
def forward(self, x):
x = self.features(x)
x = self.pool(x)
x = torch.flatten(x, 1)
return self.head(x)
def get_spectrogram(path):
sig, sr = librosa.load(path, sr=22050, duration=30)
cqt = np.abs(librosa.cqt(sig, sr=sr))
db_cqt = librosa.amplitude_to_db(cqt, ref=np.max)
# Redimensionnement pour VGG
img = Image.fromarray(((db_cqt - db_cqt.min()) / (db_cqt.max() - db_cqt.min()) * 255).astype(np.uint8))
img = img.resize((224, 224)).convert("RGB")
tensor = torch.from_numpy(np.array(img)).permute(2, 0, 1).float() / 255.0
return tensor.unsqueeze(0)
def classify_music(file_path):
# Appel au worker FFmpeg
with open(file_path, 'rb') as f:
resp = requests.post(f"{os.getenv('WORKER_URL')}/convert", files={'audio_stream': f})
processed_path = f"/app/audio_cache/{resp.json()['filename']}"
input_data = get_spectrogram(processed_path)
with torch.no_grad():
logits = model(input_data)
probs = torch.nn.functional.softmax(logits, dim=1)[0]
results = {GENRES[i]: float(probs[i]) for i in range(len(GENRES))}
return results
# Initialisation
model = MusicNet()
state = torch.load(os.getenv("MODEL_FILE", "model.pt"), map_location="cpu")
model.load_state_dict(state['model_state_dict'])
model.eval()
# Interface UI
ui = gr.Interface(
fn=classify_music,
inputs=gr.Audio(type="filepath"),
outputs=gr.Label(num_top_classes=5),
title="Analyseur de Genre Musical AI"
)
if __name__ == "__main__":
ui.launch(server_name="0.0.0.0", server_port=7860)
Déploiement et exécution
Avant de lancer l'infrastructure, assurez-vous de placer le fichier de poids du modèle (weights.pt) dans le répertoire data/models. Exécutez ensuite la commande suivante :
docker-compose up -d --build
Une fois les conteneurs opérationnels, l'interface est accessible sur le port 7860 de votre machine. Le système supporte les fichiers MP3, WAV et les enregistrements directs via micro. Grâce à l'utilisation de FFmpeg en amont, les fichiers sont systématiquement normalisés avant l'analyse, ce qui réduit considérablement les erreurs d'inférence liées aux formats hétérogènes.
Considérations techniques
- Gestion de la mémoire : Le modèle VGG19_BN nécessite environ 2 Go de RAM lors de l'inférence. Surveillez la consommation du conteneur si vous déployez sur une machine limitée.
- Optimisation : Pour les environnements de production, l'ajout d'un volume de cache partagé permet d'éviter de retraiter plusieurs fois le même échantillon sonore.
- Sécurité : Le service FFmpeg est isolé dans un réseau interne Docker, ce qui protège l'accès direct aux fonctions de traitement système depuis l'extérieur.