Aller au contenu principal

Envoyer de l'audio avec input_audio_buffer.append

Streaming audio vers le serveur

Une fois la session configurée, vous pouvez commencer à envoyer de l’audio en continu vers le serveur. L’événement input_audio_buffer.append transmet des morceaux (chunks) d’audio encodés en base64.

Structure de l’événement

{
  "type": "input_audio_buffer.append",
  "audio": "SGVsbG8gV29ybGQ..."
}

Le champ audio contient les données audio brutes encodées en base64. Le format de ces données doit correspondre à celui configuré dans session.update (par défaut, PCM 16 bits little-endian à 24000 Hz).

Capture audio depuis le navigateur

L’API Web Audio du navigateur permet de capturer le microphone et d’envoyer les données en temps réel :

async function startCapture(ws) {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: {
      sampleRate: 24000,
      channelCount: 1,
      echoCancellation: true,
      noiseSuppression: true
    }
  });

  const audioContext = new AudioContext({ sampleRate: 24000 });
  const source = audioContext.createMediaStreamSource(stream);
  const processor = audioContext.createScriptProcessor(4096, 1, 1);

  processor.onaudioprocess = (event) => {
    const inputData = event.inputBuffer.getChannelData(0);
    const pcm16 = float32ToPCM16(inputData);
    const base64 = arrayBufferToBase64(pcm16.buffer);

    ws.send(JSON.stringify({
      type: "input_audio_buffer.append",
      audio: base64
    }));
  };

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

function float32ToPCM16(float32Array) {
  const pcm16 = new Int16Array(float32Array.length);
  for (let i = 0; i < float32Array.length; i++) {
    const s = Math.max(-1, Math.min(1, float32Array[i]));
    pcm16[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
  }
  return pcm16;
}

function arrayBufferToBase64(buffer) {
  const bytes = new Uint8Array(buffer);
  let binary = "";
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary);
}

Capture audio en Python

Avec la bibliothèque pyaudio, vous pouvez capturer le microphone et envoyer les chunks :

import pyaudio
import base64
import json

RATE = 24000
CHUNK = 4096
FORMAT = pyaudio.paInt16
CHANNELS = 1

p = pyaudio.PyAudio()
stream = p.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=RATE,
    input=True,
    frames_per_buffer=CHUNK
)

async def send_audio(ws):
    while True:
        data = stream.read(CHUNK, exception_on_overflow=False)
        audio_b64 = base64.b64encode(data).decode("utf-8")
        await ws.send(json.dumps({
            "type": "input_audio_buffer.append",
            "audio": audio_b64
        }))

Taille et fréquence des chunks

La taille des chunks influence la latence et la performance :

  • Petits chunks (1024 échantillons / ~42 ms) : latence minimale, mais plus de messages WebSocket
  • Chunks moyens (4096 échantillons / ~170 ms) : bon compromis
  • Gros chunks (8192 échantillons / ~341 ms) : moins de messages, mais latence perceptible

Pour une conversation naturelle, envoyez des chunks toutes les 100-200 ms. Le VAD du serveur accumule les données dans un buffer interne et les traite en continu.

Annulation de l’écho

Si votre application joue l’audio de réponse sur des haut-parleurs pendant que le microphone est actif, vous devez gérer l’annulation d’écho. Sans cela, l’agent s’entendrait parler et pourrait entrer dans une boucle de conversation avec lui-même.

Les solutions :

  • Utilisez les options echoCancellation et noiseSuppression de l’API Web Audio
  • Coupez le microphone pendant que l’agent parle (mute/unmute)
  • Utilisez un casque pour isoler l’entrée de la sortie

Points clés à retenir

  • input_audio_buffer.append envoie des chunks audio encodés en base64
  • Le format des données doit correspondre à la configuration de session (PCM 16 bits par défaut)
  • Envoyez des chunks toutes les 100-200 ms pour un bon compromis latence/performance
  • La capture audio depuis le navigateur utilise l’API Web Audio avec conversion Float32 vers PCM16
  • Gérez l’annulation d’écho pour éviter les boucles audio