@synapxlab/voice

Lecture vocale neuronale, locale et souveraine.
Transformez vos documents Markdown en fichiers audio MP3 naturels et structurés. La synthèse s'exécute entièrement en local, sans API tierce.

  • Voix neuronale française (moteur Piper, modèles ONNX)
  • 100 % local et souverain — aucun texte envoyé à un service cloud
  • Rythme piloté par la structure Markdown (titres, listes, citations)
  • Humanisation : variations de vitesse et de volume, respirations, pauses probabilistes
  • API asynchrone, cache déterministe, sortie MP3 192 kbps
Python FastAPI Piper ONNX Local-first
tts.sh
# Markdown → MP3, en local curl -X POST voice.locme.fr/tts \ -F "voice=tom" \ -F "file=@article.md" # → 202 { "job_id": "…" } curl voice.locme.fr/tts/$job_id # → { "status": "done", "key": "…" } curl -O voice.locme.fr/audio/$key.mp3

Écouter la démo

Le même texte, synthétisé en local par le moteur neuronal Piper, avec deux voix françaises. Écoutez dans le navigateur ou téléchargez le MP3.

Voix tom · défaut

Piper · MP3 192 kbps · 44,1 kHz

⬇ Télécharger demo-tom.mp3

Voix upmc

Piper · MP3 · 22,05 kHz

⬇ Télécharger demo-upmc.mp3

Comparer avec la voix de votre navigateur

La même démo, lue cette fois par la synthèse vocale intégrée à votre navigateur (Web Speech API). L'écart met en évidence le naturel de la voix neuronale et la gestion du rythme.

Une voix locale, un rythme naturel. La lecture vocale ne devrait pas dépendre d'un service distant. Avec une synthèse exécutée localement, le document reste sous votre contrôle, du premier mot jusqu'au fichier audio final. Aucune donnée n'est transmise à une plateforme externe. La structure du texte guide naturellement l'écoute. Les titres introduisent des pauses plus longues, tandis que les paragraphes et les listes conservent un rythme fluide. La ponctuation ajoute de légères respirations, sans ralentir chaque phrase. Le résultat est une voix claire, régulière et agréable à suivre.

Présentation

@synapxlab/voice est un micro-service de synthèse vocale neuronale conçu pour transformer un document Markdown en fichier audio MP3. Développé avec Python, FastAPI et Uvicorn, il utilise le moteur Piper et ses modèles vocaux ONNX pour produire une lecture française claire et structurée.

Le service ne se contente pas de convertir une suite de caractères en parole. Il interprète l'organisation du document afin d'adapter le rythme aux titres, paragraphes, listes et citations. Cette approche améliore la fluidité de l'écoute et restitue plus fidèlement l'intention éditoriale du contenu.

Toute la chaîne de synthèse vocale fonctionne en local. Aucun texte, document ou fichier audio n'est envoyé vers une API tierce. Cette architecture souveraine constitue une alternative aux services TTS cloud de Google, Amazon ou ElevenLabs lorsque la confidentialité et la maîtrise des données sont prioritaires.

À venir : générateur de voix. Un générateur de voix permettra prochainement d'enregistrer au micro un corpus de phrases de lecture afin de fine-tuner un modèle Piper personnalisé. Cette approche produit une voix neuronale locale, fondée sur les données vocales de l'utilisateur, avec un traitement maîtrisé et souverain. Le corpus de lecture dédié est présenté sur la page Corpus. Découvrir Corpus

Comment c'est codé

Le document Markdown est d'abord rendu en HTML. Le moteur parcourt ensuite sa structure bloc par bloc : titres de niveau h1 à h6, paragraphes, listes et citations. Ce découpage permet à la forme éditoriale du document de piloter directement le rythme de la lecture.

Chaque bloc est synthétisé séparément avec Piper, à partir d'un modèle de voix neuronale ONNX. Deux voix françaises sont disponibles : tom, utilisée par défaut, et upmc. La vitesse standard est réglée à 1,2x, soit 20 % plus rapide que le débit natif.

L'humanisation repose sur plusieurs variations contrôlées. La vitesse diminue progressivement selon le niveau des titres. Un léger jitter aléatoire modifie la vitesse et la durée des silences. Des pauses peuvent également suivre la ponctuation — point, point d'exclamation, point d'interrogation, points de suspension, point-virgule, deux-points ou virgule — avec une probabilité de saut pour éviter un rendu mécanique. Les virgules sont plus souvent ignorées que les points. Une respiration longue peut apparaître occasionnellement en fin de phrase, tandis que les sauts de ligne durs sont pris en charge.

Deux mécanismes supplémentaires renforcent l'humanisation de la voix. Une respiration physiologique est insérée au-delà d'environ 7 secondes de parole continue, même sans ponctuation, avec un léger jitter sur le seuil et sur la pause d'environ 0,45 s. De rares variations de volume sont aussi appliquées par fragment, en piano (gain de 0,86 à 0,95) ou en forte (gain de 1,04 à 1,10), le signal restant borné aux limites de l'audio 16 bits pour éviter toute saturation.

Mécanismes d'humanisation

Au-delà du rendu neuronal brut, une couche de prosodie recrée les micro-variations d'une voix vivante : souffle, dynamique, hauteur et cadence.

ÉlémentCe que ça fait
Souffle inspiratoireUn bruit d'inspiration audible est synthétisé puis inséré dans les pauses longues, comme une prise d'air avant la reprise de parole.
Souffles réelsLe moteur peut remplacer le souffle synthétique par de vrais enregistrements WAV d'inspiration, afin d'ajouter un grain plus naturel.
Courbe d'expirationLe volume décroît progressivement pendant un groupe de souffle jusqu'à un plancher, puis revient au niveau plein après chaque respiration.
Nuance dynamiqueDe rares variations de volume sont appliquées par fragment, en atténuation, pour éviter un niveau parfaitement plat sans provoquer de saturation.
Variance du timbreL'aléa interne du modèle neuronal Piper VITS introduit de légères variations de couleur vocale d'une synthèse à l'autre.
Jitter temporelLa vitesse de lecture et la durée des silences reçoivent un léger jitter aléatoire, afin d'éviter une répétition strictement identique.
Respiration physiologiqueAprès environ 7 secondes de parole continue, une inspiration est imposée même sans ponctuation.
Contour interrogatifAvant un point d'interrogation, la hauteur monte progressivement sur la dernière syllabe prononcée pour former une intonation de question.
Rallentando finalLa dernière partie d'une phrase ralentit légèrement, reproduisant une cadence de fin de phrase plus humaine.
Focus prosodiqueLe mot le plus rare et encore jamais entendu dans un fragment est mis en relief une fois, avec une légère montée et un allongement.
Enchaînement des virgulesLorsqu'une virgule apparaît trop près de la fin d'une phrase, sa respiration est supprimée pour conserver une lecture fluide, sans suspension parasite.

Des silences adaptés sont insérés entre les blocs : une pause plus longue accompagne les titres, alors qu'une pause plus courte sépare les éléments d'une liste. Les segments PCM 16 bits mono sont ensuite concaténés, puis encodés par ffmpeg dans un fichier MP3 à 192 kbps.

Les blocs de code ne sont pas épelés, car leur lecture serait longue et difficile à comprendre. Ils sont remplacés par une annonce explicite, telle que « bloc de code non lisible », « bloc mermaid non lisible » ou « formule non lisible ».

Le cache est déterministe. Sa clé correspond au SHA-256 de la version du moteur, de la voix, de la vitesse et du texte. Un article identique n'est donc jamais régénéré inutilement. La variable ENGINE_VERSION permet d'invalider l'ensemble du cache lorsque le comportement du rendu évolue.

L'API fonctionne de manière asynchrone. Une requête POST /tts, contenant du texte ou un fichier .md, renvoie un statut 202 avec un job_id, ou un statut 200 si le résultat existe déjà dans le cache. L'état est suivi avec GET /tts/{job_id} jusqu'au statut done, puis le MP3 est récupéré via GET /audio/{clé}.mp3. Les endpoints /voices et /health exposent respectivement les voix disponibles et l'état du service. La synthèse est sérialisée à un seul job simultané, car la phonémisation avec espeak-ng n'est pas thread-safe.

Partition & prononciation

Vous pouvez annoter le texte comme une partition musicale, à l'aide de directives entre crochets dont la portée est bornée, par exemple [nuance]…[/nuance]. Imbriquables et alignées sur le standard SSML, ces annotations pilotent la lecture, mais n'apparaissent jamais dans le document affiché ni dans ses exports, notamment en PDF : elles sont exclusivement destinées à la voix.

Les annotations forment désormais un langage complet, le SSM (Synapx Speech Markup). La partition riche se place dans un bloc ```voice, avec un en-tête JSON facultatif pour la voix par défaut, l'intention et les personnages, puis un corps annoté. Tout crochet inconnu ou mal fermé est ignoré sans casser la synthèse, selon le principe de dégradation SSM.

DirectiveEffet
[pp] [p] [mp] [mf] [f] [ff]
Alias : [piano], [forte]
Règle la dynamique, c'est-à-dire le volume. Le réglage fonctionne par atténuation : [mf], [f] et [ff] conservent le niveau plein, tandis que le contraste est créé du côté doux avec [p] et [pp], afin d'éviter toute saturation.
[ton+2]…[/ton], [ton-1]…[/ton], [aigu], [grave]Modifie la hauteur en demi-tons. L'effet est appliqué uniquement si le passage est bordé par de la ponctuation des deux côtés ; sinon, il est ignoré pour préserver la fluidité. Cette directive convient idéalement à une incise entre virgules ou à une phrase entière.
[lent] [rapide], [vitesse=0.9]Règle le tempo de la lecture.
[pause], [pause=400ms]Insère un silence. Cette directive est auto-fermante.
[dis:graphie]mot[/dis]
Alias : [son:…], [lit:…]
Force la prononciation : le document affiche le mot, tandis que la voix lit la graphie indiquée, selon la sémantique SSML sub alias.
[colère] [joie] [tristesse] [calme] [peur] [mystère]Appliquent des préréglages cohérents de ton, de débit, de dynamique et d'enveloppe pour orienter l'interprétation d'un passage sans modifier son texte.
[voix=jessica]…[/voix], [voix=marie]…[/voix]Permettent de changer de locuteur au fil de la lecture et de distribuer des rôles nommés, notamment ceux définis dans l'en-tête du bloc voix.
[fx=reverb]…[/fx], [fx=telephone], [fx=radio], [echo=1s]Traitent la voix synthétisée comme un signal audio afin de simuler un espace, un combiné, une radio, un éloignement ou une réverbération.
[ambiance=pluie]…[/ambiance]Posent un lit sonore bouclé sous la voix, avec atténuation automatique du fond lorsque la parole est présente.
[sfx=train], [sfx=train]…[/sfx]Déclenchent un bruitage précis, soit ponctuellement, soit sur la durée exacte d'un passage encadré.

Le moteur espeak-ng gère déjà automatiquement les liaisons (« les amis »), les lettres finales muettes (« Aramis ») et les anglicismes comme « cloud » ou « markdown », lus à l'anglaise. Le respelling est donc réservé aux noms propres et aux mots étrangers récalcitrants. Il ne requiert ni API ni alphabet phonétique international (API/IPA) : utilisez simplement une graphie « à la française ». Exemple : [dis:Païpeur]Piper[/dis] affiche « Piper » et prononce « Païpeur ».

# Une confidence dite plus doucement
Le résultat est confirmé. [piano]Cette information reste confidentielle.[/piano]

# Une incise relevée de deux demi-tons
Le service, [ton+2]dans sa dernière version[/ton], produit directement un fichier MP3.

Le bloc voix : en-tête, personnages et décor sonore

Pour une partition riche, on regroupe le texte dans un bloc ```voice. Son en-tête JSON définit les réglages d'ensemble — voix par défaut, intention globale et personnages — avec des clés toutes optionnelles. Dès qu'un bloc voix existe, le moteur passe en mode partition : seul le contenu de ces blocs est lu, le reste du document (titres, notes du rédacteur) est ignoré à la synthèse. On peut ainsi entourer la partition de commentaires qui ne seront jamais prononcés.

```voice
{
  "default": "tom",
  "intention": "narration",
  "personnages": { "marie": { "voix": "jessica" } }
}

[ambiance=pluie]
La verrière de la gare résonne sous l'averse. [sfx=train]
[voix=marie][joie]Enfin, vous êtes là ![/joie][/voix]
[/ambiance]
```

Générer une partition avec une IA

Vous n'écrivez pas les annotations à la main : confiez-les à une intelligence artificielle. Copiez le prompt ci-dessous dans ChatGPT, Claude ou tout autre assistant, collez votre texte à l'endroit indiqué, puis récupérez une version annotée prête à être lue par la voix.

Tu es un metteur en voix. On te donne un texte (en Markdown). Ta mission : y insérer des annotations de lecture « partition » pour qu'une voix de synthèse le lise de façon vivante et naturelle. Tu ne réécris pas le texte et tu n'ajoutes aucun mot : tu insères uniquement des directives entre crochets.

Directives disponibles (portée bornée, imbriquables — chaque ouverture se ferme, ex. [piano]…[/piano]) :

• Dynamique (volume) : [pp] [p] [mp] [mf] [f] [ff] (alias [piano], [forte]).
  Le volume ne fonctionne qu'en ATTÉNUATION : [mf], [f], [ff] = niveau normal ;
  le contraste se crée en jouant DOUX ([p], [pp]) sur les passages secondaires.
  Pour « appuyer » une idée, adoucis ce qui l'entoure — ne cherche jamais à monter le volume.

• Hauteur : [ton+2]…[/ton], [ton-1]…[/ton] (en demi-tons), ou [aigu] / [grave].
  RÈGLE STRICTE : n'utilise [ton] QUE sur un passage bordé par de la ponctuation
  des deux côtés (une incise entre deux virgules, ou une phrase entière entre points).
  Ailleurs, la montée de ton est ignorée. Parfait pour une question complète.

• Tempo : [lent]…[/lent], [rapide]…[/rapide], ou [vitesse=0.9]…[/vitesse].

• Pause : [pause] ou [pause=400ms] (auto-fermant, à placer entre deux phrases).

• Prononciation : [dis:graphie]mot[/dis] — pour un nom propre ou un mot étranger
  mal prononcé, donne une graphie « à la française » (ex. [dis:Païpeur]Piper[/dis],
  qui affiche « Piper » mais fait lire « Païpeur »). N'utilise PAS d'alphabet phonétique.

Consignes de style :
• Sois SOBRE. Ce n'est pas du théâtre : l'essentiel du texte reste neutre.
  Une touche d'humanité suffit — quelques nuances discrètes, une ou deux respirations,
  une intonation sur une question.
• N'annote jamais l'intérieur d'un bloc de code (```), d'un tableau ou d'une URL.
• Ne modifie ni les titres Markdown ni la structure : insère seulement des directives dans le corps.
• Rends UNIQUEMENT le texte annoté, sans commentaire ni explication.

Texte à mettre en voix :
«««
[ COLLEZ ICI VOTRE TEXTE ]
»»»

Conversions de lecture automatiques

Sans aucune annotation, le service développe « 25 000 » en « vingt-cinq mille » et « 3 000 000 » en « trois millions ». Il lit également les abréviations (M. devient « Monsieur », kg « kilogrammes », K. « kilo », etc.) ainsi que les débits : 300 tonnes/an devient « 300 tonnes par an », de même pour km/h, mg/jour et les formes comparables.

API

EndpointRôle
POST /ttsSoumet du texte ou un fichier .md. Renvoie 202 { job_id }, ou 200 { key } si déjà en cache.
GET /tts/{job_id}Suit l'état du job jusqu'au statut done.
GET /audio/{key}.mp3Récupère le fichier MP3 synthétisé.
GET /voicesListe les voix disponibles (tom, upmc).
GET /healthÉtat du service et voix par défaut.
# 1. Soumettre un Markdown
curl -X POST voice.locme.fr/tts \
  -F "voice=tom" \
  -F "file=@article.md"
# → 202 { "job_id": "a1b2c3…" }

# 2. Suivre le job
curl voice.locme.fr/tts/a1b2c3…
# → { "status": "done", "key": "9f8e…" }

# 3. Récupérer l'audio
curl -O voice.locme.fr/audio/9f8e….mp3

Utilisation en direct

Déjà branché sur le blog. Le service alimente la lecture vocale de markdown.synapx.fr : chaque article Markdown y est converti en MP3 à la volée, sans configuration côté page. Rien à câbler pour l'essayer.

Studio & table de mixage

Le studio sert à mettre en voix une partition comme dans une petite station audio. Il permet de sculpter le rendu final, d'ajuster le grain, l'espace, la réverbération et la chaîne de traitement, sans modifier le moteur de synthèse lui-même.

La table de mixage et la sonothèque complètent ce travail en organisant les sons disponibles. On y importe des samples, on les pré-écoute, puis on relie un nom d'ambiance ou de bruitage SSM à un fichier par alias, afin qu'une annotation comme une pluie, un train ou une radio appelle toujours le bon son.

  • Composer une scène complète en associant voix, personnages, ambiances et bruitages
  • Faire dialoguer plusieurs personnages tout en conservant une voix par défaut stable
  • Poser une pluie, un hall, une ville ou un fond discret sous un passage parlé
  • Ajouter des effets maître, un égaliseur ou une chaîne de traitement sur le rendu final
  • Constituer une bibliothèque sonore réutilisable grâce aux alias SSM
  • Pré-écouter les sons et tester une partition avant la génération définitive
  • Sauvegarder un projet, une ambiance ou un réglage pour le rejouer et l'affiner ensuite

Fonctionnalités

  • Synthèse vocale neuronale française avec Piper et des modèles ONNX
  • Fonctionnement 100 % local et souverain, sans API tierce
  • Conversion directe de documents Markdown en fichiers MP3
  • Rythme piloté par les titres, paragraphes, listes et citations
  • Humanisation par variations de vitesse, pauses probabilistes et respirations
  • Respiration physiologique insérée au-delà d'environ 7 secondes de parole continue
  • Variations de volume piano/forte par fragment, sans saturation
  • Grammaire SSM : blocs ```voice avec en-tête JSON (voix, intention, personnages)
  • Émotions préconfigurées, multi-voix et personnages nommés
  • Effets audio, ambiances bouclées et bruitages ponctuels
  • Studio de mise en voix et sonothèque avec alias SSM
  • Blocs de code annoncés sans être épelés
  • Cache déterministe avec invalidation par version du moteur
  • API asynchrone avec suivi des jobs et récupération du fichier audio
  • Deux voix françaises : tom par défaut et upmc
  • Sortie PCM 16 bits mono encodée en MP3 à 192 kbps