> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gradium.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Du microphone du navigateur à la transcription (STT)

> Capturez l'audio du microphone dans un navigateur et diffusez-le en streaming vers la transcription (STT) Gradium

Cette recette présente les différentes briques de la transcription
depuis le microphone du navigateur. En production, combinez-la avec
les [WebSockets dans le navigateur](/fr/guides/browser-websockets) afin que le navigateur utilise un
token de courte durée plutôt qu'une clé API.

## Déroulement

1. Demandez à l'utilisateur l'autorisation d'accéder au microphone.
2. Capturez l'audio avec la Web Audio API.
3. Convertissez les échantillons flottants en PCM mono 16 bits.
4. Envoyez des fragments audio en base64 via `wss://api.gradium.ai/api/speech/asr`.
5. Affichez les messages `text` et utilisez les messages `step` pour la gestion des tours de parole.

## Client navigateur

```js theme={null}
async function getGradiumToken() {
  const response = await fetch("/gradium-token", {method: "POST"});
  if (!response.ok) throw new Error("Could not get Gradium token");
  return response.json();
}

function pcm16Base64(float32) {
  const pcm = new Int16Array(float32.length);
  for (let i = 0; i < float32.length; i += 1) {
    const sample = Math.max(-1, Math.min(1, float32[i]));
    pcm[i] = sample < 0 ? sample * 32768 : sample * 32767;
  }

  const bytes = new Uint8Array(pcm.buffer);
  let binary = "";
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary);
}

function appendTranscript(text) {
  console.log("transcript", text);
}

function markPossibleTurnEnd() {
  console.log("possible turn end");
}

async function startTranscription() {
  const {token} = await getGradiumToken();
  const url = new URL("wss://api.gradium.ai/api/speech/asr");
  url.searchParams.set("token", token);

  const stream = await navigator.mediaDevices.getUserMedia({audio: true});
  const audioContext = new AudioContext({sampleRate: 24000});
  const source = audioContext.createMediaStreamSource(stream);
  const processor = audioContext.createScriptProcessor(2048, 1, 1);
  const ws = new WebSocket(url);

  ws.addEventListener("open", () => {
    ws.send(JSON.stringify({
      type: "setup",
      model_name: "default",
      input_format: "pcm",
      json_config: {language: "en"},
    }));
  });

  ws.addEventListener("message", (event) => {
    const msg = JSON.parse(event.data);
    if (msg.type === "text") {
      appendTranscript(msg.text);
    } else if (msg.type === "step") {
      const horizon = msg.vad[msg.vad.length - 1];
      if (horizon?.inactivity_prob > 0.5) markPossibleTurnEnd();
    }
  });

  processor.onaudioprocess = (event) => {
    if (ws.readyState !== WebSocket.OPEN) return;
    const samples = event.inputBuffer.getChannelData(0);
    ws.send(JSON.stringify({
      type: "audio",
      audio: pcm16Base64(samples),
    }));
  };

  source.connect(processor);
  processor.connect(audioContext.destination);

  return {
    stop() {
      ws.send(JSON.stringify({type: "end_of_stream"}));
      processor.disconnect();
      source.disconnect();
      stream.getTracks().forEach((track) => track.stop());
    },
  };
}
```

`ScriptProcessorNode` est facile à lire mais obsolète. En production,
préférez un `AudioWorklet` pour que la capture audio reste fiable même lorsque l'interface est chargée.

## Remarques sur le format audio

* `input_format: "pcm"` correspond à du PCM mono 24 kHz, entiers signés 16 bits.
* Si le graphe audio de votre navigateur tourne à 48 kHz, rééchantillonnez à 24 kHz
  ou envoyez `input_format: "pcm_48000"`.
* Envoyez de petits fragments, d'environ 80-100 ms, pour maintenir une latence faible.
* N'envoyez pas de formats compressés du navigateur, sauf si vous définissez explicitement un
  format d'entrée Gradium pris en charge, comme `opus`.

## Voir aussi

<CardGroup cols={2}>
  <Card title="WebSocket de transcription (STT)" icon="microphone" href="/fr/guides/speech-to-text">
    Types de messages, VAD, flush et exemples de WebSocket direct.
  </Card>

  <Card title="Gestion des tours de parole avec la VAD" icon="comments" href="/fr/guides/recipes/turn-taking">
    Utilisez la VAD sémantique pour déterminer quand un locuteur a fini de parler.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.