Adds an OVH-backed branch to /api/presenter/tts so the German presenter
narration is synthesized by OVH AI Endpoints' nvr-tts-de-de (NVIDIA Riva)
reached through the LiteLLM passthrough at /tts-ovh/audio/*, which
injects the OVH API token server-side.
- DE requests now hit ${LITELLM_URL}/tts-ovh/audio/v1/tts/text_to_audio
with the documented body shape (encoding=1, language_code=de-DE,
voice_name=German-DE-Male-1, sample_rate_hz=22050) and return the
audio/wav bytes upstream serves (confirmed RIFF-framed in a smoke test).
- EN continues to hit compliance-tts-service until OVH_TTS_URL_EN is set,
making the eventual EN switch a single env flip.
- OVH and voice/url/sample-rate parameters are env-overridable
(OVH_TTS_URL_DE, OVH_TTS_VOICE_DE, OVH_TTS_SAMPLE_RATE,
OVH_TTS_URL_EN, OVH_TTS_VOICE_EN) so retuning doesn't need a redeploy.
- Defensive: OVH failures surface as 502 (no silent fallback) so upstream
issues are visible during this test rollout.
- wrapPcmAsWav() helper is kept as a safety net in case OVH ever returns
bare PCM instead of a full WAV.
Adds X-TTS-Source response header (ovh | compliance) to make
provenance observable from DevTools.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>