Synthèse vocale en Rust hors ligne
Rust a des crates qui enveloppent les moteurs vocaux du système, parfaits pour l’accessibilité mais avec des voix robotiques différentes sur chaque plateforme, et des SDK cloud facturés au caractère. Pour un jeu, un bot ou un outil en ligne de commande qui a besoin d’une même voix naturelle partout, aucun n’est idéal.
Ce guide montre comment appeler le moteur gratuit SuperClonica depuis Rust via un serveur HTTP local : des voix naturelles, des fichiers WAV que vous gardez et quelques lignes avec reqwest.
Les façons de parler depuis Rust
Pour une sortie façon lecteur d’écran, les voix système conviennent ; pour la voix d’un produit ou d’un jeu, prenez un moteur.
- Crates qui enveloppent les voix du système : hors ligne et légers, mais robotiques et différents sous Windows, macOS et Linux.
- SDK cloud : voix naturelles, mais compte, clé, facturation au caractère et votre texte sur leurs serveurs.
- SuperClonica : un serveur HTTP local avec des voix naturelles, de personnages et personnalisées, hors ligne, partout où tourne Docker.
- Il parle 31 langues ; le chinois n’est pas encore pris en charge.
Écouter les voix gratuitement
Avant d’écrire du code, ouvrez la page de n’importe quelle voix, saisissez une phrase de 30 à 100 caractères, choisissez la langue et cliquez sur le bouton de synthèse. En quelques secondes, vous entendez la voix que pourrait avoir votre appli, sans compte.
Lancer le serveur vocal
Une carte graphique NVIDIA accélère le tout avec l’image cuda, mais elle n’est pas obligatoire.
- Lancez le serveur sur n’importe quel processeur : docker run -d -p 8000:8000 -v superclonica-models:/models superclonica/superclonica:cpu.
- Le premier démarrage télécharge le modèle Supertonic 3, environ 385 Mo, dans le volume ; GET /health indique quand il est prêt.
- POST /synthesize reçoit du JSON avec text, voice, lang, seed et normalize, et répond par un WAV mono 16 bits.
- voice est un nom de base de M1 à M5 et de F1 à F5, ou le contenu JSON d’un fichier de voix.
L’appeler depuis Rust
Avec le crate reqwest et sa fonctionnalité blocking, dans une fonction qui renvoie un Result, une requête tient en quelques lignes : let voice = std::fs::read_to_string("voice.json")?; let body = format!(r#"{{"text": "Bonjour depuis Rust !", "lang": "fr", "seed": 7, "voice": {voice}}}"#); let wav = reqwest::blocking::Client::new().post("http://localhost:8000/synthesize").header("Content-Type", "application/json").body(body).send()?.bytes()?; std::fs::write("hello.wav", wav)?; En code asynchrone, utilisez de la même façon le client asynchrone de reqwest. Pour une voix de base, envoyez "voice": "F1" au lieu du fichier. Le même texte, la même voix et le même seed donnent toujours le même son : mettez en cache les fichiers des phrases qui reviennent ; serde_json garde les grosses requêtes propres.
Bonnes pratiques en production
Réutilisez un seul client reqwest et fixez un délai d’expiration. N’exposez pas le port 8000 sur internet tel quel : définissez SUPERCLONICA_API_KEY et envoyez-la comme jeton Bearer, ou gardez le serveur sur un réseau privé. Si beaucoup de requêtes arrivent en même temps, lancez plus de copies du modèle avec SUPERCLONICA_LANES, et mesurez sur votre matériel : dans nos tests, une phrase courte a pris 0,12 s sur une RTX 5070 Ti et 0,43 s sur quatre threads de processeur.