synthGradium destructured json_config from options but only forwarded
pronunciation_id into the say: param block, so the setting could never
reach mediajam's streaming dialect — only the cache-render POST. The
say: parser is brace-aware, so a nested json object survives intact.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The streaming say: path guarded on opts.audioConfig?.pitch and
opts.audioConfig?.speakingRate but interpolated opts.pitch and
opts.speakingRate, which are undefined — so anyone setting them under
audioConfig (what the docs and the portal defaults tell you to do) got
'pitch=undefined,speakingRate=undefined' on the wire and their setting
silently dropped.
Adds a test for the say: params that needs no credentials, since the
streaming branch builds the path without calling the vendor.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Streaming arm returns a say: url for the mediajam dialect; the cache-render
arm posts to /api/post/speech/tts with only_audio and pcm_8000, which is bare
r8 samples and avoids gradium's streaming wav header (0xffffffff RIFF size).
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Streaming goes through mediajam's say: url; the cache render posts to
/tts/bytes for wav, since the service rejects mp3.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* feat(murf): add Murf.ai TTS support to synthAudio
Add synthMurf() following the rimelabs/cartesia pattern:
- streaming path returns a say:{vendor=murf,...} filePath consumed by the
FreeSWITCH mod_murf_tts module
- non-streaming path calls POST /v1/speech/stream (api-key header) and returns
WAV audio for cache rendering
Register murf in the supported-vendor assert list and the synth switch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(murf): drop Accept: audio/basic header (caused 406 Not Acceptable)
Murf's /v1/speech/stream rejects an unmatched Accept header with 406; the
response container is chosen by the `format` body field instead. Verified a
WAV request now returns 200 (valid RIFF/WAVE).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: deprecate and remove verbio, nuance speech vendor support
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: also deprecate and remove PlayHT speech vendor
PlayHT was acquired and no longer provides the service.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
synthPolly received voice but never emitted it into the say:{...} url
(unlike synthMicrosoft, which includes voice=). Polly's SynthesizeSpeech
requires a VoiceId, so the media-server-native (say:-url) Polly path had no
way to pick a voice. Add voice= to the params.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>