Streaming de la voix
Le streaming envoie l'audio d'une requête de synthèse vocale par fragments pendant que la génération se poursuit. L'auditeur entend ainsi les premiers mots plus tôt. Cette page explique comment envoyer une requête en streaming, lire l'audio à mesure qu'il arrive et mesurer le temps d'attente de l'auditeur.
Pour obtenir un fichier complet à la place, consultez Génération de Speech. Pour comprendre ce qui fait attendre l'auditeur et comment se répartit ce délai, consultez Latence.
Fonctionnement du streaming
Une requête en streaming est une requête de synthèse vocale dont le paramètre stream est défini sur true. Vous envoyez toujours le texte complet en une seule requête : seul l'audio est renvoyé par fragments, sous forme de server-sent events.
| Événement | Champs | Action de votre application |
|---|---|---|
speech.audio.delta | audio_data : un fragment audio encodé en base64 | Décodez le fragment et transmettez-le à votre lecteur, ou ajoutez-le au fichier que vous écrivez. |
speech.audio.done | usage | Arrêtez de lire la réponse : l'audio est complet. |
Les fragments arrivent dans l'ordre. Une fois assemblés, ils forment un fichier audio au format response_format demandé, identique au fichier obtenu avec une requête sans streaming.
Le streaming de la réponse ne transforme pas la requête en session temps réel : le texte doit être complet au moment de l'envoi. Pour synthétiser le texte pendant son écriture, consultez Envoyer le texte en streaming pendant son écriture.
Envoyer une requête en streaming
Le script suivant envoie une requête en streaming, enregistre l'instant où le premier fragment arrive et sauvegarde tous les fragments dans un seul fichier MP3 :
import base64
import os
import time
from pathlib import Path
from mistralai.client import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
chunks = []
first_audio = None
start = time.perf_counter()
with client.audio.speech.complete(
model="voxtral-mini-tts-3-0",
input=(
"Thanks for calling. Your order shipped this morning and should arrive on Thursday. "
"You'll get a tracking link by email within the hour."
),
voice_id="gb_jane_neutral",
response_format="mp3",
stream=True,
) as stream:
for event in stream:
if event.event == "speech.audio.delta":
if first_audio is None:
first_audio = time.perf_counter() - start
chunks.append(base64.b64decode(event.data.audio_data))
elif event.event == "speech.audio.done":
print(f"Usage: {event.data.usage}")
output = Path("streamed.mp3")
output.write_bytes(b"".join(chunks))
print(f"First audio after {first_audio:.2f} s, {len(chunks)} chunks, total {time.perf_counter() - start:.2f} s")
print(f"Saved {output.resolve()}")Lire l'audio à mesure qu'il arrive
Pour démarrer la lecture avant que le fichier complet soit prêt, décodez chaque speech.audio.delta et transmettez les octets à un lecteur qui accepte un flux, dans leur ordre d'arrivée.
La plupart des lecteurs conservent une petite quantité d'audio dans une mémoire tampon avant de démarrer. La taille de cette mémoire tampon impose un compromis :
| Mémoire tampon du lecteur | Résultat pour l'auditeur | Risque |
|---|---|---|
| Plus petite | Le premier son arrive plus tôt | Des coupures pendant la lecture si le fragment suivant arrive en retard |
| Plus grande | Une lecture fluide | Une attente plus longue avant le premier son |
Commencez avec la mémoire tampon par défaut de votre lecteur et réduisez-la uniquement si le premier son arrive trop tard. Testez avec les conditions réseau de vos utilisateurs, pas seulement avec une connexion rapide.
Mesurer le délai avant le premier son
Le délai avant le premier son correspond au temps d'attente de l'auditeur. Mesurez-le à deux niveaux :
- De l'envoi de la requête au premier
speech.audio.delta, comme dans l'exemple. Ce délai correspond à l'attente liée à l'API et au réseau. - De l'envoi de la requête au premier son émis par votre lecteur. Ce délai inclut la mémoire tampon du lecteur et correspond à l'attente perçue par l'auditeur.
. Mesurez-le donc sur de nombreuses requêtes et surveillez les plus lentes, pas seulement la moyenne. Pour la méthode complète, consultez Latence.
Envoyer le texte en streaming pendant son écriture
Problèmes courants
Ces problèmes sont propres au streaming. Pour les erreurs liées à la requête elle-même, comme une voix inconnue ou un format invalide, consultez Dépannage.
| Symptôme | Cause | Solution |
|---|---|---|
| La lecture ne démarre qu'une fois l'audio complet disponible | Votre client lit la réponse complète avant de la transmettre | Lisez les événements à mesure qu'ils arrivent et transmettez immédiatement chaque fragment au lecteur. |
| Coupures ou saccades pendant la lecture | La mémoire tampon du lecteur se vide avant l'arrivée du fragment suivant | Augmentez la mémoire tampon du lecteur ou vérifiez le réseau entre votre application et l'API. |
| Le fichier sauvegardé ne peut pas être lu | Les fragments ont été sauvegardés dans le désordre, ou l'un d'eux a été perdu | Décodez chaque speech.audio.delta et écrivez les fragments dans leur ordre d'arrivée. |