Simplify Makefile to run locally, remove all remote SSH/rsync

Remove REMOTE_HOST, REMOTE_USER, REMOTE_PATH, vars.sh loading.
All docker commands use sudo locally. Tests hit localhost:8000.
Delete old non-gendered voice WAV files (alloy, echo, fable, etc).
This commit is contained in:
russell@unturf.com 2026-01-27 12:51:08 -05:00
parent ebfa0319d1
commit c56b8cb24e
21 changed files with 191 additions and 246 deletions

411
Makefile
View file

@ -1,39 +1,26 @@
# Raccoon Mission: uncloseai-speech Development Makefile
# Deploy to remote server with ease
# Configuration is loaded from vars.sh (copy vars.sh.example to vars.sh)
# Raccoon Mission: uncloseai-speech Makefile
# All commands run locally. Use git push/pull to sync between machines.
# Load configuration from vars.sh if it exists
ifneq (,$(wildcard vars.sh))
include vars.sh
export
endif
# Fallback defaults if vars.sh is not found
REMOTE_HOST ?= localhost
REMOTE_USER ?= $(USER)
REMOTE_PATH ?= ~/uncloseai-speech
CONTAINER_NAME ?= uncloseai-speech-server-1
.PHONY: help deploy sync restart logs test clean stop start voices voices-qwen voices-piper voices-xtts voices-kokoro test-kokoro voices-silero test-silero voices-chatterbox test-chatterbox push-all hydrate load-test test-qwen venv venv-run local local-cpu
.PHONY: help deploy restart logs test clean stop start voices voices-qwen voices-piper voices-xtts voices-kokoro test-kokoro voices-silero test-silero voices-chatterbox test-chatterbox push-all hydrate load-test test-qwen venv venv-run local local-cpu
help:
@echo "🦝 Raccoon TTS Mission - Development Commands"
@echo "Raccoon TTS Mission - Development Commands"
@echo ""
@echo "Quick Start (Docker with GPU):"
@echo " make local - Build and run locally with GPU support"
@echo " make local-cpu - Build and run locally (CPU only, slower)"
@echo " make test - Test Qwen3-TTS endpoint"
@echo "Docker (GPU):"
@echo " make deploy - Build and start container (GPU)"
@echo " make deploy-cpu - Build and start container (CPU only)"
@echo " make restart - Rebuild and restart container"
@echo " make stop - Stop container"
@echo " make start - Start container (no rebuild)"
@echo " make clean - Stop and remove container + volumes"
@echo " make logs - Tail container logs"
@echo ""
@echo "Quick Start (No Docker):"
@echo "No Docker:"
@echo " make venv - Create Python virtual environment"
@echo " make venv-run - Run server in virtual environment"
@echo ""
@echo "Remote Deployment:"
@echo " make deploy - Full deploy: sync files, restart container"
@echo " make sync - Sync local files to remote server"
@echo " make restart - Restart the Docker container"
@echo ""
@echo "Testing:"
@echo " make test - Test TTS endpoint (Qwen3-TTS)"
@echo " make test-qwen - Test Qwen3-TTS voice cloning"
@ -49,268 +36,227 @@ help:
@echo " make voices-kokoro - Download Kokoro models"
@echo " make voices-silero - Download Silero models"
@echo ""
@echo "Container Management:"
@echo " make start - Start Docker container"
@echo " make stop - Stop Docker container"
@echo " make clean - Stop and remove container"
@echo ""
@echo "Git:"
@echo " make push-all - Push to all git remotes"
sync:
@echo "📦 Syncing files to $(REMOTE_HOST)..."
rsync -avz --exclude '.git' --exclude '__pycache__' --exclude '*.pyc' \
--exclude 'voices/*' --exclude 'config/voice_to_speaker.yaml' \
./ $(REMOTE_USER)@$(REMOTE_HOST):$(REMOTE_PATH)/
@echo "📝 Ensuring speech.env exists..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && [ -f speech.env ] || cp sample.env speech.env"
deploy: sync restart
@echo "✅ Deployment complete!"
# ============================================================================
# Local Development (Docker)
# Docker
# ============================================================================
local:
@echo "🐳 Building and running with GPU support..."
deploy:
@[ -f speech.env ] || cp sample.env speech.env
docker compose up -d --build
@echo ""
@echo "✅ Container started! Qwen3-TTS model will download on first request (~3.4GB)"
@echo " Test with: make test"
@echo " View logs: make logs"
sudo docker compose up -d --build
local-cpu:
@echo "🐳 Building and running (CPU only - slower inference)..."
deploy-cpu:
@[ -f speech.env ] || cp sample.env speech.env
docker compose -f docker-compose.cpu.yml up -d --build
@echo ""
@echo "✅ Container started (CPU mode)!"
@echo " Note: Qwen3-TTS is ~10x slower on CPU"
@echo " Test with: make test"
sudo docker compose -f docker-compose.cpu.yml up -d --build
restart:
sudo docker compose up -d --build
stop:
sudo docker compose down
start:
sudo docker compose up -d
clean: stop
sudo docker compose down -v
logs:
sudo docker logs -f $(CONTAINER_NAME)
# ============================================================================
# Local Development (Python venv - no Docker)
# Python venv (no Docker)
# ============================================================================
VENV_DIR := .venv
PYTHON := python3
venv:
@echo "🐍 Creating Python virtual environment..."
@echo "Creating Python virtual environment..."
@if [ ! -d "$(VENV_DIR)" ]; then \
$(PYTHON) -m venv $(VENV_DIR); \
echo "✅ Virtual environment created at $(VENV_DIR)"; \
echo "Virtual environment created at $(VENV_DIR)"; \
else \
echo "ℹ️ Virtual environment already exists at $(VENV_DIR)"; \
echo "Virtual environment already exists at $(VENV_DIR)"; \
fi
@echo ""
@echo "📦 Installing dependencies..."
@echo "Installing dependencies..."
$(VENV_DIR)/bin/pip install --upgrade pip
$(VENV_DIR)/bin/pip install -r requirements.txt
@echo ""
@echo "✅ Setup complete!"
@echo ""
@echo "To activate manually:"
@echo " source $(VENV_DIR)/bin/activate"
@echo ""
@echo "To run the server:"
@echo " make venv-run"
@echo ""
@echo "Or run directly:"
@echo " $(VENV_DIR)/bin/python speech.py"
@echo "Done. Run: make venv-run"
venv-run:
@echo "🚀 Starting uncloseai-speech server..."
@if [ ! -d "$(VENV_DIR)" ]; then \
echo "❌ Virtual environment not found. Run 'make venv' first."; \
echo "Virtual environment not found. Run 'make venv' first."; \
exit 1; \
fi
@[ -d "config" ] || mkdir -p config
@[ -d "voices" ] || mkdir -p voices
@echo ""
@echo "Server starting on http://localhost:8000"
@echo "Qwen3-TTS model will download on first request (~3.4GB)"
@echo ""
$(VENV_DIR)/bin/python speech.py
venv-clean:
@echo "🧹 Removing virtual environment..."
rm -rf $(VENV_DIR)
@echo "✅ Virtual environment removed"
restart:
@echo "🔄 Rebuilding and restarting container on $(REMOTE_HOST)..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose up -d --build"
stop:
@echo "🛑 Stopping container on $(REMOTE_HOST)..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose down"
start:
@echo "▶️ Starting container on $(REMOTE_HOST)..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose up -d"
clean: stop
@echo "🧹 Removing container..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "cd $(REMOTE_PATH) && docker compose down -v"
logs:
@echo "📋 Tailing logs from $(REMOTE_HOST)..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker logs -f $(CONTAINER_NAME)"
# ============================================================================
# Testing
# ============================================================================
test: test-qwen
test-qwen:
@echo "🧪 Testing Qwen3-TTS endpoint (default model)..."
curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
@echo "Testing Qwen3-TTS endpoint..."
curl -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1-qwen","voice":"alloy","input":"Raccoon mission TTS test with Qwen three"}' \
-d '{"model":"tts-1-qwen","voice":"aria","input":"Raccoon mission TTS test with Qwen three"}' \
-o /tmp/qwen_test.mp3
@echo "✅ Test complete! Playing audio..."
@firefox /tmp/qwen_test.mp3 || mpv /tmp/qwen_test.mp3 || echo "Install firefox or mpv to play audio"
voices: voices-qwen
@echo "✅ Qwen3-TTS ready (model downloads automatically on first use)"
voices-qwen:
@echo "🎤 Qwen3-TTS models download automatically on first use"
@echo " Model: Qwen/Qwen3-TTS-12Hz-1.7B-Base (~3.4GB)"
@echo " The model will be cached in /app/voices/hub/"
@echo ""
@echo "To pre-download, run: make test-qwen"
voices-all: voices-qwen voices-piper voices-xtts voices-silero
@echo "✅ All voices downloaded (Qwen, Piper, XTTS, Silero)!"
voices-piper:
@echo "🎤 Downloading all Piper voices..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
set -e; \
BASE_URL=\"https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0\"; \
download_voice() { \
local path=\"\$$1\"; \
local name=\"\$$2\"; \
mkdir -p \"/app/voices/\$$path\"; \
cd \"/app/voices/\$$path\"; \
echo \"Downloading \$$name...\"; \
curl -f -L \"\$$BASE_URL/\$$path/\$$name.onnx\" -o \"\$$name.onnx\" || echo \"Failed to download \$$name.onnx\"; \
curl -f -L \"\$$BASE_URL/\$$path/\$$name.onnx.json\" -o \"\$$name.onnx.json\" || echo \"Failed to download \$$name.onnx.json\"; \
}; \
echo \"=== Downloading English US voices ===\"; \
download_voice \"en/en_US/libritts_r/medium\" \"en_US-libritts_r-medium\"; \
download_voice \"en/en_US/amy/medium\" \"en_US-amy-medium\"; \
download_voice \"en/en_US/arctic/medium\" \"en_US-arctic-medium\"; \
download_voice \"en/en_US/bryce/medium\" \"en_US-bryce-medium\"; \
download_voice \"en/en_US/danny/low\" \"en_US-danny-low\"; \
download_voice \"en/en_US/hfc_female/medium\" \"en_US-hfc_female-medium\"; \
download_voice \"en/en_US/hfc_male/medium\" \"en_US-hfc_male-medium\"; \
download_voice \"en/en_US/joe/medium\" \"en_US-joe-medium\"; \
download_voice \"en/en_US/john/medium\" \"en_US-john-medium\"; \
download_voice \"en/en_US/kathleen/low\" \"en_US-kathleen-low\"; \
download_voice \"en/en_US/kristin/medium\" \"en_US-kristin-medium\"; \
download_voice \"en/en_US/kusal/medium\" \"en_US-kusal-medium\"; \
download_voice \"en/en_US/l2arctic/medium\" \"en_US-l2arctic-medium\"; \
download_voice \"en/en_US/lessac/medium\" \"en_US-lessac-medium\"; \
download_voice \"en/en_US/libritts/high\" \"en_US-libritts-high\"; \
download_voice \"en/en_US/ljspeech/medium\" \"en_US-ljspeech-medium\"; \
download_voice \"en/en_US/norman/medium\" \"en_US-norman-medium\"; \
download_voice \"en/en_US/reza_ibrahim/medium\" \"en_US-reza_ibrahim-medium\"; \
download_voice \"en/en_US/ryan/high\" \"en_US-ryan-high\"; \
download_voice \"en/en_US/sam/medium\" \"en_US-sam-medium\"; \
echo \"=== Downloading English GB voices ===\"; \
download_voice \"en/en_GB/northern_english_male/medium\" \"en_GB-northern_english_male-medium\"; \
download_voice \"en/en_GB/alan/medium\" \"en_GB-alan-medium\"; \
download_voice \"en/en_GB/alba/medium\" \"en_GB-alba-medium\"; \
download_voice \"en/en_GB/aru/medium\" \"en_GB-aru-medium\"; \
download_voice \"en/en_GB/cori/medium\" \"en_GB-cori-medium\"; \
download_voice \"en/en_GB/jenny_dioco/medium\" \"en_GB-jenny_dioco-medium\"; \
download_voice \"en/en_GB/semaine/medium\" \"en_GB-semaine-medium\"; \
download_voice \"en/en_GB/southern_english_female/low\" \"en_GB-southern_english_female-low\"; \
download_voice \"en/en_GB/vctk/medium\" \"en_GB-vctk-medium\"; \
echo \"=== All Piper voices downloaded! ===\"'"
@echo "✅ All Piper voices downloaded!"
voices-xtts:
@echo "🎤 Downloading XTTS speaker samples..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c 'cd /app && ./scripts/download_samples.sh'"
@echo "✅ XTTS speaker samples downloaded!"
voices-kokoro:
@echo "🎤 Downloading Kokoro TTS models..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
mkdir -p /app/voices/kokoro && \
cd /app/voices/kokoro && \
huggingface-cli download hexgrad/kokoro-82m --local-dir .'"
@echo "✅ Kokoro models downloaded!"
@echo "Saved to /tmp/qwen_test.mp3"
test-kokoro:
@echo "🧪 Testing Kokoro fast synthesis..."
curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
@echo "Testing Kokoro fast synthesis..."
curl -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1-kokoro","voice":"alloy","input":"Testing Kokoro fast decoder synthesis"}' \
-d '{"model":"tts-1-kokoro","voice":"aria","input":"Testing Kokoro fast decoder synthesis"}' \
-o /tmp/kokoro_test.mp3
@echo "✅ Test complete! Playing audio..."
@firefox /tmp/kokoro_test.mp3 || mpv /tmp/kokoro_test.mp3 || echo "Install firefox or mpv to play audio"
@echo ""
@echo "Saved to /tmp/kokoro_test.mp3"
test-xtts:
@echo "🧪 Testing XTTS HD endpoint (this may take 1-2 minutes on first run)..."
curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
@echo "Testing XTTS HD endpoint..."
curl -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1-hd","voice":"alloy","input":"Testing XTTS high definition"}' \
-d '{"model":"tts-1-hd","voice":"aria","input":"Testing XTTS high definition"}' \
-o /tmp/xtts_test.mp3
@echo "✅ Test complete! Playing audio..."
@firefox /tmp/xtts_test.mp3 || mpv /tmp/xtts_test.mp3 || echo "Install firefox or mpv to play audio"
push-all:
@echo "🚀 Pushing to all remotes..."
git push origin main
git push github main
@echo "✅ Pushed to origin and github!"
voices-silero:
@echo "🎤 Downloading Silero TTS models..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
cd /app/voices && \
python3 -c \"import torch; \
for lang in [\"\"en\"\", \"\"ru\"\", \"\"de\"\", \"\"es\"\", \"\"fr\"\"]: \
model, *_ = torch.hub.load(repo_or_dir=\"\"snakers4/silero-models\"\", model=\"\"silero_tts\"\", language=lang, speaker=\"\"v4_\"\"+lang if lang==\"\"en\"\" else \"\"v3_\"\"+lang); \
print(f\"\"Downloaded Silero {lang}\"\")\"'"
@echo "✅ Silero models downloaded!"
@echo ""
@echo "Saved to /tmp/xtts_test.mp3"
test-silero:
@echo "🧪 Testing Silero endpoint..."
curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
@echo "Testing Silero endpoint..."
curl -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1-silero","voice":"alloy","input":"Testing Silero fast synthesis"}' \
-d '{"model":"tts-1-silero","voice":"aria","input":"Testing Silero fast synthesis"}' \
-o /tmp/silero_test.mp3
@echo "✅ Test complete! Playing audio..."
@firefox /tmp/silero_test.mp3 || mpv /tmp/silero_test.mp3 || echo "Install firefox or mpv to play audio"
voices-chatterbox:
@echo "🎤 Downloading Chatterbox models..."
ssh $(REMOTE_USER)@$(REMOTE_HOST) "docker exec $(CONTAINER_NAME) bash -c '\
mkdir -p /app/voices/chatterbox && \
cd /app/voices/chatterbox && \
huggingface-cli download resemble-ai/chatterbox --local-dir .'"
@echo "✅ Chatterbox models downloaded!"
@echo ""
@echo "Saved to /tmp/silero_test.mp3"
test-chatterbox:
@echo "🧪 Testing Chatterbox with emotion control..."
curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
@echo "Testing Chatterbox with emotion control..."
curl -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1-chatter","voice":"alloy","input":"Testing emotional speech synthesis"}' \
-d '{"model":"tts-1-chatter","voice":"aria","input":"Testing emotional speech synthesis"}' \
-o /tmp/chatterbox_test.mp3
@echo "✅ Test complete! Playing audio..."
@firefox /tmp/chatterbox_test.mp3 || mpv /tmp/chatterbox_test.mp3 || echo "Install firefox or mpv to play audio"
@echo ""
@echo "Saved to /tmp/chatterbox_test.mp3"
# ============================================================================
# Voice Downloads
# ============================================================================
voices: voices-qwen
@echo "Qwen3-TTS ready (model downloads automatically on first use)"
voices-qwen:
@echo "Qwen3-TTS models download automatically on first use"
@echo " Model: Qwen/Qwen3-TTS-12Hz-1.7B-Base (~3.4GB)"
@echo " To pre-download, run: make test-qwen"
voices-all: voices-qwen voices-piper voices-xtts voices-silero
@echo "All voices downloaded!"
voices-piper:
@echo "Downloading all Piper voices..."
sudo docker exec $(CONTAINER_NAME) bash -c '\
set -e; \
BASE_URL="https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0"; \
download_voice() { \
local path="$$1"; \
local name="$$2"; \
mkdir -p "/app/voices/$$path"; \
cd "/app/voices/$$path"; \
echo "Downloading $$name..."; \
curl -f -L "$$BASE_URL/$$path/$$name.onnx" -o "$$name.onnx" || echo "Failed: $$name.onnx"; \
curl -f -L "$$BASE_URL/$$path/$$name.onnx.json" -o "$$name.onnx.json" || echo "Failed: $$name.onnx.json"; \
}; \
echo "=== English US voices ==="; \
download_voice "en/en_US/libritts_r/medium" "en_US-libritts_r-medium"; \
download_voice "en/en_US/amy/medium" "en_US-amy-medium"; \
download_voice "en/en_US/arctic/medium" "en_US-arctic-medium"; \
download_voice "en/en_US/bryce/medium" "en_US-bryce-medium"; \
download_voice "en/en_US/danny/low" "en_US-danny-low"; \
download_voice "en/en_US/hfc_female/medium" "en_US-hfc_female-medium"; \
download_voice "en/en_US/hfc_male/medium" "en_US-hfc_male-medium"; \
download_voice "en/en_US/joe/medium" "en_US-joe-medium"; \
download_voice "en/en_US/john/medium" "en_US-john-medium"; \
download_voice "en/en_US/kathleen/low" "en_US-kathleen-low"; \
download_voice "en/en_US/kristin/medium" "en_US-kristin-medium"; \
download_voice "en/en_US/kusal/medium" "en_US-kusal-medium"; \
download_voice "en/en_US/l2arctic/medium" "en_US-l2arctic-medium"; \
download_voice "en/en_US/lessac/medium" "en_US-lessac-medium"; \
download_voice "en/en_US/libritts/high" "en_US-libritts-high"; \
download_voice "en/en_US/ljspeech/medium" "en_US-ljspeech-medium"; \
download_voice "en/en_US/norman/medium" "en_US-norman-medium"; \
download_voice "en/en_US/reza_ibrahim/medium" "en_US-reza_ibrahim-medium"; \
download_voice "en/en_US/ryan/high" "en_US-ryan-high"; \
download_voice "en/en_US/sam/medium" "en_US-sam-medium"; \
echo "=== English GB voices ==="; \
download_voice "en/en_GB/northern_english_male/medium" "en_GB-northern_english_male-medium"; \
download_voice "en/en_GB/alan/medium" "en_GB-alan-medium"; \
download_voice "en/en_GB/alba/medium" "en_GB-alba-medium"; \
download_voice "en/en_GB/aru/medium" "en_GB-aru-medium"; \
download_voice "en/en_GB/cori/medium" "en_GB-cori-medium"; \
download_voice "en/en_GB/jenny_dioco/medium" "en_GB-jenny_dioco-medium"; \
download_voice "en/en_GB/semaine/medium" "en_GB-semaine-medium"; \
download_voice "en/en_GB/southern_english_female/low" "en_GB-southern_english_female-low"; \
download_voice "en/en_GB/vctk/medium" "en_GB-vctk-medium"; \
echo "=== Done ==="'
voices-xtts:
@echo "Downloading XTTS speaker samples..."
sudo docker exec $(CONTAINER_NAME) bash -c 'cd /app && ./scripts/download_samples.sh'
voices-kokoro:
@echo "Downloading Kokoro TTS models..."
sudo docker exec $(CONTAINER_NAME) bash -c '\
mkdir -p /app/voices/kokoro && \
cd /app/voices/kokoro && \
huggingface-cli download hexgrad/kokoro-82m --local-dir .'
voices-silero:
@echo "Downloading Silero TTS models..."
sudo docker exec $(CONTAINER_NAME) bash -c '\
cd /app/voices && \
python3 -c "import torch; \
for lang in [\"en\", \"ru\", \"de\", \"es\", \"fr\"]: \
model, *_ = torch.hub.load(repo_or_dir=\"snakers4/silero-models\", model=\"silero_tts\", language=lang, speaker=\"v4_\"+lang if lang==\"en\" else \"v3_\"+lang); \
print(f\"Downloaded Silero {lang}\")"'
voices-chatterbox:
@echo "Downloading Chatterbox models..."
sudo docker exec $(CONTAINER_NAME) bash -c '\
mkdir -p /app/voices/chatterbox && \
cd /app/voices/chatterbox && \
huggingface-cli download resemble-ai/chatterbox --local-dir .'
# ============================================================================
# Git
# ============================================================================
push-all:
git push origin main
git push github main
# ============================================================================
# Stress Testing
# ============================================================================
hydrate:
@echo "🦝 Hydrating all TTS models by testing ALL voices..."
@echo "This will test all 227 voices across 4 engines (Piper, XTTS, Silero, Kokoro)"
@echo "Hydrating all TTS models by testing ALL voices..."
@echo ""
@mkdir -p /tmp/hydrate_test
@curl -s http://$(REMOTE_HOST):8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/hydrate_voices.txt
@curl -s http://localhost:8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/hydrate_voices.txt
@TOTAL=$$(wc -l < /tmp/hydrate_voices.txt); \
COUNT=0; \
FAILED=0; \
@ -318,18 +264,18 @@ hydrate:
while IFS=: read -r MODEL VOICE; do \
COUNT=$$((COUNT + 1)); \
printf "[%3d/%3d] Testing %-20s %-30s ... " "$$COUNT" "$$TOTAL" "$$MODEL" "$$VOICE"; \
if curl -s -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
if curl -s -X POST http://localhost:8000/v1/audio/speech \
-H "Content-Type: application/json" \
-d "{\"voice\":\"$$VOICE\",\"input\":\"Hydration test\"}" \
-o /tmp/hydrate_test/$${MODEL}_$${VOICE}.mp3 2>&1 | grep -q "error"; then \
echo "❌ FAILED"; \
echo "FAILED"; \
FAILED=$$((FAILED + 1)); \
else \
SIZE=$$(stat -c%s /tmp/hydrate_test/$${MODEL}_$${VOICE}.mp3 2>/dev/null || echo 0); \
if [ "$$SIZE" -gt 1000 ]; then \
echo "✅ OK ($${SIZE} bytes)"; \
echo "OK ($${SIZE} bytes)"; \
else \
echo "⚠️ SMALL ($${SIZE} bytes)"; \
echo "SMALL ($${SIZE} bytes)"; \
FAILED=$$((FAILED + 1)); \
fi; \
fi; \
@ -337,7 +283,7 @@ hydrate:
END_TIME=$$(date +%s); \
DURATION=$$((END_TIME - START_TIME)); \
echo ""; \
echo "🎉 Hydration complete!"; \
echo "Hydration complete!"; \
echo " Total voices: $$TOTAL"; \
echo " Successful: $$((TOTAL - FAILED))"; \
echo " Failed: $$FAILED"; \
@ -345,11 +291,10 @@ hydrate:
echo " Output: /tmp/hydrate_test/"
load-test:
@echo "🚀 Load testing TTS service with random concurrent requests..."
@echo "This will send 100 concurrent requests with random voices across all models"
@echo "Load testing TTS service with random concurrent requests..."
@echo ""
@mkdir -p /tmp/load_test
@curl -s http://$(REMOTE_HOST):8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/load_test_voices.txt
@curl -s http://localhost:8000/v1/voices | jq -r '.data[] as $$model | $$model.voices[] | "\($$model.id):\(.)"' > /tmp/load_test_voices.txt
@TOTAL_VOICES=$$(wc -l < /tmp/load_test_voices.txt); \
REQUESTS=100; \
CONCURRENT=10; \
@ -366,7 +311,7 @@ load-test:
VOICE=\$$(echo \$$VOICE_SPEC | cut -d: -f2); \
NUM={}; \
START=\$$(date +%s%3N); \
if curl -s -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \
if curl -s -X POST http://localhost:8000/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{\"model\":\"'\$$MODEL'\",\"voice\":\"'\$$VOICE'\",\"input\":\"Load test number '\$$NUM'\"}' \
-o /tmp/load_test/request_\$${NUM}.mp3 2>&1; then \
@ -383,7 +328,7 @@ load-test:
SUCCESS=$$(ls /tmp/load_test/*.mp3 2>/dev/null | wc -l); \
VALID=$$(find /tmp/load_test -name '*.mp3' -size +1000c 2>/dev/null | wc -l); \
echo ""; \
echo "🎉 Load test complete!"; \
echo "Load test complete!"; \
echo " Total requests: $$REQUESTS"; \
echo " Files created: $$SUCCESS"; \
echo " Valid audio (>1KB): $$VALID"; \

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.