cpu-tts / tests /test_speech_response.py
grimshaw's picture
Improve storage fallback and UI source editor
0a81ef3 verified
Raw
History Blame Contribute Delete
5.48 kB
import numpy as np
from fastapi.testclient import TestClient
from app.main import app
from app.services.engine_registry import EngineRegistry, get_engine_registry
from app.services.supertonic_engine import SynthesisResult
class FakeEngine:
def supports_voice(self, _: str) -> bool:
return True
def list_voice_bindings(self) -> list[dict[str, str]]:
return []
def synthesize(self, **_: object) -> SynthesisResult:
wav = np.zeros((1, 2400), dtype=np.float32)
return SynthesisResult(waveform=wav, sample_rate=24000, duration_seconds=0.1)
def fake_registry() -> EngineRegistry:
engine = FakeEngine()
return EngineRegistry(
model_to_engine={
"supertonic-2": engine,
"tts-1": engine,
"tts-1-hd": engine,
"gpt-4o-mini-tts": engine,
"kitten-tts-micro-0.8": engine,
"kitten-tts-micro": engine,
"kitten-tts": engine,
"kitten": engine,
"melo-en": engine,
"kokoro": engine,
"kokoro-onnx": engine,
"kokoro-82m": engine,
}
)
def test_speech_returns_wav(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "supertonic-2",
"input": "hello",
"voice": "alloy",
"response_format": "wav",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/wav")
assert len(response.content) > 44
finally:
app.dependency_overrides.clear()
def test_speech_returns_mp3(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "supertonic-2",
"input": "hello",
"voice": "alloy",
"response_format": "mp3",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/mpeg")
assert response.content[:3] == b"ID3" or response.content[:2] == b"\xff\xfb"
finally:
app.dependency_overrides.clear()
def test_speech_accepts_quality_and_friendly_voice(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "supertonic-2",
"input": "hello",
"voice": "atlas",
"quality": "high",
"response_format": "wav",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/wav")
finally:
app.dependency_overrides.clear()
def test_kokoro_model_route(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "kokoro",
"input": "hello",
"voice": "af_bella",
"response_format": "wav",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/wav")
finally:
app.dependency_overrides.clear()
def test_kitten_model_route(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "kitten-tts-micro-0.8",
"input": "hello",
"voice": "bella",
"response_format": "wav",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/wav")
finally:
app.dependency_overrides.clear()
def test_melo_model_route(monkeypatch) -> None:
app.dependency_overrides[get_engine_registry] = fake_registry
try:
with TestClient(app) as client:
response = client.post(
"/v1/audio/speech",
headers={"Authorization": "Bearer changeme"},
json={
"model": "melo-en",
"input": "hello",
"voice": "us",
"response_format": "wav",
},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("audio/wav")
finally:
app.dependency_overrides.clear()