> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# WebSocket

> **Note**
>
> Diese Dokumentation richtet sich an Entwickler, die direkt die ElevenLabs WebSocket API integrieren. Der Einfachheit halber
> empfehlen wir die [offiziellen SDKs von ElevenLabs](/docs/de/eleven-agents/libraries/python).

Die [ElevenAgents](https://elevenlabs.io/agents) WebSocket API ermöglicht Echtzeit-, interaktive Sprachgespräche mit KI-Agenten. Durch eine WebSocket-Verbindung können Sie Audioeingaben senden und Audioantworten in Echtzeit empfangen. So entstehen realistische Gesprächserlebnisse.

> **Note**
>
> Endpunkt: `wss://api.elevenlabs.io/v1/convai/conversation?agent_id={agent_id}`

## Authentifizierung

### Agent-ID verwenden

Bei öffentlichen Agenten können Sie die `agent_id` direkt in der WebSocket-URL verwenden, ohne zusätzliche Authentifizierung:

```bash
wss://api.elevenlabs.io/v1/convai/conversation?agent_id=<your-agent-id>
```

### Signierte URL verwenden

Für private Agenten oder Gespräche, die eine Autorisierung erfordern, rufen Sie von Ihrem Server eine signierte URL ab. Dieser kommuniziert über Ihren API-Schlüssel sicher mit der ElevenLabs API.

### Beispiel mit cURL

**Anfrage:**

```bash
curl -X GET "https://api.elevenlabs.io/v1/convai/conversation/get-signed-url?agent_id=<your-agent-id>" \
     -H "xi-api-key: <your-api-key>"
```

**Antwort:**

```json
{
  "signed_url": "wss://api.elevenlabs.io/v1/convai/conversation?agent_id=<your-agent-id>&token=<token>"
}
```

> **Warning**
>
> Geben Sie Ihren ElevenLabs API-Schlüssel niemals clientseitig preis.

## WebSocket-Ereignisse

### Ereignisse vom Client zum Server

Der Client kann folgende Ereignisse an den Server senden:

#### Kontextuelle Aktualisierungen

Senden Sie nicht unterbrechende Kontextinformationen, um den Gesprächsstatus zu aktualisieren. So können Sie zusätzlichen Kontext bereitstellen, ohne den laufenden Gesprächsfluss zu stören.

```javascript
{
  "type": "contextual_update",
  "text": "User clicked on pricing page"
}
```

**Anwendungsfälle:**

* Nutzerstatus oder Präferenzen aktualisieren
* Umgebungskontext bereitstellen
* Hintergrundinformationen hinzufügen
* Interaktionen mit der Benutzeroberfläche verfolgen

**Wichtige Punkte:**

* Unterbricht den aktuellen Gesprächsfluss nicht
* Aktualisierungen werden als Tool-Aufrufe in den Gesprächsverlauf aufgenommen
* Hilft, den Kontext zu wahren, ohne den natürlichen Dialog zu unterbrechen

> **Note**
>
> Kontextuelle Aktualisierungen werden asynchron verarbeitet und erfordern keine direkte Antwort vom Server.

#### [WebSocket API-Referenz](/docs/de/eleven-agents/api-reference/eleven-agents/websocket)

In der WebSocket API-Referenz für ElevenLabs Agents finden Sie detaillierte Nachrichtenstrukturen,
Parameter und Beispiele.

## Implementierungsbeispiel für Next.js

Dieses Beispiel zeigt, wie Sie einen WebSocket-basierten Client für einen Gesprächsagenten in Next.js mit der ElevenLabs WebSocket API implementieren.

> **Note**
>
> Dieses Beispiel verwendet zwar das Paket `voice-stream` zur Verarbeitung von Mikrofoneingaben, Sie können jedoch
> auch eine eigene Lösung zum Erfassen und Kodieren von Audio implementieren. Der Schwerpunkt liegt hier auf der Demonstration
> der WebSocket-Verbindung und Ereignisverarbeitung mit der ElevenLabs API.

#### Erforderliche Abhängigkeiten installieren

Installieren Sie zuerst die erforderlichen Pakete:

```bash
npm install voice-stream
```

Das Paket `voice-stream` verarbeitet Mikrofonzugriff und Audio-Streaming und kodiert das Audio automatisch im von der ElevenLabs API benötigten Base64-Format.

> **Note**
>
> Dieses Beispiel verwendet Tailwind CSS für das Styling. So fügen Sie Tailwind Ihrem Next.js-Projekt hinzu:
>
> ```bash
> npm install -D tailwindcss postcss autoprefixer
> npx tailwindcss init -p
> ```
>
> Folgen Sie anschließend der [offiziellen Tailwind-CSS-Einrichtungsanleitung für Next.js](https://tailwindcss.com/docs/guides/nextjs).
>
> Alternativ können Sie die className-Attribute durch eigene CSS-Stile ersetzen.

#### WebSocket-Typen erstellen

Definieren Sie die Typen für WebSocket-Ereignisse:

**`app/types/websocket.ts`**

```typescript app/types/websocket.ts
type BaseEvent = {
  type: string;
};

type UserTranscriptEvent = BaseEvent & {
  type: "user_transcript";
  user_transcription_event: {
    user_transcript: string;
  };
};

type AgentResponseEvent = BaseEvent & {
  type: "agent_response";
  agent_response_event: {
    agent_response: string;
  };
};

type AgentResponseCorrectionEvent = BaseEvent & {
  type: "agent_response_correction";
  agent_response_correction_event: {
    original_agent_response: string;
    corrected_agent_response: string;
  };
};

type AudioResponseEvent = BaseEvent & {
  type: "audio";
  audio_event: {
    audio_base_64: string;
    event_id: number;
    alignment: {
      chars: string[];
      char_durations_ms: number[];
      char_start_times_ms: number[];
    };
  };
};

type InterruptionEvent = BaseEvent & {
  type: "interruption";
  interruption_event: {
    reason: string;
  };
};

type PingEvent = BaseEvent & {
  type: "ping";
  ping_event: {
    event_id: number;
    ping_ms?: number;
  };
};

type AgentChatResponsePartEvent = BaseEvent & {
  type: "agent_chat_response_part";
  text_response_part: {
    type: "start" | "delta" | "stop";
    text: string;
    event_id: number;
    response_id: string;
  };
};

export type ElevenLabsWebSocketEvent =
  | UserTranscriptEvent
  | AgentResponseEvent
  | AgentResponseCorrectionEvent
  | AudioResponseEvent
  | InterruptionEvent
  | PingEvent
  | AgentChatResponsePartEvent;
```

#### WebSocket-Hook erstellen

Erstellen Sie einen benutzerdefinierten Hook zur Verwaltung der WebSocket-Verbindung:

**`app/hooks/useAgentConversation.ts`**

```typescript app/hooks/useAgentConversation.ts
'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { useVoiceStream } from 'voice-stream';
import type { ElevenLabsWebSocketEvent } from '../types/websocket';

const sendMessage = (websocket: WebSocket, request: object) => {
  if (websocket.readyState !== WebSocket.OPEN) {
    return;
  }
  websocket.send(JSON.stringify(request));
};

export const useAgentConversation = () => {
  const websocketRef = useRef<WebSocket>(null);
  const [isConnected, setIsConnected] = useState<boolean>(false);

  const { startStreaming, stopStreaming } = useVoiceStream({
    onAudioChunked: (audioData) => {
      if (!websocketRef.current) return;
      sendMessage(websocketRef.current, {
        user_audio_chunk: audioData,
      });
    },
  });

  const startConversation = useCallback(async () => {
    if (isConnected) return;

    const websocket = new WebSocket("wss://api.elevenlabs.io/v1/convai/conversation");

    websocket.onopen = async () => {
      setIsConnected(true);
      sendMessage(websocket, {
        type: "conversation_initiation_client_data",
      });
      await startStreaming();
    };

    websocket.onmessage = async (event) => {
      const data = JSON.parse(event.data) as ElevenLabsWebSocketEvent;

      // Handle ping events to keep connection alive
      if (data.type === "ping") {
        setTimeout(() => {
          sendMessage(websocket, {
            type: "pong",
            event_id: data.ping_event.event_id,
          });
        }, data.ping_event.ping_ms);
      }

      if (data.type === "user_transcript") {
        const { user_transcription_event } = data;
        console.log("User transcript", user_transcription_event.user_transcript);
      }

      if (data.type === "agent_response") {
        const { agent_response_event } = data;
        console.log("Agent response", agent_response_event.agent_response);
      }

      if (data.type === "agent_response_correction") {
        const { agent_response_correction_event } = data;
        console.log("Agent response correction", agent_response_correction_event.corrected_agent_response);
      }

      if (data.type === "interruption") {
        // Handle interruption
      }

      if (data.type === "audio") {
        const { audio_event } = data;
        // Implement your own audio playback system here
        // Note: You'll need to handle audio queuing to prevent overlapping
        // as the WebSocket sends audio events in chunks
      }

      if (data.type === "agent_chat_response_part") {
        const { text_response_part } = data;
        const { type: partType, text, response_id } = text_response_part;
        // Handle the agent's response text as it is generated. Enable
        // agent_chat_response_part in the agent's client_events to receive
        // this during voice conversations.
        console.log("Chat response part:", partType, text, response_id);
      }
    };

    websocketRef.current = websocket;

    websocket.onclose = async () => {
      websocketRef.current = null;
      setIsConnected(false);
      stopStreaming();
    };
  }, [startStreaming, isConnected, stopStreaming]);

  const stopConversation = useCallback(async () => {
    if (!websocketRef.current) return;
    websocketRef.current.close();
  }, []);

  useEffect(() => {
    return () => {
      if (websocketRef.current) {
        websocketRef.current.close();
      }
    };
  }, []);

  return {
    startConversation,
    stopConversation,
    isConnected,
  };
};
```

#### Gesprächskomponente erstellen

Erstellen Sie eine Komponente, die den WebSocket-Hook verwendet:

**`app/components/Conversation.tsx`**

```typescript app/components/Conversation.tsx
'use client';

import { useCallback } from 'react';
import { useAgentConversation } from '../hooks/useAgentConversation';

export function Conversation() {
  const { startConversation, stopConversation, isConnected } = useAgentConversation();

  const handleStart = useCallback(async () => {
    try {
      await navigator.mediaDevices.getUserMedia({ audio: true });
      await startConversation();
    } catch (error) {
      console.error('Failed to start conversation:', error);
    }
  }, [startConversation]);

  return (
    <div className="flex flex-col items-center gap-4">
      <div className="flex gap-2">
        <button
          onClick={handleStart}
          disabled={isConnected}
          className="px-4 py-2 bg-blue-500 text-white rounded disabled:bg-gray-300"
        >
          Start Conversation
        </button>
        <button
          onClick={stopConversation}
          disabled={!isConnected}
          className="px-4 py-2 bg-red-500 text-white rounded disabled:bg-gray-300"
        >
          Stop Conversation
        </button>
      </div>
      <div className="flex flex-col items-center">
        <p>Status: {isConnected ? 'Connected' : 'Disconnected'}</p>
      </div>
    </div>
  );
}
```

## Nächste Schritte

1. **Audiowiedergabe**: Implementieren Sie ein eigenes Audiowiedergabesystem mit der Web Audio API oder einer Bibliothek. Berücksichtigen Sie die Audiowarteschlange, um Überlappungen zu vermeiden, da WebSocket Audioereignisse in Blöcken sendet.
2. **Fehlerbehandlung**: Fügen Sie Wiederholungslogik und Mechanismen zur Fehlerbehebung hinzu
3. **UI-Feedback**: Fügen Sie visuelle Anzeigen für Sprachaktivität und Verbindungsstatus hinzu

## Latenzmanagement

Für reibungslose Gespräche implementieren Sie diese Strategien:

* **Adaptives Buffering:** Passen Sie die Audiopufferung an die Netzwerkbedingungen an.
* **Jitter-Puffer:** Implementieren Sie einen Jitter-Puffer, um Schwankungen bei den Paketankunftszeiten auszugleichen.
* **Ping-Pong-Überwachung:** Verwenden Sie Ping- und Pong-Ereignisse, um die Round-Trip-Zeit zu messen und entsprechend anzupassen.

## Sicherheits-Best-Practices

* Rotieren Sie API-Schlüssel regelmäßig und speichern Sie sie in Umgebungsvariablen.
* Implementieren Sie Ratenbegrenzungen, um Missbrauch zu verhindern.
* Erklären Sie klar den Zweck, wenn Sie Nutzer um Mikrofonzugriff bitten.
* Optimierte Blockbildung: Passen Sie die Dauer der Audioblöcke an, um Latenz und Effizienz auszubalancieren.

## Zusätzliche Ressourcen

* [ElevenLabs Agents-Dokumentation](/docs/de/eleven-agents/overview)
* [ElevenLabs Agents SDKs](/docs/de/eleven-agents/libraries/python)