mcspeak/Makefile
Ryan Malloy 27b4c4ae29 Add generate_audio file/format params; bring Piper TTS up with es_MX default
generate_audio gains output_path + format params (wav, mp3, ogg, flac,
m4a). Non-wav formats route through ffmpeg (added to the Dockerfile).
Files land under /output/ inside the container, bind-mounted from the
host's TTS_OUTPUT_HOST_DIR (defaults to ~/mcspeak-out). Subdirectories
are auto-created. Path validation rejects writes outside /output/ —
both absolute escapes like /etc/passwd and traversal forms like
../../etc/passwd are canonicalized and checked against the mount root.
Extension auto-corrects to match the requested format.

piper-tts service added to compose using rhasspy/wyoming-piper. Default
voice es_MX-ald-medium is pre-warmed at container start and persists in
./piper-data/ across recreates (~60 MB download on first run). Port
10200 published to localhost so host-side scripts can also reach
Wyoming directly; mcspeak inside the stack uses container DNS. Voice
configurable via TTS_PIPER_VOICE — the same env var threads through to
both wyoming-piper's --voice flag and mcspeak's settings.piper_voice,
so they stay in sync.

PiperEngine.__init__ accepts a default_voice override; settings.piper_voice
threads it from the env. list_engines now reports the configured default
rather than the hardcoded en_US-lessac-medium. speak() / generate_audio()
calls with engine=piper and no explicit voice use the configured one.

mcspeak-internal network changed from internal:true to default-bridge.
internal:true was overkill — the goal was per-stack DNS scoping (which
compose provides automatically via the project-prefixed network name),
not internet isolation. The latter broke piper-tts's HuggingFace voice
download with "Name resolution failure" on first start.

.gitignore: add piper-data/ so the downloaded voice models stay out of
the repo.
2026-06-13 17:35:36 -06:00

45 lines
1.3 KiB
Makefile

# .env is optional in kokoro-only mode (only needed for ORPHEUS_GGUF_PATH).
# The leading dash makes Make silently tolerate a missing file.
-include .env
export
.PHONY: build up up-with-orpheus down logs restart status bench
build:
docker compose build
up: build
@mkdir -p $${TTS_OUTPUT_HOST_DIR:-$$HOME/mcspeak-out}
docker compose up -d
@sleep 2
docker compose logs --tail 20
up-with-orpheus: build
@mkdir -p $${TTS_OUTPUT_HOST_DIR:-$$HOME/mcspeak-out}
docker compose --profile with-orpheus up -d
@sleep 2
docker compose logs --tail 20
down:
docker compose down
logs:
docker compose logs -f
restart:
docker compose restart
@sleep 2
docker compose logs --tail 20
status:
@docker compose ps
@echo "---"
@curl -s http://localhost:8371/mcp 2>/dev/null | head -5 || echo "Server not responding"
bench:
@echo "Benchmarking llama-server throughput..."
@docker exec orpheus-llama-server curl -s "http://127.0.0.1:8081/v1/completions" \
-H "Content-Type: application/json" \
-d '{"prompt":"<|audio|>tara: Hello, how are you doing today?<|eot_id|>","max_tokens":500,"stream":false}' | \
python3 -c "import sys,json; d=json.load(sys.stdin); u=d['usage']; t=d.get('timings',{}); print(f\"{u['completion_tokens']} tokens, {t.get('predicted_per_second',0):.1f} tok/s\")"