Unterbrechungen und Sprechwechsel-Management
Auf dieser Seite
Aktualisiert am 2. November 2026 — Audio-Modelle. Mehrere Modelle in diesem Kurs wurden eingestellt:
tts-1,tts-1-hdundgpt-4o-mini-ttswerden am 6. Januar 2027 nicht mehr funktionieren (Ersatz:gpt-realtime-2.1-mini, wobei die OpenAI-TTS-Richtlinien angeben, dass dies nicht durch/v1/audio/speechunterstützt wird: Die Migration der Spracherstellung erfolgt über die Realtime API);gpt-realtime,gpt-4o-realtimeund Legacy-Audiomodelle am 20. Januar 2027 (gpt-realtime-2.1,gpt-realtime-2.1-mini,gpt-audio-1.5);whisper-1,gpt-4o-transcribeund/v1/audio/translationsam 26. Februar 2027 (gpt-transcribe,gpt-live-transcribe,v1/realtime/translations). Für die Voll-Duplex-Stimme ist GPT-Live 1 seit dem 10. September 2026 in der API verfügbar.
Korrigiert am 3. November 2026.
session.update-Ereignisse platzierten zuvorturn_detectionam Session-Wurzel, ein Format aus der alten Beta: Mit der aktuellen Realtime API befindet sich die Einstellung insession.audio.input.turn_detection, und die Session trägt"type": "realtime". Die Behandlung von Unterbrechungen sandte zuvorresponse.cancel, aber mit VAD storniert der Server die Antwort selbst, und der Code verwendete eine undefinierte Variable. Diese Lektion behandelt nunsemantic_vad,create_responseundinterrupt_responseund unterscheidet zwischen WebSocket und WebRTC. Die Ereignisformen wurden gegenopenaiSDK-Typen 3.42.1 verifiziert. Quellen: Sprachaktivitätserkennung · Realtime-Gespräche.
Unterbrechungen und Sprechwechsel-Management
In natürlichen Gesprächen unterbrechen sich Menschen, sprechen übereinander und unterbrechen sich gegenseitig. Eine Sprach-Agentur, die diese Situationen nicht bewältigen kann, wirkt roboterhaft und frustrierend. Die Realtime API bietet zwei Mechanismen zur Verwaltung des Sprechwechsels: automatische Sprachaktivitätserkennung (VAD) und manuelle Steuerung.
Sprachaktivitätserkennung (VAD)
VAD ist in einer Sprach-Session standardmäßig aktiviert und arbeitet im Modus server_vad: Der Server analysiert eingehende Audioinhalte kontinuierlich, segmentiert basierend auf Stille und signalisiert den Beginn und das Ende der Benutzerrede. Sie konfigurieren dies in session.audio.input.turn_detection:
await ws.send(json.dumps({
"type": "session.update",
"session": {
"type": "realtime",
"audio": {
"input": {
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 300,
"silence_duration_ms": 500,
"create_response": True, # sofort antworten, wenn der Sprechwechsel endet
"interrupt_response": True, # Agent unterbrechen, wenn der Benutzer spricht
}
}
},
},
}))
VAD-Parameter
| Parameter | Beschreibung | Auswirkung |
|---|---|---|
| threshold | Erkennungsschwelle (0,0 bis 1,0) | Hoch = weniger empfindlich, Niedrig = empfindlicher |
| prefix_padding_ms | Vor dem Erkennungspunkt beibehaltene Audioinhalte | Verhindert das Abschneiden von Wortanfängen |
| silence_duration_ms | Benötigte Stillezeit zum Beenden des Sprechwechsels | Kurz = reaktionsschnell, Lang = geduldig |
Eine zu kurze silence_duration_ms löst eine Antwort während natürlicher Pausen in der Rede des Benutzers aus; zu lang wirkt die Agentur unreaktiv. OpenAI veröffentlicht keine sprachspezifischen Standards: Beginnen Sie mit dem Dokumentationsbeispiel (500 ms) und passen Sie es basierend auf Aufnahmen Ihrer Benutzer an. Ein höherer threshold erfordert lauterer Ton zur Auslösung, was in lauten Umgebungen hilft.
Semantische VAD
Der zweite Modus, semantic_vad, stützt sich nicht auf Stille, sondern auf Wörter: Ein Klassifizierer schätzt, ob der Benutzer seinen Satz beendet hat. Ein unvollständiger Satz gewinnt mehr Zeit als eine klare Aussage, und das Modell unterbricht seltener. Die Einstellung eagerness kann low (lassen Sie den Benutzer seine Zeit), medium, high (sofort antworten) oder auto, der Standardwert, der äquivalent zu medium ist:
await ws.send(json.dumps({
"type": "session.update",
"session": {
"type": "realtime",
"audio": {"input": {"turn_detection": {"type": "semantic_vad", "eagerness": "low"}}},
},
}))
Behandlung von Unterbrechungen
Wenn der Benutzer spricht, während die Agentur antwortet, sendet der Server input_audio_buffer.speech_started. Mit VAD und interrupt_response aktiviert storniert der Server die aktuelle Antwort: Er sendet dann response.done mit dem Status cancelled. Sie müssen dennoch zwei Dinge auf Ihrer Seite tun, auf einer WebSocket-Verbindung, auf der Sie das Audio abspielen:
- Spielen Sie sofort ab und werfen Sie jedes gepufferte Audio weg, wobei Sie notieren, wie viele Millisekunden der Benutzer tatsächlich gehört hat
- Kürzen Sie den Agenten-Item auf diese Dauer unter Verwendung von
conversation.item.truncate
Warten Sie nicht auf response.done, um eines der beiden zu tun.
async def handle_interruption(ws, event: dict, player, item_id: str | None, ms_played: int) -> None:
"""Behandelt Benutzerrede, während die Agentur spricht (WebSocket)."""
if event["type"] != "input_audio_buffer.speech_started":
return
# 1. Abspielung stoppen und gepuffertes Audio löschen
player.stop_stream()
# 2. Den Teil aus der Historie entfernen, den der Benutzer nicht gehört hat
if item_id:
await ws.send(json.dumps({
"type": "conversation.item.truncate",
"item_id": item_id,
"content_index": 0,
"audio_end_ms": ms_played,
}))
# 3. Abspielung für die nächste Antwort neu öffnen
player.start_stream()
Berechnen Sie ms_played basierend darauf, was Sie tatsächlich an den Lautsprecher gesendet haben: Bei 16-Bit Mono PCM mit 24 kHz entsprechen 48.000 Bytes einer Sekunde. Bei WebRTC oder SIP verwaltet der Server selbst den Ausgabepuffer, weiß, was abgespielt wurde, und kürzt automatisch: Sie müssen nichts senden.
Warum die Antwort kürzen?
Ohne Kürzung würde die Gesprächshistorie die vollständige Antwort des Modells enthalten, obwohl der Benutzer nur einen Teil gehört hat. Wenn der Benutzer fragt: „Was hast du zuletzt gesagt?“, würde das Modell denken, es hätte alles gesagt. Durch Kürzen wird die Historie mit dem abgehörten Inhalt des Benutzers abgeglichen. Die Dokumentation weist auf eine Einschränkung hin: Die Kürzung schneidet das Audio und entfernt die Transkription des nicht abgespielten Teils, bietet aber keine wortgenaue gekürzte Transkription.
Manueller Steuerungsmodus
Für bestimmte Anwendungsfälle (IVR-Menüs, Diktiergeräte, Quiz) ist automatische VAD nicht geeignet. Der manuelle Modus gibt Ihnen volle Kontrolle:
# VAD deaktivieren
await ws.send(json.dumps({
"type": "session.update",
"session": {"type": "realtime", "audio": {"input": {"turn_detection": None}}},
}))
# Taste gedrückt: Wenn die Agentur noch spricht, stornieren Sie ihre Antwort und kürzen Sie das nicht abgespielte Audio
await ws.send(json.dumps({"type": "response.cancel"}))
# Taste losgelassen: Audio wurde über input_audio_buffer.append gesendet, commit den Sprechwechsel...
await ws.send(json.dumps({"type": "input_audio_buffer.commit"}))
# ...dann die Antwort auslösen
await ws.send(json.dumps({"type": "response.create"}))
Ohne VAD ist nichts automatisch: Hier kommt response.cancel ins Spiel, wenn eine Antwort im Gange ist, während der Benutzer die Kontrolle wieder übernimmt. Zwischen den Sprechwechseln leert input_audio_buffer.clear den Eingabepuffer.
Es gibt einen Mittelweg: Lassen Sie VAD aktiviert, damit es weiterhin Sprechwechsel segmentiert und Ereignisse sendet, aber setzen Sie create_response und interrupt_response auf False. Ohne Ihre explizite response.create wird keine Antwort gesendet, was Ihnen Zeit gibt, den Input zu überprüfen oder zu bereichern (Moderation, Dokumentenabruf), zum Preis einer gewissen Latenz.
Anwendungsfälle für den manuellen Modus
- IVR-Menü: Warten Sie auf einen DTMF-Ton oder ein bestimmtes Schlüsselwort, bevor Sie antworten
- Diktat: Akkumulieren Sie lange Audiosegmente ohne Unterbrechung
- Bestätigung: Warten Sie auf eine explizite „Ja” oder „Nein”
- Push-to-talk: Der Benutzer drückt eine Taste, um zu sprechen
Architektur des Zustandsmanagements
Für ein robustes Sprechwechsel-Management pflegen Sie einen Zustandsautomaten:
from enum import Enum
class ConversationState(Enum):
IDLE = "idle" # Warten
USER_SPEAKING = "user_speaking" # Benutzer spricht
PROCESSING = "processing" # Modell verarbeitet
AGENT_SPEAKING = "agent_speaking" # Agentur antwortet
INTERRUPTED = "interrupted" # Unterbrechung im Gange
class TurnManager:
def __init__(self):
self.state = ConversationState.IDLE
self.current_response_item_id = None
self.played_audio_ms = 0
def on_event(self, event_type: str):
if event_type == "input_audio_buffer.speech_started":
if self.state == ConversationState.AGENT_SPEAKING:
self.state = ConversationState.INTERRUPTED
else:
self.state = ConversationState.USER_SPEAKING
elif event_type == "input_audio_buffer.speech_stopped":
self.state = ConversationState.PROCESSING
elif event_type == "response.output_audio.delta":
self.state = ConversationState.AGENT_SPEAKING
elif event_type == "response.done":
self.state = ConversationState.IDLE
Kernaussagen
- VAD (
server_vadstandardmäßig) wird insession.audio.input.turn_detectionkonfiguriert semantic_vadsegmentiert basierend auf Bedeutung;eagernesssteuert seine Geduld- Mit VAD storniert der Server die unterbrochene Antwort; auf WebSocket stoppen Sie die Abspielung und kürzen mit
conversation.item.truncate(automatisch bei WebRTC und SIP) - Der manuelle Modus (
turn_detectionaufNonegesetzt) eignet sich für Push-to-talk, IVR-Menüs und Diktat - Ein expliziter Zustandsautomat verhindert inkonsistentes Verhalten in Grenzfällen