deploy/mainnet: add PiperTTS (private) + supplier-tts (audio.synthesize.piper.v1)
Mirrors deploy/testnet/docker-compose.supplier-tts.yml and the simulation PiperTTS stack, co-located on vector-marketplace as a private internal service on marketplace-mainnet-net (no Traefik labels, no public DNS for Piper itself). Supplier reaches Piper at http://marketplace-mainnet-tts-piper:8000. Voice: en_US-lessac-high. New supplier wallet + on-chain advert are published out-of-band by the operator per the runbook header. Files: - deploy/mainnet/docker-compose.tts-piper.yml openedai-speech-min, private - deploy/mainnet/docker-compose.supplier-tts.yml CAPABILITY_KIND=tts supplier - deploy/mainnet/install-voice-extras.sh voice download + yaml mapping - deploy/mainnet/voice-mappings.py idempotent yaml editor - supplier/.env.tts.example operator env template - .gitignore whitelist .env.*.example Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
deploy/mainnet/voice-mappings.py
Normal file
60
deploy/mainnet/voice-mappings.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
# voice-mappings.py — idempotently apply project-specific voice aliases to
|
||||
# /app/config/voice_to_speaker.yaml inside the marketplace-mainnet-tts-piper container.
|
||||
#
|
||||
# Why this exists:
|
||||
# The openedai-speech-min image populates voice_to_speaker.yaml on first
|
||||
# start with its OWN defaults (alloy/echo/fable/onyx/nova/shimmer mapped
|
||||
# onto the bundled LibriTTS + northern-english-male voices). Voices we
|
||||
# install ourselves (e.g. en_US-lessac-high) need a name in that yaml so
|
||||
# the OpenAI-shape `voice` field can resolve to them. This script adds
|
||||
# those entries — and only those — without disturbing the defaults.
|
||||
#
|
||||
# Idempotency contract:
|
||||
# Reads the yaml, compares each desired entry against what's there, only
|
||||
# rewrites if at least one entry is missing or stale. Prints "modified"
|
||||
# on write, "unchanged" otherwise — install-voice-extras.sh greps for
|
||||
# "modified" to decide whether to restart the container.
|
||||
#
|
||||
# Run via:
|
||||
# docker cp voice-mappings.py marketplace-mainnet-tts-piper:/tmp/voice-mappings.py
|
||||
# docker exec marketplace-mainnet-tts-piper python3 /tmp/voice-mappings.py
|
||||
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
CONFIG_PATH = "/app/config/voice_to_speaker.yaml"
|
||||
|
||||
# Mappings to ensure exist under `tts-1`. Adding more voices later is a
|
||||
# matter of dropping the .onnx + .onnx.json into voices/ (handled by
|
||||
# install-voice-extras.sh) and adding an entry here.
|
||||
DESIRED_TTS1 = {
|
||||
# en_US-lessac-high — high-quality American female single-speaker voice.
|
||||
# Single-speaker model, so no `speaker:` key.
|
||||
"lessac": {"model": "voices/en_US-lessac-high.onnx"},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
with open(CONFIG_PATH) as f:
|
||||
cfg = yaml.safe_load(f) or {}
|
||||
|
||||
cfg.setdefault("tts-1", {})
|
||||
|
||||
modified_keys = []
|
||||
for name, mapping in DESIRED_TTS1.items():
|
||||
if cfg["tts-1"].get(name) != mapping:
|
||||
cfg["tts-1"][name] = mapping
|
||||
modified_keys.append(name)
|
||||
|
||||
if modified_keys:
|
||||
with open(CONFIG_PATH, "w") as f:
|
||||
yaml.safe_dump(cfg, f, sort_keys=False)
|
||||
print(f"modified — applied: {', '.join(modified_keys)}")
|
||||
else:
|
||||
print("unchanged — all mappings already present")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user