fix(pitch-deck): pin presenter TTS to Edge TTS (de-DE-ConradNeural)
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m25s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 44s
CI / test-python-voice (push) Successful in 36s
CI / test-bqas (push) Successful in 37s
All checks were successful
Build pitch-deck / build-push-deploy (push) Successful in 1m25s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 44s
CI / test-python-voice (push) Successful in 36s
CI / test-bqas (push) Successful in 37s
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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-<lang>.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)
|
||||
|
||||
Reference in New Issue
Block a user