azure-ai-voicelive-ts

npx skills add https://github.com/microsoft/skills --skill azure-ai-voicelive-ts

@azure/ai-voicelive (JavaScript/TypeScript)

SDK de voix IA en temps réel pour construire des assistants vocaux bidirectionnels avec Azure AI dans les environnements Node.js et navigateur.

Installation

npm install @azure/ai-voicelive @azure/identity
# Utilisateurs TypeScript
npm install @types/node

Version actuelle : 1.0.0-beta.3

Environnements supportés :

  • Versions Node.js LTS (20+)
  • Navigateurs modernes (Chrome, Firefox, Safari, Edge)

Variables d'environnement

AZURE_VOICELIVE_ENDPOINT=https://<resource>.cognitiveservices.azure.com
# Optionnel : clé API si vous n'utilisez pas Entra ID
AZURE_VOICELIVE_API_KEY=<your-api-key>
# Optionnel : Journalisation
AZURE_LOG_LEVEL=info
AZURE_TOKEN_CREDENTIALS=prod # Requis uniquement si DefaultAzureCredential est utilisé en production

Authentification

Identifiant de jeton Microsoft Entra (Recommandé)

import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
import { VoiceLiveClient } from "@azure/ai-voicelive";

// Dev local : DefaultAzureCredential. Production : définir AZURE_TOKEN_CREDENTIALS=prod ou AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Ou utilisez un identifiant spécifique directement en production :
// Voir https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const endpoint = "https://your-resource.cognitiveservices.azure.com";

const client = new VoiceLiveClient(endpoint, credential);

Clé API

import { AzureKeyCredential } from "@azure/core-auth";
import { VoiceLiveClient } from "@azure/ai-voicelive";

const endpoint = "https://your-resource.cognitiveservices.azure.com";
const credential = new AzureKeyCredential("your-api-key");

const client = new VoiceLiveClient(endpoint, credential);

Hiérarchie du client

VoiceLiveClient
└── VoiceLiveSession (connexion WebSocket)
    ├── updateSession()      → Configurer les options de session
    ├── subscribe()          → Gestionnaires d'événements (motif Azure SDK)
    ├── sendAudio()          → Diffuser l'entrée audio
    ├── addConversationItem() → Ajouter des messages/résultats de fonction
    └── sendEvent()          → Envoyer des événements de protocole bruts

Démarrage rapide

import { DefaultAzureCredential } from "@azure/identity";
import { VoiceLiveClient } from "@azure/ai-voicelive";

const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
const endpoint = process.env.AZURE_VOICELIVE_ENDPOINT!;

// Créer le client et démarrer la session
const client = new VoiceLiveClient(endpoint, credential);
const session = await client.startSession("gpt-4o-mini-realtime-preview");

// Configurer la session
await session.updateSession({
  modalities: ["text", "audio"],
  instructions: "You are a helpful AI assistant. Respond naturally.",
  voice: {
    type: "azure-standard",
    name: "en-US-AvaNeural",
  },
  turnDetection: {
    type: "server_vad",
    threshold: 0.5,
    prefixPaddingMs: 300,
    silenceDurationMs: 500,
  },
  inputAudioFormat: "pcm16",
  outputAudioFormat: "pcm16",
});

// S'abonner aux événements
const subscription = session.subscribe({
  onResponseAudioDelta: async (event, context) => {
    // Gérer la sortie audio en continu
    const audioData = event.delta;
    playAudioChunk(audioData);
  },
  onResponseTextDelta: async (event, context) => {
    // Gérer le texte en continu
    process.stdout.write(event.delta);
  },
  onInputAudioTranscriptionCompleted: async (event, context) => {
    console.log("User said:", event.transcript);
  },
});

// Envoyer l'audio du microphone
function sendAudioChunk(audioBuffer: ArrayBuffer) {
  session.sendAudio(audioBuffer);
}

Configuration de la session

await session.updateSession({
  // Modalités
  modalities: ["audio", "text"],

  // Instructions système
  instructions: "You are a customer service representative.",

  // Sélection de la voix
  voice: {
    type: "azure-standard",  // ou "azure-custom", "openai"
    name: "en-US-AvaNeural",
  },

  // Détection de tour (VAD)
  turnDetection: {
    type: "server_vad",      // ou "azure_semantic_vad"
    threshold: 0.5,
    prefixPaddingMs: 300,
    silenceDurationMs: 500,
  },

  // Formats audio
  inputAudioFormat: "pcm16",
  outputAudioFormat: "pcm16",

  // Outils (function calling)
  tools: [
    {
      type: "function",
      name: "get_weather",
      description: "Get current weather",
      parameters: {
        type: "object",
        properties: {
          location: { type: "string" }
        },
        required: ["location"]
      }
    }
  ],
  toolChoice: "auto",
});

Gestion des événements (motif Azure SDK)

Le SDK utilise un motif de gestion d'événements basé sur l'abonnement :

const subscription = session.subscribe({
  // Cycle de vie de la connexion
  onConnected: async (args, context) => {
    console.log("Connected:", args.connectionId);
  },
  onDisconnected: async (args, context) => {
    console.log("Disconnected:", args.code, args.reason);
  },
  onError: async (args, context) => {
    console.error("Error:", args.error.message);
  },

  // Événements de session
  onSessionCreated: async (event, context) => {
    console.log("Session created:", context.sessionId);
  },
  onSessionUpdated: async (event, context) => {
    console.log("Session updated");
  },

  // Événements d'entrée audio (VAD)
  onInputAudioBufferSpeechStarted: async (event, context) => {
    console.log("Speech started at:", event.audioStartMs);
  },
  onInputAudioBufferSpeechStopped: async (event, context) => {
    console.log("Speech stopped at:", event.audioEndMs);
  },

  // Événements de transcription
  onConversationItemInputAudioTranscriptionCompleted: async (event, context) => {
    console.log("User said:", event.transcript);
  },
  onConversationItemInputAudioTranscriptionDelta: async (event, context) => {
    process.stdout.write(event.delta);
  },

  // Événements de réponse
  onResponseCreated: async (event, context) => {
    console.log("Response started");
  },
  onResponseDone: async (event, context) => {
    console.log("Response complete");
  },

  // Texte en continu
  onResponseTextDelta: async (event, context) => {
    process.stdout.write(event.delta);
  },
  onResponseTextDone: async (event, context) => {
    console.log("\n--- Text complete ---");
  },

  // Audio en continu
  onResponseAudioDelta: async (event, context) => {
    const audioData = event.delta;
    playAudioChunk(audioData);
  },
  onResponseAudioDone: async (event, context) => {
    console.log("Audio complete");
  },

  // Transcription audio (ce que l'assistant a dit)
  onResponseAudioTranscriptDelta: async (event, context) => {
    process.stdout.write(event.delta);
  },

  // Function calling
  onResponseFunctionCallArgumentsDone: async (event, context) => {
    if (event.name === "get_weather") {
      const args = JSON.parse(event.arguments);
      const result = await getWeather(args.location);

      await session.addConversationItem({
        type: "function_call_output",
        callId: event.callId,
        output: JSON.stringify(result),
      });

      await session.sendEvent({ type: "response.create" });
    }
  },

  // Catch-all pour le débogage
  onServerEvent: async (event, context) => {
    console.log("Event:", event.type);
  },
});

// Nettoyer quand vous avez terminé
await subscription.close();

Function Calling

// Définir les outils dans la configuration de la session
await session.updateSession({
  modalities: ["audio", "text"],
  instructions: "Help users with weather information.",
  tools: [
    {
      type: "function",
      name: "get_weather",
      description: "Get current weather for a location",
      parameters: {
        type: "object",
        properties: {
          location: {
            type: "string",
            description: "City and state or country",
          },
        },
        required: ["location"],
      },
    },
  ],
  toolChoice: "auto",
});

// Gérer les appels de fonction
const subscription = session.subscribe({
  onResponseFunctionCallArgumentsDone: async (event, context) => {
    if (event.name === "get_weather") {
      const args = JSON.parse(event.arguments);
      const weatherData = await fetchWeather(args.location);

      // Envoyer le résultat de la fonction
      await session.addConversationItem({
        type: "function_call_output",
        callId: event.callId,
        output: JSON.stringify(weatherData),
      });

      // Déclencher la génération de réponse
      await session.sendEvent({ type: "response.create" });
    }
  },
});

Options de voix

Type de voix Configuration Exemple
Azure Standard { type: "azure-standard", name: "..." } "en-US-AvaNeural"
Azure Custom { type: "azure-custom", name: "...", endpointId: "..." } Point de terminaison de voix personnalisée
Azure Personal { type: "azure-personal", speakerProfileId: "..." } Clone de voix personnelle
OpenAI { type: "openai", name: "..." } "alloy", "echo", "shimmer"

Modèles supportés

Modèle Description Cas d'usage
gpt-4o-realtime-preview GPT-4o avec audio en temps réel IA conversationnelle haute qualité
gpt-4o-mini-realtime-preview GPT-4o léger Interactions rapides et efficaces
phi4-mm-realtime Phi multimodal Applications économiques

Options de détection de tour

// Server VAD (par défaut)
turnDetection: {
  type: "server_vad",
  threshold: 0.5,
  prefixPaddingMs: 300,
  silenceDurationMs: 500,
}

// Azure Semantic VAD (détection plus intelligente)
turnDetection: {
  type: "azure_semantic_vad",
}

// Azure Semantic VAD (optimisé pour l'anglais)
turnDetection: {
  type: "azure_semantic_vad_en",
}

// Azure Semantic VAD (Multilingue)
turnDetection: {
  type: "azure_semantic_vad_multilingual",
}

Formats audio

Format Fréquence d'échantillonnage Cas d'usage
pcm16 24 kHz Par défaut, haute qualité
pcm16-8000hz 8 kHz Téléphonie
pcm16-16000hz 16 kHz Assistants vocaux
g711_ulaw 8 kHz Téléphonie (États-Unis)
g711_alaw 8 kHz Téléphonie (UE)

Référence des types clés

Type Objectif
VoiceLiveClient Client principal pour créer des sessions
VoiceLiveSession Session WebSocket active
VoiceLiveSessionHandlers Interface du gestionnaire d'événements
VoiceLiveSubscription Abonnement actif aux événements
ConnectionContext Contexte pour les événements de connexion
SessionContext Contexte pour les événements de session
ServerEventUnion Union de tous les événements serveur

Gestion des erreurs

import {
  VoiceLiveError,
  VoiceLiveConnectionError,
  VoiceLiveAuthenticationError,
  VoiceLiveProtocolError,
} from "@azure/ai-voicelive";

const subscription = session.subscribe({
  onError: async (args, context) => {
    const { error } = args;

    if (error instanceof VoiceLiveConnectionError) {
      console.error("Connection error:", error.message);
    } else if (error instanceof VoiceLiveAuthenticationError) {
      console.error("Auth error:", error.message);
    } else if (error instanceof VoiceLiveProtocolError) {
      console.error("Protocol error:", error.message);
    }
  },

  onServerError: async (event, context) => {
    console.error("Server error:", event.error?.message);
  },
});

Journalisation

import { setLogLevel } from "@azure/logger";

// Activer la journalisation détaillée
setLogLevel("info");

// Ou via variable d'environnement
// AZURE_LOG_LEVEL=info

Utilisation dans le navigateur

// Le navigateur nécessite un bundler (Vite, webpack, etc.)
import { VoiceLiveClient } from "@azure/ai-voicelive";
import { InteractiveBrowserCredential } from "@azure/identity";

// Utiliser un identifiant compatible avec le navigateur
const credential = new InteractiveBrowserCredential({
  clientId: "your-client-id",
  tenantId: "your-tenant-id",
});

const client = new VoiceLiveClient(endpoint, credential);

// Demander l'accès au microphone
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const audioContext = new AudioContext({ sampleRate: 24000 });

// Traiter l'audio et l'envoyer à la session
// ... (voir les exemples pour l'implémentation complète)

Bonnes pratiques

  1. Utiliser DefaultAzureCredential pour le développement local ; utiliser ManagedIdentityCredential ou WorkloadIdentityCredential en production — Ne jamais coder en dur les clés API
  2. Définir les deux modalités — Inclure ["text", "audio"] pour les assistants vocaux
  3. Utiliser Azure Semantic VAD — Meilleure détection de tour que le VAD serveur basique
  4. Gérer tous les types d'erreurs — Connexion, authentification et erreurs de protocole
  5. Nettoyer les abonnements — Appeler subscription.close() une fois terminé
  6. Utiliser le format audio approprié — PCM16 à 24 kHz pour la meilleure qualité

Liens de référence

Ressource URL
Package npm https://www.npmjs.com/package/@azure/ai-voicelive
Source GitHub https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/ai/ai-voicelive
Exemples https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/ai/ai-voicelive/samples
Référence API https://learn.microsoft.com/javascript/api/@azure/ai-voicelive

Skills similaires