Die Verbindung von LLMs mit Voice Output ist das Herzstück jedes Voice Agents. Die Herausforderung: Wie schafft man eine Pipeline, die natürlich klingt, schnell reagiert und skaliert? Hier lernen Sie die Architektur und Optimierung der LLM-to-Voice-Pipeline.
Audio Input ──→ ASR ──→ Text ──→ LLM ──→ Response Text ──→ TTS ──→ Audio Output
(Nutzer) (STT) (Brain) (Voice) (Nutzer)
// SCHLECHT: Sequentiell — wartet auf komplette LLM-Antwort
const transcript = await elevenlabs.speechToText(audioInput)
const llmResponse = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: transcript }],
})
const audio = await elevenlabs.textToSpeech.convert(voiceId, {
text: llmResponse.choices[0].message.content,
})
// Gesamtlatenz: 2.000–4.000 ms
// GUT: Streaming — LLM-Tokens direkt an TTS weiterleiten
const transcript = await elevenlabs.speechToText(audioInput)
// LLM Streaming starten
const stream = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: transcript }],
stream: true,
})
// TTS WebSocket öffnen
const ttsWs = new WebSocket(
`wss://api.elevenlabs.io/v1/text-to-speech/${voiceId}/stream-input`
)
let buffer = ''
for await (const chunk of stream) {
const token = chunk.choices[0]?.delta?.content || ''
buffer += token
// Satz-Erkennung: Bei Satzende an TTS senden
if (buffer.match(/[.!?]\s/)) {
ttsWs.send(JSON.stringify({ text: buffer }))
buffer = ''
}
}
// Gesamtlatenz: 500–1.000 ms bis zum ersten Audio
| Phase | Ziel | Optimierung |
|---|---|---|
| ASR | < 300 ms | Streaming STT, Voice Activity Detection |
| LLM TTFT | < 500 ms | Modellwahl, Prompt-Caching |
| TTS | < 300 ms | Turbo-Modell, Streaming |
| Netzwerk | < 100 ms | Regionale Endpoints, WebSocket |
| Gesamt | < 1.200 ms | End-to-End-Optimierung |
1. LLM-Latenz reduzieren:
2. ASR-Latenz reduzieren:
3. TTS-Latenz reduzieren:
4. Netzwerk-Latenz reduzieren:
Die effektivste Strategie: LLM-Output in Sätze aufteilen und jeden Satz sofort an TTS senden:
LLM Token 1: "Ich"
LLM Token 2: "kann"
LLM Token 3: "Ihnen"
LLM Token 4: "helfen." ← Satzende erkannt!
→ Satz an TTS senden: "Ich kann Ihnen helfen."
→ Audio wird generiert während LLM den nächsten Satz produziert
function detectSentenceEnd(buffer: string): boolean {
// Einfache Heuristik
return /[.!?]\s/.test(buffer) || buffer.length > 200
}
// Erweitert: Auch Komma-Pausen für natürlicheres Sprechen
function detectPausePoint(buffer: string): boolean {
return /[.!?,;:]\s/.test(buffer) || buffer.length > 150
}
Der Voice Agent passt seine Stimme an den Kontext an:
| Kontext | Voice Settings |
|---|---|
| Begrüßung | stability: 0.6, style: 0.4 (freundlich, warm) |
| Technische Erklärung | stability: 0.8, style: 0.1 (klar, sachlich) |
| Entschuldigung | stability: 0.7, style: 0.3 (empathisch) |
| Verabschiedung | stability: 0.5, style: 0.5 (warm, persönlich) |
function getVoiceSettings(context: ConversationContext) {
if (context.intent === 'complaint') {
return { stability: 0.7, similarity_boost: 0.8, style: 0.3 }
}
if (context.intent === 'technical_support') {
return { stability: 0.8, similarity_boost: 0.8, style: 0.1 }
}
// Default: freundlich und natürlich
return { stability: 0.5, similarity_boost: 0.75, style: 0.3 }
}
Praxis-Tipp: Die wichtigste Optimierung ist Sentence-Level Streaming. Ohne Streaming wartet der Nutzer 2–4 Sekunden auf eine Antwort — mit Streaming hört er die ersten Worte nach 500–800 ms. Das ist der Unterschied zwischen "fühlt sich wie ein Roboter an" und "fühlt sich wie ein Gespräch an".