Repository navigation
v2.2.0 — OpenAI-compat polish sweep (9 fixes, 1 CRITICAL)
cloning (custom_voice_file / speaker_wav), upgrade. v2.1.0 on
FastAPI 0.136+ silently ignored uploaded reference audio and returned
default-voice (alloy) output with X-Route: HOT / X-Cache: MISS
headers. v2.2.0 is the first release where cloning actually works
against FastAPI 0.136+ / Starlette 1.0+.
Same root cause as the just-fixed
uttera-tts-vllm v1.2.0
bug: fastapi.datastructures.UploadFile and
starlette.datastructures.UploadFile are now DISTINCT classes, so a
plain isinstance(x, UploadFile) against a Starlette instance
silently returns False.
Fixed
- [CRITICAL] Adhoc voice cloning was silently disabled — see
above. - Unknown
voicesilently fell back to the default — now
HTTP 400 with the list of available voices. response_formatoutside {mp3, wav, pcm, opus, flac} reached
ffmpeg and produced HTTP 500. Now validated → HTTP 422.speedoutside[0.25, 4.0](OpenAI spec) not validated.
speed=99→ HTTP 500;speed=-1→ HTTP 200 with garbage. Now 422.temperatureoutside[0.0, 2.0]not validated. Now 422.cfg_valueoutside[0.5, 5.0](VoxCPM range) not validated.
Now 422.- JSON body without
inputraisedpydantic.ValidationError
that escaped as HTTP 500. Now caught → HTTP 422. - Bogus / non-audio
custom_voice_filesurfaced as HTTP 500.
Now HTTP 400 with a trimmed decode message. - HEAD /health returned HTTP 405. Now accepted.
Added
- Opt-in
CORSMiddlewareviaCORS_ALLOW_ORIGINSenv var
(comma-separated list or"*"). Disabled by default. X-Cache: ADHOCresponse header on adhoc cloning, matching
uttera-tts-vllmv1.2.0. Adhoc cloning also always bypasses
the MD5 audio cache (both read and write) — previously the
cache key used the temp-file path md5 and wrote single-use junk
entries on every adhoc request (cache pollution).
Changed
SERVER_VERSIONbumped to2.2.0. The in-file# Version:
header comment had been stuck at2.0.0since the v2.0.0 release
(runtimeSERVER_VERSIONwas already tracking). Resynced./v1/modelsowned_byrebranded from"stark-fleet"to
"uttera".
Breaking?
Clients that relied on v2.1.0's silent behaviours will see explicit
errors instead:
- Unknown
voicenames now return HTTP 400 (were: alloy audio + 200). - Adhoc uploads now actually clone the voice (were: alloy audio).
Every previously-valid request continues to return the same shape.
Verified
- All 13 validation cases return expected 4xx codes.
- Adhoc cloning via both
custom_voice_fileandspeaker_wavalias
emitsX-Cache: ADHOC, writes no cache entry, produces audio in
the cloned voice, and leaves no copy of the uploaded WAV on disk
(MD5-scan verified). - 32-concurrent Coqui burst: 32/32 OK, 0 tracebacks.