- WS /ws/session: modes, summon, anomaly fragments, streaming direct contact,
passive wire-ghost ambient loop, per-user rate limits, event transcript
- entities: anomaly-signature fingerprinting, LLM minting + procedural
fallback, Codex matching with contact counts and sightings
- tts: 8 local Piper voices (EN/ES), per-entity voice profiles, numpy
effects chain (pitch/rate/bitcrush/echo/static)
- llm: streaming client, submit_stream in bounded queue, SpiritService
with offline fallbacks for every channel
- routes: public /api/codex, /api/codex/{id}, /api/stats; /audio static mount
- models: Entity, EntitySighting, Event, ContactSession(entity_id, language)
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""Catalog of locally installed Piper voices.
|
|
|
|
Each entity's voice_profile pins one of these voice ids plus pitch/rate/noise
|
|
shaping, giving every spirit its own recognizable throat."""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Voice:
|
|
id: str
|
|
model_file: str
|
|
language: str
|
|
description: str
|
|
|
|
|
|
VOICES: dict[str, Voice] = {
|
|
"lessac": Voice("lessac", "en_US-lessac-low.onnx", "en", "a measured American woman"),
|
|
"amy": Voice("amy", "en_US-amy-low.onnx", "en", "a soft American woman"),
|
|
"ryan": Voice("ryan", "en_US-ryan-low.onnx", "en", "a deep American man"),
|
|
"alan": Voice("alan", "en_GB-alan-low.onnx", "en", "a low British man"),
|
|
"hfc_male": Voice("hfc_male", "en_US-hfc_male-medium.onnx", "en", "a worn male voice"),
|
|
"hfc_female": Voice(
|
|
"hfc_female", "en_US-hfc_female-medium.onnx", "en", "a worn female voice"
|
|
),
|
|
"davefx": Voice("davefx", "es_ES-davefx-medium.onnx", "es", "una voz masculina grave"),
|
|
"ald": Voice("ald", "es_MX-ald-medium.onnx", "es", "una voz masculina seca"),
|
|
}
|
|
|
|
EN_VOICE_IDS = [v.id for v in VOICES.values() if v.language == "en"]
|
|
ES_VOICE_IDS = [v.id for v in VOICES.values() if v.language == "es"]
|
|
|
|
|
|
def pick_voice(voice_id: str | None, language: str) -> Voice:
|
|
"""Resolve an entity's voice id, falling back to a language-appropriate default."""
|
|
if voice_id and voice_id in VOICES:
|
|
voice = VOICES[voice_id]
|
|
if voice.language == language:
|
|
return voice
|
|
return VOICES["davefx" if language == "es" else "lessac"]
|