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

> Créer des applications vocales et des agents IA.

# Voice

Le VoiceSDK offre des capacités de conversation vocale avancées avec l'intégration automatique du système de chat et des hooks React pour construire des applications compatibles avec la voix. Créez des interactions vocales naturelles avec des agents IA, complètes avec visualisation audio, transcription et gestion de conversation. Dans cet article, vous trouverez un exemple de démarrage rapide qui vous permettra non seulement de vous lancer rapidement, mais aussi de comprendre comment cela fonctionne. Le reste de l'article détaille les diverses méthodes que vous pouvez utiliser, à quoi elles servent et les meilleures pratiques.

## Installation

```bash theme={null}
npm install @odin-ai-staging/sdk @elevenlabs/react
```

## Démarrage rapide

### Conversation vocale basique

Dans cet exemple, vous apprendrez comment implémenter des conversations vocales en temps réel en utilisant le VoiceSDK dans les applications TypeScript et React. Vous commencez par initialiser le VoiceSDK avec vos identifiants API, y compris un `agentId` spécifique qui définit quel agent vocal IA gérera la conversation, puis utilisez `startVoiceConversation()` pour démarrer une session vocale avec des gestionnaires de rappel qui vous permettent de répondre aux événements de connexion, de recevoir des messages IA, de gérer les déconnexions et de traiter les transcriptions en direct de ce que dit l'utilisateur (`isFinal` indiquant quand une phrase complète a été reconnue). L'option `saveToChat` vous permet de persister la conversation vocale en tant que texte dans votre historique de chat pour une référence ultérieure. Pour les applications React, vous utiliserez le hook `useVoiceConversation`, qui fournit une interface plus propre avec la gestion d'état intégrée : il vous donne une variable `status` pour suivre l'état de la connexion, les méthodes `startSession()` et `endSession()` pour contrôler la conversation, `setVolume()` pour ajuster les niveaux audio, `getInputByteFrequencyData()` pour visualiser l'entrée audio (parfait pour créer des affichages de forme d'onde) et `conversationState` qui contient des informations en temps réel comme les niveaux de volume actuels. Cela vous donne tout ce dont vous avez besoin pour créer des applications vocales compatibles avec l'IA avec reconnaissance et synthèse vocale en temps réel, parfait pour créer des assistants vocaux, des interfaces sans mains ou des expériences conversationnelles d'IA, avec le hook React gérant toute la gestion d'état complexe et les connexions WebSocket pour vous.

```typescript theme={null}
import { VoiceSDK } from '@odin-ai-staging/sdk';

// Initialiser le SDK
const voiceSDK = new VoiceSDK({
  baseUrl: 'https://your-api-endpoint.com/',
  projectId: 'your-project-id',
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
  agentId: 'your-agent-id'
});

// Démarrer une conversation vocale
async function startVoiceChat() {
  const sessionId = await voiceSDK.startVoiceConversation({
    saveToChat: true,
    callbacks: {
      onConnect: () => console.log('Voix connectée'),
      onMessage: (message) => console.log('Message vocal:', message),
      onDisconnect: () => console.log('Voix déconnectée'),
      onTranscription: (text, isFinal) => {
        if (isFinal) console.log('Utilisateur a dit:', text);
      }
    }
  });
  
  console.log('Session vocale démarrée:', sessionId);
}
```

### Utilisation du hook React

```tsx theme={null}
import { useVoiceConversation } from '@odin-ai-staging/sdk';

function VoiceChat() {
  const {
    status,
    startSession,
    endSession,
    setVolume,
    getInputByteFrequencyData,
    conversationState
  } = useVoiceConversation({
    sdkConfig: {
      baseUrl: 'https://your-api-endpoint.com/',
      projectId: 'your-project-id',
      agentId: 'your-agent-id'
    },
    callbacks: {
      onConnect: () => console.log('Connecté !'),
      onMessage: (message) => console.log('Message:', message)
    }
  });

  return (
    <div>
      <button 
        onClick={() => startSession()}
        disabled={status === 'connected'}
      >
        Démarrer le chat vocal
      </button>
      
      <button 
        onClick={() => endSession()}
        disabled={status !== 'connected'}
      >
        Terminer le chat
      </button>
      
      <div>Statut: {status}</div>
      <div>Volume: {conversationState.volume}</div>
    </div>
  );
}
```

## Configuration

### Interface VoiceSDKConfig

```typescript theme={null}
interface VoiceSDKConfig extends BaseClientConfig {
  agentId?: string;            // ID d'agent par défaut pour les conversations
  defaultVoiceSettings?: VoiceSettings;  // Configuration vocale par défaut
}
```

### Paramètres vocaux

```typescript theme={null}
interface VoiceSettings {
  stability?: number;          // Stabilité vocale (0.0 à 1.0)
  similarityBoost?: number;    // Amplification de similarité vocale (0.0 à 1.0)
  style?: number;             // Style vocal (0.0 à 1.0)
  useSpeakerBoost?: boolean;  // Activer l'amplification du haut-parleur
}
```

**Exemple de configuration :**

```typescript theme={null}
const voiceSDK = new VoiceSDK({
  baseUrl: 'https://api.example.com/',
  projectId: 'proj_123',
  apiKey: 'your-api-key',
  apiSecret: 'your-api-secret',
  agentId: 'agent_456',
  defaultVoiceSettings: {
    stability: 0.8,
    similarityBoost: 0.7,
    style: 0.3,
    useSpeakerBoost: true
  }
});
```

## Fonctionnalités principales

### Sessions de conversation vocale

Le VoiceSDK gère les sessions de conversation vocale avec intégration automatique du chat :

```typescript theme={null}
interface VoiceConversationSession {
  id: string;                    // Identifiant de session
  chatId?: string;               // ID de chat associé
  startTime: number;             // Horodatage du début de session
  endTime?: number;              // Horodatage de fin de session
  messages: VoiceMessage[];      // Messages vocaux de la session
  metadata?: {
    agentId?: string;
    voiceSettings?: VoiceSettings;
    totalDuration?: number;
    userInfo?: { name: string; id: string };
  };
}
```

### Messages vocaux

```typescript theme={null}
interface VoiceMessage {
  id: string;                    // ID du message
  type: 'user_speech' | 'ai_speech' | 'system';
  text: string;                  // Texte transcrit/généré
  audioUrl?: string;             // URL du fichier audio
  timestamp: number;             // Horodatage du message
  duration?: number;             // Durée audio en secondes
  voiceSettings?: VoiceSettings; // Paramètres vocaux utilisés
  saved?: boolean;               // Enregistré ou non en base de données
}
```

## Gestion des sessions

### `startVoiceConversation(options?)`

Démarrer une nouvelle session de conversation vocale.

```typescript theme={null}
async startVoiceConversation(
  options?: StartVoiceConversationOptions
): Promise<string>
```

**Options StartVoiceConversationOptions :**

```typescript theme={null}
interface StartVoiceConversationOptions {
  callbacks?: VoiceConversationCallbacks;
  saveToChat?: boolean;          // Enregistrement automatique dans l'historique de chat
  existingChatId?: string;       // Continuer un chat existant
  agentId?: string;             // Remplacer l'agent par défaut
  voiceSettings?: VoiceSettings; // Paramètres vocaux personnalisés
  userInfo?: { name: string; id: string };
}
```

**Exemple :**

```typescript theme={null}
const sessionId = await voiceSDK.startVoiceConversation({
  saveToChat: true,
  existingChatId: 'chat_123',
  voiceSettings: {
    stability: 0.9,
    similarityBoost: 0.8
  },
  userInfo: {
    name: 'Jean Dupont',
    id: 'user_456'
  },
  callbacks: {
    onConnect: () => console.log('Conversation vocale démarrée'),
    onMessage: (message) => handleVoiceMessage(message),
    onTranscription: (text, isFinal) => {
      if (isFinal) displayTranscription(text);
    },
    onConversationSaved: (chatId, messageId) => {
      console.log(`Conversation enregistrée dans le chat ${chatId}`);
    }
  }
});
```

### `endVoiceSession(sessionId, reason?)`

Terminer une session de conversation vocale.

```typescript theme={null}
async endVoiceSession(sessionId: string, reason?: string): Promise<void>
```

**Exemple :**

```typescript theme={null}
await voiceSDK.endVoiceSession(sessionId, 'Utilisateur a terminé la conversation');
```

### `getVoiceState(sessionId)`

Obtenir l'état actuel de la conversation vocale.

```typescript theme={null}
getVoiceState(sessionId: string): VoiceConversationState | null
```

**Exemple :**

```typescript theme={null}
const state = voiceSDK.getVoiceState(sessionId);
if (state) {
  console.log('Statut de connexion:', state.connectionStatus);
  console.log('Est en train de parler:', state.isSpeaking);
  console.log('Volume:', state.volume);
}
```

## Intégration React

### Hook useVoiceConversation

Le hook `useVoiceConversation` fournit l'intégration React avec la gestion d'état :

```typescript theme={null}
function useVoiceConversation(options: VoiceHookOptions): {
  // Propriétés du hook
  status: VoiceStatus;
  isSpeaking: boolean;
  startSession: (config?: VoiceSessionConfig) => Promise<string>;
  endSession: () => Promise<void>;
  setVolume: (options: { volume: number }) => void;
  
  // Propriétés SDK améliorées
  conversationState: VoiceConversationState;
  currentSessionId: string | null;
  getInputByteFrequencyData: () => Uint8Array | null;
  getOutputByteFrequencyData: () => Uint8Array | null;
}
```

**Exemple React complet :**

```tsx theme={null}
import React, { useState } from 'react';
import { useVoiceConversation } from '@odin-ai-staging/sdk';

function VoiceConversationComponent() {
  const [messages, setMessages] = useState<string[]>([]);
  const [isRecording, setIsRecording] = useState(false);

  const {
    status,
    isSpeaking,
    startSession,
    endSession,
    setVolume,
    conversationState,
    currentSessionId,
    getInputByteFrequencyData
  } = useVoiceConversation({
    sdkConfig: {
      baseUrl: process.env.REACT_APP_API_BASE_URL,
      projectId: process.env.REACT_APP_PROJECT_ID,
      agentId: process.env.REACT_APP_AGENT_ID
    },
    callbacks: {
      onConnect: () => {
        console.log('Connecté au chat vocal');
        setIsRecording(true);
      },
      onDisconnect: () => {
        console.log('Déconnecté du chat vocal');
        setIsRecording(false);
      },
      onTranscription: (text, isFinal) => {
        if (isFinal) {
          setMessages(prev => [...prev, `Vous: ${text}`]);
        }
      },
      onMessage: (message) => {
        if (message.type === 'ai_speech') {
          setMessages(prev => [...prev, `IA: ${message.text}`]);
        }
      },
      onError: (error) => {
        console.error('Erreur vocale:', error);
        setIsRecording(false);
      }
    }
  });

  const handleStartConversation = async () => {
    try {
      await startSession({
        saveToChat: true,
        voiceSettings: {
          stability: 0.8,
          similarityBoost: 0.7
        }
      });
    } catch (error) {
      console.error('Impossible de démarrer la conversation:', error);
    }
  };

  const handleEndConversation = async () => {
    try {
      await endSession();
    } catch (error) {
      console.error('Impossible de terminer la conversation:', error);
    }
  };

  const handleVolumeChange = (volume: number) => {
    setVolume({ volume });
  };

  return (
    <div className="voice-conversation">
      <div className="controls">
        <button 
          onClick={handleStartConversation}
          disabled={status === 'connected'}
        >
          Démarrer le chat vocal
        </button>
        
        <button 
          onClick={handleEndConversation}
          disabled={status !== 'connected'}
        >
          Terminer le chat vocal
        </button>
      </div>

      <div className="status">
        <div>Statut: {status}</div>
        <div>En train de parler: {isSpeaking ? 'Oui' : 'Non'}</div>
        <div>Enregistrement: {isRecording ? 'Oui' : 'Non'}</div>
        <div>Volume: {conversationState.volume}</div>
      </div>

      <div className="volume-control">
        <label>Volume:</label>
        <input
n          type="range"
          min="0"
          max="100"
          value={conversationState.volume}
          onChange={(e) => handleVolumeChange(parseInt(e.target.value))}
        />
      </div>

      <div className="messages">
        {messages.map((message, index) => (
          <div key={index} className="message">
            {message}
          </div>
        ))}
      </div>

      {currentSessionId && (
        <AudioVisualizer 
          getInputData={getInputByteFrequencyData}
          isActive={status === 'connected'}
        />
      )}
    </div>
  );
}
```

## Contrôles vocaux

### Contrôle du volume

```typescript theme={null}
// Définir le volume (0-100)
await voiceSDK.setVolume(sessionId, 75);
```

### Contrôle du microphone

```typescript theme={null}
// Désactiver/activer le microphone
await voiceSDK.setMicrophoneMuted(sessionId, true);  // Désactiver
await voiceSDK.setMicrophoneMuted(sessionId, false); // Activer
```

### Mises à jour des paramètres vocaux

```typescript theme={null}
// Mettre à jour les paramètres vocaux pendant la conversation
await voiceSDK.updateVoiceSettings(sessionId, {
  stability: 0.9,
  similarityBoost: 0.8,
  style: 0.4
});
```

## Visualisation audio

### Données audio en temps réel

```typescript theme={null}
// Obtenir les données de fréquence audio pour la visualisation
const audioData = voiceSDK.getAudioFrequencyData(sessionId);

if (audioData) {
  const inputData = audioData.input;   // Entrée audio de l'utilisateur
  const outputData = audioData.output; // Sortie audio de l'IA
  
  // Utiliser pour la visualisation audio
  renderAudioVisualization(inputData, outputData);
}
```

### Composant de visualisation audio

```tsx theme={null}
import React, { useRef, useEffect } from 'react';

interface AudioVisualizerProps {
  getInputData: () => Uint8Array | null;
  isActive: boolean;
}

function AudioVisualizer({ getInputData, isActive }: AudioVisualizerProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    if (!isActive) return;

    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    const animate = () => {
      const data = getInputData();
      
      if (data) {
        // Effacer le canevas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Dessiner les barres de fréquence
        const barWidth = canvas.width / data.length;
        
        for (let i = 0; i < data.length; i++) {
          const barHeight = (data[i] / 255) * canvas.height;
          
          ctx.fillStyle = `hsl(${i * 2}, 100%, 50%)`;
          ctx.fillRect(
            i * barWidth,
            canvas.height - barHeight,
            barWidth - 1,
            barHeight
          );
        }
      }
      
      requestAnimationFrame(animate);
    };

    animate();
  }, [isActive, getInputData]);

  return (
    <canvas 
      ref={canvasRef}
      width={400}
      height={100}
      className="audio-visualizer"
    />
  );
}
```

## Intégration du chat

### Enregistrement automatique du chat

Les conversations vocales peuvent être automatiquement enregistrées dans votre système de chat :

```typescript theme={null}
const sessionId = await voiceSDK.startVoiceConversation({
  saveToChat: true,  // Activer l'enregistrement automatique
  existingChatId: 'chat_123',  // Optionnel : continuer un chat existant
  callbacks: {
    onConversationSaved: (chatId, messageId) => {
      console.log(`Conversation vocale enregistrée dans le chat ${chatId}`);
      // Mettre à jour l'interface utilisateur pour afficher la conversation enregistrée
      refreshChatHistory(chatId);
    }
  }
});
```

### Intégration manuelle du chat

```typescript theme={null}
// Obtenir l'historique de conversation à partir de la session vocale
const messages = voiceSDK.getConversationHistory(sessionId);

// Enregistrer dans le chat manuellement
for (const message of messages) {
  if (message.type === 'user_speech') {
    await chatSDK.sendMessage(message.text, {
      chatId: 'chat_123',
      metadata: {
        voiceMessage: true,
        audioUrl: message.audioUrl,
        sessionId: sessionId
      }
    });
  }
}
```

### Mises à jour contextuelles

Envoyer du contexte supplémentaire à la conversation vocale :

```typescript theme={null}
// Envoyer le contexte de l'historique de chat
await voiceSDK.sendContextualUpdate(
  sessionId,
  'L\'utilisateur a précédemment posé des questions sur les prix. La conversation actuelle porte sur les fonctionnalités.'
);
```

## Gestion des erreurs

```typescript theme={null}
try {
  const sessionId = await voiceSDK.startVoiceConversation({
    callbacks: {
      onError: (error) => {
        console.error('Erreur de conversation vocale:', error);
        
        // Gérer les types d'erreur spécifiques
        if (error.message.includes('microphone')) {
          showMicrophonePermissionDialog();
        } else if (error.message.includes('network')) {
          showNetworkErrorMessage();
        }
      },
      onDisconnect: (details) => {
        console.log('Déconnecté:', details?.reason);
        
        // Gérer différentes raisons de déconnexion
        if (details?.reason === 'user_ended') {
          showConversationSummary();
        } else if (details?.reason === 'error') {
          showReconnectOption();
        }
      }
    }
  });
} catch (error) {
  console.error('Impossible de démarrer la conversation vocale:', error);
  
  if (error.message.includes('agent')) {
    showAgentConfigError();
  }
}
```

## Exemples

### Support client avec voix

```typescript theme={null}
import { VoiceSDK, ChatSDK } from '@odin-ai-staging/sdk';

class VoiceCustomerSupport {
  private voiceSDK: VoiceSDK;
  private chatSDK: ChatSDK;
  private activeSession?: string;

  constructor() {
    const config = {
      baseUrl: process.env.API_BASE_URL,
      projectId: process.env.PROJECT_ID,
      apiKey: process.env.API_KEY,
      apiSecret: process.env.API_SECRET,
    };

    this.voiceSDK = new VoiceSDK(config);
    this.chatSDK = new ChatSDK(config);
  }

  async startSupportSession(customerId: string, issueType: string) {
    try {
      // Créer un nouveau chat pour cette session de support
      const chat = await this.chatSDK.createChat(
        `Support vocal - ${issueType}`,
        [] // Pourrait ajouter des clés de document pertinentes en fonction du type de problème
      );

      // Démarrer la conversation vocale
      this.activeSession = await this.voiceSDK.startVoiceConversation({
        saveToChat: true,
        existingChatId: chat.chat_id,
        agentId: this.getAgentForIssueType(issueType),
        userInfo: {
          name: `Client ${customerId}`,
          id: customerId
        },
        callbacks: {
          onConnect: () => {
            console.log('Session de support démarrée');
            this.logSupportEvent('session_started', { customerId, issueType });
          },
          onTranscription: (text, isFinal) => {
            if (isFinal) {
              this.logSupportEvent('customer_spoke', { 
                customerId, 
                text: text.substring(0, 100) // Enregistrer les 100 premiers caractères
              });
            }
          },
          onMessage: (message) => {
            if (message.type === 'ai_speech') {
              this.logSupportEvent('agent_responded', {
                customerId,
                responseLength: message.text.length
              });
            }
          },
          onConversationSaved: (chatId, messageId) => {
            console.log(`Conversation de support enregistrée dans le chat ${chatId}`);
          },
          onDisconnect: (details) => {
            this.logSupportEvent('session_ended', {
              customerId,
              reason: details?.reason,
              duration: this.getSessionDuration()
            });
          }
        }
      });

      return {
        sessionId: this.activeSession,
        chatId: chat.chat_id
      };
    } catch (error) {
      console.error('Impossible de démarrer la session de support:', error);
      throw error;
    }
  }

  async endSupportSession() {
    if (this.activeSession) {
      await this.voiceSDK.endVoiceSession(this.activeSession);
      this.activeSession = undefined;
    }
  }

  private getAgentForIssueType(issueType: string): string {
    const agentMap = {
      'technical': 'agent_technical_support',
      'billing': 'agent_billing_support',
      'general': 'agent_general_support'
    };
    return agentMap[issueType] || agentMap['general'];
  }

  private logSupportEvent(event: string, data: any) {
    console.log(`Événement de support: ${event}`, data);
    // Envoyer vers votre système d'analyse/journalisation
  }

  private getSessionDuration(): number {
    // Calculer la durée de la session
    return 0; // Espace réservé
  }
}
```

## Meilleures pratiques

### Gestion des erreurs et solutions de secours

```typescript theme={null}
const voiceSupport = {
  async startWithFallback() {
    try {
      return await this.voiceSDK.startVoiceConversation(options);
    } catch (error) {
      console.warn('Voix échouée, utilisation du chat texte comme solution de secours:', error);
      
      // Solution de secours : chat texte uniquement
      return await this.chatSDK.createChat('Chat support (texte)');
    }
  }
};
```

### Gestion des ressources

```typescript theme={null}
class VoiceManager {
  private activeSessions = new Set<string>();

  async startSession(options: any) {
    const sessionId = await this.voiceSDK.startVoiceConversation(options);
    this.activeSessions.add(sessionId);
    return sessionId;
  }

  async cleanup() {
    // Terminer toutes les sessions actives
    for (const sessionId of this.activeSessions) {
      try {
        await this.voiceSDK.endVoiceSession(sessionId);
      } catch (error) {
        console.warn('Impossible de terminer la session:', sessionId, error);
      }
    }
    this.activeSessions.clear();
  }
}
```

### Optimisation des performances

```typescript theme={null}
// Utiliser React.memo pour les composants de visualisation audio
const AudioVisualizer = React.memo(({ getInputData, isActive }) => {
  // Ralentir les mises à jour d'animation
  const throttledAnimate = useCallback(
    throttle(() => {
      // Logique d'animation
    }, 16), // ~60fps
    []
  );
  
  // ... logique du composant
});
```

### Accessibilité

```typescript theme={null}
function VoiceAccessibleChat() {
  const [transcript, setTranscript] = useState('');
  
  const { startSession } = useVoiceConversation({
    callbacks: {
      onTranscription: (text, isFinal) => {
        setTranscript(text);
        
        // Mettre à jour le lecteur d'écran
        if (isFinal) {
          announceToScreenReader(`Vous avez dit: ${text}`);
        }
      }
    }
  });

  return (
    <div>
      <button 
        aria-label="Démarrer la conversation vocale"
        onClick={startSession}
      >
        🎤 Démarrer le chat vocal
      </button>
      
      <div 
        aria-live="polite"
        aria-label="Transcription vocale"
      >
        {transcript}
      </div>
    </div>
  );
}
```
