Tune Inworld TTS: temperature, text normalization, emotional register mapping

Changes to backend/services/tts.py:
- Add temperature: 0.9 and applyTextNormalization: "ON" to Inworld payload
  (text normalization auto-speaks "$5,432", "Dr.", phone numbers, dates, etc.)
- Add _emotional_register_to_params() mapping caller's emotional_register
  to (temperature, speed_adjust) across 5 families: sadness/grief,
  anger/aggression, manic/excited, nervous/earnest, gruff/restrained.
- generate_speech_inworld() and generate_speech() now accept optional
  emotional_register kwarg; all providers take it via the dispatch lambdas
  (only inworld uses it; others ignore)
- Clamp speed to 0.5-1.5 after both emotional-register and per-text adjustments

In backend/main.py: plumb emotional_register through the two caller-dialog
TTS calls (auto-respond and ai-respond) by reading from the slim caller
background dict. Devon and cohost/announcer calls pass empty string and
hit the default (0.9, 0.0) branch — no behavior change.
This commit is contained in:
2026-04-05 14:54:15 -06:00
parent 9e37fbf124
commit 4e28f3fb84
2 changed files with 53 additions and 16 deletions
+8 -2
View File
@@ -4141,9 +4141,12 @@ async def _trigger_ai_auto_respond(accumulated_text: str):
broadcast_chat(ai_name, response)
broadcast_event("ai_status", {"text": f"{ai_name} is speaking..."})
_caller_bg = session.caller_backgrounds.get(session.current_caller_key) or {}
_emotional_register = _caller_bg.get("emotional_register", "") if isinstance(_caller_bg, dict) else ""
try:
audio_bytes = await generate_speech(response, session.caller["voice"], "none",
provider_override=session.caller.get("tts_provider"))
provider_override=session.caller.get("tts_provider"),
emotional_register=_emotional_register)
except Exception as e:
print(f"[Auto-Respond] TTS failed: {e}")
broadcast_event("ai_done")
@@ -4253,11 +4256,14 @@ async def ai_respond():
ai_name = caller["name"]
ai_voice = caller["voice"]
ai_tts_provider = caller.get("tts_provider")
_caller_bg = session.caller_backgrounds.get(session.current_caller_key) or {}
ai_emotional_register = _caller_bg.get("emotional_register", "") if isinstance(_caller_bg, dict) else ""
# TTS — outside the lock so other requests aren't blocked
try:
audio_bytes = await generate_speech(response, ai_voice, "none",
provider_override=ai_tts_provider)
provider_override=ai_tts_provider,
emotional_register=ai_emotional_register)
except Exception as e:
print(f"[AI-Respond] TTS failed: {e}")
broadcast_event("ai_done")