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