Zum Hauptinhalt springen
Lektion 15 von 18 · Realtime API und Voice Agents

Telefonie-Integration (Twilio, etc.)

Lektion 15 von 18 Aktualisiert am 3. November 2026 Entwickler
Auf dieser Seite
  1. Telefonie-Integration (Twilio, etc.)
  2. Telefonie-Architektur
  3. Implementierung mit Twilio
  4. Alternativen zu Twilio
  5. Kernaussagen

Aktualisiert am 3. November 2026 basierend auf der Realtime API-Dokumentation: Das G.711 μ-law-Format heißt audio/pcmu (früher wurde im Text g711_ulaw zitiert, was der Beta-Name war). Quelle: Realtime API.

Aktualisierung vom 2. November 2026 — Audio-Modelle. Mehrere Modelle in diesem Kurs sind veraltet: tts-1, tts-1-hd und gpt-4o-mini-tts werden am 6. Januar 2027 nicht mehr funktionieren (die angegebene Alternative ist gpt-realtime-2.1-mini, die laut OpenAI-TTS-Leitfaden nicht über /v1/audio/speech unterstützt wird: Die Migration der Sprachsynthese muss über die Realtime API erfolgen); gpt-realtime, gpt-4o-realtime und veraltete Audio-Modelle am 20. Januar 2027 (gpt-realtime-2.1, gpt-realtime-2.1-mini, gpt-audio-1.5); whisper-1, gpt-4o-transcribe und /v1/audio/translations am 26. Februar 2027 (gpt-transcribe, gpt-live-transcribe, v1/realtime/translations). Für Voll-Duplex-Stimme ist GPT-Live 1 seit dem 10. September 2026 in der API verfügbar.

Telefonie-Integration (Twilio, etc.)

Ein Voice-Agent wird erst dann wirklich nützlich, wenn er über das Telefon erreichbar ist. Cloud-Telefonie-Plattformen wie Twilio, LiveKit und Daily ermöglichen es Ihnen, die Realtime API mit dem weltweiten Telefonnetz zu verbinden. Ein Nutzer wählt eine Nummer, und Ihr Agent antwortet in Echtzeit.

Telefonie-Architektur

Die Telefonie-Integration fügt eine Schicht zwischen dem Telefonnetz und der Realtime API ein:

1

Eingehender Anruf → Twilio

Der Nutzer wählt eine Telefonnummer. Twilio empfängt den Anruf und sendet ein Webhook an Ihren Server.

2

Ihr Server → Media Stream

Ihr Server antwortet mit TwiML-Anweisungen, die einen bidirektionalen Media-Stream-WebSocket öffnen.

3

Media Stream ↔ Realtime API

Ihr Server leitet Audio zwischen dem Twilio Media Stream und der OpenAI Realtime API weiter.

4

Stimmenantwort → Nutzer

Das Antwort-Audio von der Realtime API wird über Twilio zurück an das Telefon des Nutzers gesendet.

Implementierung mit Twilio

Webhook für eingehende Anrufe

Wenn ein Anruf eingeht, sendet Twilio eine HTTP-Anfrage an Ihren Server. Sie antworten mit TwiML, das einen Media Stream öffnet:

from fastapi import FastAPI, Request
from fastapi.responses import Response

app = FastAPI()

@app.post("/incoming-call")
async def incoming_call(request: Request):
    """Twilio-Webhook für eingehende Anrufe."""
    twiml = """<?xml version="1.0" encoding="UTF-8"?>
    <Response>
        <Say language="en-US">
            Willkommen bei Corsen AI. Wir verbinden Sie mit Ihrem Sprachassistenten.
        </Say>
        <Connect>
            <Stream url="wss://your-server.com/media-stream">
                <Parameter name="caller" value="{caller_number}" />
            </Stream>
        </Connect>
    </Response>"""

    form_data = await request.form()
    caller = form_data.get("From", "unknown")
    twiml = twiml.replace("{caller_number}", caller)

    return Response(content=twiml, media_type="application/xml")

Die Brücke Media Stream ↔ Realtime API

Der WebSocket-Server empfängt Audio von Twilio und leitet es an die Realtime API weiter:

from fastapi import WebSocket
import websockets
import json
import base64
import audioop
import asyncio

OPENAI_API_KEY = "sk-..."
REALTIME_URL = "wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1"

@app.websocket("/media-stream")
async def media_stream(twilio_ws: WebSocket):
    """Brücke zwischen Twilio Media Stream und der Realtime API."""
    await twilio_ws.accept()

    # Verbindung zur Realtime API herstellen
    headers = {
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }

    async with websockets.connect(REALTIME_URL, additional_headers=headers) as openai_ws:
        await openai_ws.recv()  # session.created

        # Sitzung konfigurieren
        await openai_ws.send(json.dumps({
            "type": "session.update",
            "session": {
                "type": "realtime",
                "output_modalities": ["audio"],
                "instructions": "Sie sind ein Telefon-Assistent. "
                                "Antworten Sie auf Englisch, knapp.",
                "audio": {
                    "input": {
                        "format": {"type": "audio/pcmu"},
                        "turn_detection": {
                            "type": "server_vad",
                            "threshold": 0.5,
                            "silence_duration_ms": 600
                        }
                    },
                    "output": {
                        "format": {"type": "audio/pcmu"},
                        "voice": "marin"
                    }
                }
            }
        }))
        await openai_ws.recv()

        stream_sid = None

        async def twilio_to_openai():
            nonlocal stream_sid
            async for message in twilio_ws.iter_text():
                data = json.loads(message)

                if data["event"] == "media":
                    audio_b64 = data["media"]["payload"]
                    await openai_ws.send(json.dumps({
                        "type": "input_audio_buffer.append",
                        "audio": audio_b64
                    }))

                elif data["event"] == "start":
                    stream_sid = data["start"]["streamSid"]

        async def openai_to_twilio():
            async for message in openai_ws:
                event = json.loads(message)

                if event["type"] == "response.output_audio.delta":
                    await twilio_ws.send_json({
                        "event": "media",
                        "streamSid": stream_sid,
                        "media": {
                            "payload": event["delta"]
                        }
                    })

        await asyncio.gather(twilio_to_openai(), openai_to_twilio())

G.711-Audioformat

Die Telefonie verwendet das G.711 μ-law-Format (8 kHz, ein Byte pro Sample). Die Realtime API unterstützt dies nativ unter dem Namen audio/pcmu, den Sie sowohl für die Eingabe als auch für die Ausgabe deklarieren (audio.input.format und audio.output.format, wie im obigen Code). Dies vermeidet jegliche serverseitige Konvertierung. Der Name g711_ulaw gehörte zur API-Beta; das äquivalente A-law-Format heißt audio/pcma.

Alternativen zu Twilio

Plattform Stärke Integration mit Realtime API
Twilio Komplettes Ökosystem, Nummern in über 100 Ländern Native WebSocket Media Streams
LiveKit Open Source, geringe Latenz, WebRTC Offizielles OpenAI-Plugin
Daily Einfach, gehostet, gut für Prototypen Pipecat SDK mit Realtime-Connector

Kernaussagen

  • Twilio Media Streams ermöglichen die Verbindung eines Telefonanrufs mit einem bidirektionalen WebSocket.
  • Ihr Server fungiert als Brücke zwischen dem Twilio Media Stream und der OpenAI Realtime API.
  • Das G.711 μ-law-Format ist für die Telefonie nativ und wird direkt von der Realtime API unterstützt.
  • LiveKit (Open Source, WebRTC) und Daily (gehostet) sind lebensfähige Alternativen zu Twilio.
  • Die Architektur ist immer dieselbe: Telefonie → Ihr Server → Realtime API.