# 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) # 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-piper voices-xtts voices-kokoro test-kokoro voices-silero test-silero voices-chatterbox test-chatterbox push-all help: @echo "๐Ÿฆ Raccoon TTS Mission - Development Commands" @echo "" @echo "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 "Development:" @echo " make logs - Tail container logs" @echo " make test - Test TTS endpoint (Piper)" @echo " make test-xtts - Test XTTS HD endpoint" @echo " make voices - Download all voices (Piper + XTTS)" @echo " make voices-piper - Download Piper voices only" @echo " make voices-xtts - Download XTTS voices and samples" @echo " make voices-kokoro - Download Kokoro models" @echo " make test-kokoro - Test Kokoro fast TTS" @echo " make voices-silero - Download Silero models (en, ru, de, es, fr)" @echo " make test-silero - Test Silero TTS endpoint" @echo " make voices-chatterbox - Download Chatterbox models" @echo " make test-chatterbox - Test Chatterbox TTS with emotion control" @echo "" @echo "Container:" @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 (origin + github)" 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!" 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)" test: @echo "๐Ÿงช Testing TTS endpoint..." curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \ -H "Content-Type: application/json" \ -d '{"model":"tts-1","voice":"alloy","input":"Raccoon mission TTS test"}' \ -o /tmp/raccoon_test.mp3 @echo "โœ… Test complete! Playing audio..." @firefox /tmp/raccoon_test.mp3 || mpv /tmp/raccoon_test.mp3 || echo "Install firefox or mpv to play audio" voices: voices-piper voices-xtts voices-silero @echo "โœ… All voices downloaded (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!" test-kokoro: @echo "๐Ÿงช Testing Kokoro fast synthesis..." curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \ -H "Content-Type: application/json" \ -d '{"model":"tts-1-kokoro","voice":"alloy","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" 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 \ -H "Content-Type: application/json" \ -d '{"model":"tts-1-hd","voice":"alloy","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!" test-silero: @echo "๐Ÿงช Testing Silero endpoint..." curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \ -H "Content-Type: application/json" \ -d '{"model":"tts-1-silero","voice":"alloy","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!" test-chatterbox: @echo "๐Ÿงช Testing Chatterbox with emotion control..." curl -X POST http://$(REMOTE_HOST):8000/v1/audio/speech \ -H "Content-Type: application/json" \ -d '{"model":"tts-1-chatter","voice":"alloy","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"