Aller au contenu principal
Leçon 9 sur 14 · Grok Voice & Audio

TTS en Streaming avec WebSocket

Leçon 9 sur 14 Mis à jour le 3 novembre 2026 Intermédiaire
Sur cette page
  1. Pourquoi le streaming change l’expérience
  2. Établir la connexion
  3. Le protocole de messages
  4. Une implémentation complète
  5. Les limites à connaître
  6. HTTP ou WebSocket
  7. Points clés à retenir

Leçon corrigée le 3 novembre 2026 d’après la page Text to Speech de xAI : deltas de 60 000 caractères et non 15 000 ; la page ne dit pas que la session se ferme après dix minutes d’inactivité — elle indique une connexion sans délai d’expiration et un « permis de session » de 600 secondes. Source : Text to Speech.

Pourquoi le streaming change l’expérience

En mode HTTP, le TTS ne vous rend la main qu’une fois l’intégralité de l’audio produite. Pour une notification de deux phrases, l’attente passe inaperçue. Pour un article de blog, un chapitre de livre ou un fil d’actualités qui défile en continu, elle devient le principal défaut de votre produit : l’utilisateur clique, puis regarde un indicateur de chargement pendant plusieurs secondes.

Le mode WebSocket supprime cette attente en poussant l’audio au fur et à mesure de sa synthèse. Le lecteur démarre sur les premiers mots alors que la fin du texte n’a pas encore été traitée — la différence entre une page qui semble figée et une lecture immédiate.

Établir la connexion

La connexion s’ouvre sur wss://api.x.ai/v1/tts, et toute la configuration passe par la query string de l’URL plutôt que par un message d’initialisation.

const ws = new WebSocket(
  "wss://api.x.ai/v1/tts?language=fr&voice=ara&codec=mp3&sample_rate=24000",
  {
    headers: {
      "Authorization": "Bearer " + XAI_API_KEY
    }
  }
);

Les paramètres acceptés sont les suivants :

  • language (obligatoire) : code BCP-47 ou auto
  • voice (optionnel, défaut : eve) : identifiant de la voix
  • codec (optionnel, défaut : mp3) : format audio de sortie
  • sample_rate (optionnel, défaut : 24000) : fréquence d’échantillonnage en Hz
  • bit_rate (optionnel, défaut : 128000) : débit binaire en bps (MP3 uniquement)

Ces réglages valent pour toute la durée de la session : vous ne changez pas de voix ni de codec en cours de route. Si votre application doit alterner deux narrateurs, ouvrez deux connexions.

Le protocole de messages

Côté émission, deux messages suffisent à piloter la synthèse. Le premier envoie un morceau de texte, le second annonce que le texte est complet.

{ "type": "text.delta", "delta": "Bonjour et bienvenue " }
{ "type": "text.done" }

Vous pouvez enchaîner autant de text.delta que nécessaire, chacun jusqu’à 60 000 caractères. Mieux vaut pourtant ne pas remplir ce plafond : découper en morceaux de quelques phrases fait arriver le premier chunk audio bien plus tôt, ce qui est précisément l’intérêt du streaming. Un delta unique de plusieurs milliers de caractères vous ramène au comportement du mode HTTP.

Côté réception, chaque audio.delta transporte un fragment d’audio encodé en base64, dans le codec que vous avez spécifié à la connexion. Vous le décodez et l’ajoutez à votre buffer de lecture.

{ "type": "audio.delta", "delta": "<base64 audio>" }
{ "type": "audio.done", "trace_id": "uuid-de-trace" }

L’événement audio.done marque la fin de la synthèse ; son trace_id est l’identifiant à fournir au support ou à consigner dans vos logs lorsqu’une génération se comporte mal. En cas de texte invalide ou de quota dépassé, un message d’erreur arrive à la place.

{ "type": "error", "message": "description de l'erreur" }

Une implémentation complète

L’exemple ci-dessous découpe un texte long par paragraphes, les envoie tous, puis assemble les fragments audio reçus dans un fichier MP3.

const WebSocket = require("ws");
const fs = require("fs");

const ws = new WebSocket(
  "wss://api.x.ai/v1/tts?language=fr&voice=rex&codec=mp3",
  { headers: { "Authorization": "Bearer " + process.env.XAI_API_KEY } }
);

const audioChunks = [];

ws.on("open", () => {
  const paragraphs = longText.split("\n\n");
  for (const para of paragraphs) {
    ws.send(JSON.stringify({
      type: "text.delta",
      delta: para + " "
    }));
  }
  ws.send(JSON.stringify({ type: "text.done" }));
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  if (msg.type === "audio.delta") {
    audioChunks.push(Buffer.from(msg.delta, "base64"));
  } else if (msg.type === "audio.done") {
    fs.writeFileSync("output.mp3", Buffer.concat(audioChunks));
    ws.close();
  }
});

Notez le para + " " : sans cet espace, la fin d’un paragraphe se colle au début du suivant et le moteur enchaîne les deux mots sans respiration.

Les limites à connaître

MétriqueValeur
Texte par delta60 000 caractères max
Texte totalIllimité
Sessions simultanées50 par équipe
Permis de session600 secondes
Délai d’expiration de la connexionAucun

La page de xAI indique que la connexion n’a pas de délai d’expiration, et mentionne par ailleurs un « permis de session » de 600 secondes sans détailler ce qui se passe à son terme. Par prudence, connectez-vous au moment où vous avez du texte à envoyer plutôt qu’au chargement de la page, et prévoyez la reconnexion. La limite de 50 sessions simultanées par équipe se planifie de la même façon — une bibliothèque audio qui convertit son catalogue en tâche de fond sérialise ses travaux plutôt que de lancer deux cents connexions en parallèle.

HTTP ou WebSocket

Le mode HTTP reste le bon choix pour les textes courts, pour les générations ponctuelles et partout où la simplicité d’intégration prime : une requête, une réponse, aucun état à gérer. Le WebSocket s’impose dès que le texte s’allonge, que l’audio doit être écouté pendant sa production, ou que le contenu arrive lui-même en flux continu — typiquement la sortie d’un modèle de langage que vous vocalisez au fil de sa génération.

Points clés à retenir

  • Le mode WebSocket TTS permet de recevoir l’audio en streaming sans attendre la fin de la génération
  • Les paramètres de configuration se passent dans la query string de l’URL de connexion
  • Le protocole est simple : text.delta pour envoyer du texte, audio.delta pour recevoir l’audio
  • Les sessions WebSocket sont limitées à 50 simultanées par équipe ; prévoyez la reconnexion
  • Privilégiez le WebSocket pour les textes longs et les expériences de lecture en temps réel