From 6e6525a4160cdc80b94e5a3554e740057b5c30e4 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Thu, 16 Apr 2026 21:44:12 +0200 Subject: [PATCH] fix(pitch-deck): pin presenter TTS to Edge TTS (de-DE-ConradNeural) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit German permanently routes to compliance TTS service (Edge TTS neural voice, Piper fallback). OVH DE path removed — no env var can flip it back accidentally. Co-Authored-By: Claude Sonnet 4.6 --- pitch-deck/app/api/presenter/tts/route.ts | 42 ++++++++--------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/pitch-deck/app/api/presenter/tts/route.ts b/pitch-deck/app/api/presenter/tts/route.ts index 4e1b6cf..1436aad 100644 --- a/pitch-deck/app/api/presenter/tts/route.ts +++ b/pitch-deck/app/api/presenter/tts/route.ts @@ -4,28 +4,15 @@ const TTS_SERVICE_URL = process.env.TTS_SERVICE_URL || 'http://compliance-tts-se const LITELLM_URL = process.env.LITELLM_URL || 'https://llm-dev.meghsakha.com' const LITELLM_API_KEY = process.env.LITELLM_API_KEY || '' -// OVH AI Endpoints TTS via the LiteLLM passthrough. -// Path on the LiteLLM side: /tts-ovh/audio/* → https://nvr-tts-.endpoints.kepler.ai.cloud.ovh.net/api/* -// OVH DE is opt-in: set OVH_TTS_ENABLED_DE=true to activate. -// When disabled, German falls through to the compliance TTS service (Edge TTS → Piper). -const OVH_TTS = { - de: process.env.OVH_TTS_ENABLED_DE === 'true' - ? { - url: process.env.OVH_TTS_URL_DE || `${LITELLM_URL}/tts-ovh/audio/v1/tts/text_to_audio`, - voice: process.env.OVH_TTS_VOICE_DE || 'German-DE-Male-1', - languageCode: 'de-DE', - } - : null, - // Enable by setting OVH_TTS_URL_EN (e.g. pointing at a second LiteLLM - // passthrough that targets nvr-tts-en-us). Keeps EN on the old path until set. - en: process.env.OVH_TTS_URL_EN - ? { - url: process.env.OVH_TTS_URL_EN, - voice: process.env.OVH_TTS_VOICE_EN || 'English-US.Female-1', - languageCode: 'en-US', - } - : null, -} +// English via OVH is opt-in (set OVH_TTS_URL_EN). German always uses the +// compliance TTS service (Edge TTS de-DE-ConradNeural → Piper fallback). +const OVH_EN = process.env.OVH_TTS_URL_EN + ? { + url: process.env.OVH_TTS_URL_EN, + voice: process.env.OVH_TTS_VOICE_EN || 'English-US.Female-1', + languageCode: 'en-US', + } + : null const SAMPLE_RATE_HZ = parseInt(process.env.OVH_TTS_SAMPLE_RATE || '16000', 10) @@ -38,9 +25,8 @@ export async function POST(request: NextRequest) { return NextResponse.json({ error: 'Text is required' }, { status: 400 }) } - const ovh = language === 'de' ? OVH_TTS.de : OVH_TTS.en - if (ovh) { - return await synthesizeViaOvh(text, ovh) + if (language === 'en' && OVH_EN) { + return await synthesizeViaOvh(text, OVH_EN) } return await synthesizeViaComplianceService(text, language) @@ -115,7 +101,7 @@ async function synthesizeViaComplianceService(text: string, language: string): P } // Prepend a minimal 44-byte WAV header to raw 16-bit mono PCM. -// OVH's Riva HTTP endpoint returns bare PCM samples; browsers need RIFF/WAV framing. +// Used only for OVH EN if enabled — OVH Riva returns bare PCM samples. function wrapPcmAsWav(pcm: Buffer, sampleRateHz: number): Buffer { const numChannels = 1 const bitsPerSample = 16 @@ -128,8 +114,8 @@ function wrapPcmAsWav(pcm: Buffer, sampleRateHz: number): Buffer { header.writeUInt32LE(36 + dataSize, 4) header.write('WAVE', 8) header.write('fmt ', 12) - header.writeUInt32LE(16, 16) // PCM subchunk size - header.writeUInt16LE(1, 20) // PCM format + header.writeUInt32LE(16, 16) + header.writeUInt16LE(1, 20) header.writeUInt16LE(numChannels, 22) header.writeUInt32LE(sampleRateHz, 24) header.writeUInt32LE(byteRate, 28)