Aller au contenu principal

Génération de parole basique

Mis à jour le 29 juillet 2026

Votre première génération vocale

Vous savez maintenant créer une voix et la gérer via l’API Voices. Il reste à faire ce pour quoi tout ce travail a été mené : produire du son. L’API Speech de Mistral tient dans un seul appel, client.audio.speech.complete(), qui reçoit du texte et un identifiant de voix, et renvoie de l’audio encodé en base64. Cette leçon couvre la génération basique avec une voix sauvegardée ; le clonage à la volée et le streaming viendront juste après.

Le code ci-dessous suffit à transformer une phrase en fichier MP3 sur votre disque. Observez la dernière étape : la réponse ne contient pas des octets audio directement exploitables, mais une chaîne base64 qu’il faut décoder avant d’écrire le fichier. C’est l’erreur classique du premier essai — on sauvegarde la chaîne telle quelle et le lecteur audio refuse de l’ouvrir.

import base64
from pathlib import Path
from mistralai.client import Mistral

client = Mistral(api_key="votre-cle-api")

# Générer de la parole avec une voix sauvegardée
response = client.audio.speech.complete(
    model="voxtral-mini-tts-2603",
    input="Bonjour et bienvenue dans cette formation sur Voxtral TTS.",
    voice_id="votre-voice-id",
    response_format="mp3",
)

# Décoder le base64 et sauvegarder en fichier
audio_bytes = base64.b64decode(response.audio_data)
Path("sortie.mp3").write_bytes(audio_bytes)
print(f"Audio généré : {len(audio_bytes)} octets")

Ce que gouverne chaque paramètre

Le paramètre model désigne le modèle de synthèse. À ce jour, voxtral-mini-tts-2603 est le seul disponible, mais indiquez-le toujours explicitement : le jour où d’autres modèles apparaîtront, votre code continuera de produire exactement la même voix qu’aujourd’hui.

input reçoit le texte à prononcer, et c’est de loin le paramètre qui demande le plus d’attention. Restez sous 300 mots par requête pour conserver une qualité optimale. Bannissez les emojis, que le modèle ne sait pas interpréter, ainsi que le formatage complexe — Markdown, HTML, caractères spéciaux —, qui finit lu à voix haute tel quel. Écrivez enfin les chiffres et les abréviations en toutes lettres : « vingt-trois » plutôt que « 23 », « Société à Responsabilité Limitée » plutôt que « SARL ». Un agent vocal qui annonce un montant en butant sur les chiffres perd sa crédibilité en une phrase.

voice_id identifie la voix employée. Vous l’obtenez de trois façons : en créant une voix avec client.audio.voices.create() (voir leçon 5), en listant vos voix existantes avec client.audio.voices.list(), ou en reprenant l’identifiant d’une voix professionnelle Mistral. response_format, enfin, fixe le format de sortie parmi mp3, wav, pcm, flac et opus. Ce choix pèse sur la taille des fichiers comme sur la latence, et la leçon 12 lui est entièrement consacrée.

Passer à l’échelle : un chapitre d’audiobook

La limite des 300 mots impose de découper tout texte un peu long. Le principe est simple : vous préparez une liste de paragraphes, vous générez chacun d’eux séparément, puis vous accumulez les octets décodés dans un même tampon avant d’écrire le fichier final.

import base64
from pathlib import Path
from mistralai.client import Mistral

client = Mistral(api_key="votre-cle-api")
voice_id = "votre-voice-id"

# Texte découpé en paragraphes (max 300 mots chacun)
paragraphes = [
    "Premier paragraphe du chapitre. Le narrateur introduit le contexte.",
    "Deuxième paragraphe. L'action commence à se développer.",
    "Troisième paragraphe. Le suspense monte progressivement.",
]

audio_complet = b""

for i, texte in enumerate(paragraphes):
    print(f"Génération du segment {i + 1}/{len(paragraphes)}...")
    response = client.audio.speech.complete(
        model="voxtral-mini-tts-2603",
        input=texte,
        voice_id=voice_id,
        response_format="wav",
    )
    audio_complet += base64.b64decode(response.audio_data)

Path("chapitre-01.wav").write_bytes(audio_complet)
print("Chapitre audio généré avec succès !")

Ce script fonctionne parce qu’il produit du WAV, un format non compressé dont les segments se mettent bout à bout sans traitement particulier. Tentez la même chose avec du MP3 ou de l’Opus et le résultat sera inutilisable : ces formats compressés portent des en-têtes et un découpage en trames que la concaténation brute casse. Passez alors par une bibliothèque comme pydub, qui décode chaque segment avant de les fusionner proprement.

Quand la génération échoue

En production, l’appel doit être protégé. Un voice_id supprimé la veille par un collègue, un texte qui dépasse discrètement les 300 mots parce qu’un champ a été concaténé, un quota API épuisé en fin de mois, un format de sortie mal orthographié : chacune de ces situations lève une exception, et sans garde-fou votre traitement par lots s’arrête au milieu du corpus.

try:
    response = client.audio.speech.complete(
        model="voxtral-mini-tts-2603",
        input="Texte à convertir en parole.",
        voice_id=voice_id,
        response_format="mp3",
    )
    audio_bytes = base64.b64decode(response.audio_data)
    Path("sortie.mp3").write_bytes(audio_bytes)
except Exception as e:
    print(f"Erreur lors de la génération : {e}")

Prenez le temps de tester ce chemin d’erreur avant de partir en production : générez volontairement avec un voice_id fantaisiste et vérifiez que votre application le signale clairement plutôt que de produire un fichier vide.

Points clés à retenir

  • La génération utilise client.audio.speech.complete() avec le modèle voxtral-mini-tts-2603
  • Le texte doit respecter la limite de 300 mots et éviter les emojis et le formatage
  • Épelez les chiffres et les abréviations pour une prononciation correcte
  • L’audio retourné est en base64 — décodez-le avant de sauvegarder
  • Pour les textes longs, découpez en segments et concaténez les résultats