fix: Update Piper TTS to support voice preview and improve setup
- Fixed preview endpoint to work with both Kokoro and Piper engines - Improved voice model download with curl fallback and SSL handling - Added better error messages when models are missing - Created PIPER_SETUP.md with manual download instructions - Added test_piper_direct.py for testing Piper installation - Updated README with voice model download requirements Note: Piper voice models require manual download from GitHub releases due to HuggingFace URL structure. See PIPER_SETUP.md for instructions.
This commit is contained in:
94
backend/test_piper_direct.py
Normal file
94
backend/test_piper_direct.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
Direct test of Piper TTS functionality.
|
||||
"""
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def test_piper_installation():
|
||||
"""Test if Piper is installed and accessible."""
|
||||
print("Testing Piper Installation\n" + "="*50)
|
||||
|
||||
# Check if piper command exists
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["piper", "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5
|
||||
)
|
||||
print(f"✓ Piper found: {result.stdout.strip()}")
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
print("✗ Piper not found in PATH")
|
||||
print(" Install with: ./install_piper.sh")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"✗ Error checking Piper: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def test_piper_synthesis():
|
||||
"""Test basic Piper synthesis."""
|
||||
print("\nTesting Piper Synthesis\n" + "="*50)
|
||||
|
||||
# Create models directory
|
||||
models_dir = os.path.join(os.path.dirname(__file__), "piper_models")
|
||||
os.makedirs(models_dir, exist_ok=True)
|
||||
print(f"Models directory: {models_dir}")
|
||||
|
||||
# Try to synthesize with default voice
|
||||
voice = "en_US-lessac-medium"
|
||||
model_path = os.path.join(models_dir, f"{voice}.onnx")
|
||||
|
||||
if not os.path.exists(model_path):
|
||||
print(f"\n⚠️ Model not found: {model_path}")
|
||||
print(f"Attempting to download {voice}...")
|
||||
|
||||
# Try downloading
|
||||
try:
|
||||
import urllib.request
|
||||
base_url = "https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0"
|
||||
model_url = f"{base_url}/en_US/{voice}.onnx"
|
||||
config_url = f"{base_url}/en_US/{voice}.onnx.json"
|
||||
|
||||
print(f"Downloading from: {model_url}")
|
||||
urllib.request.urlretrieve(model_url, model_path)
|
||||
urllib.request.urlretrieve(config_url, f"{model_path}.json")
|
||||
print("✓ Download complete")
|
||||
except Exception as e:
|
||||
print(f"✗ Download failed: {e}")
|
||||
return False
|
||||
else:
|
||||
print(f"✓ Model found: {model_path}")
|
||||
|
||||
# Try synthesis
|
||||
try:
|
||||
print("\nAttempting synthesis...")
|
||||
process = subprocess.Popen(
|
||||
["piper", "--model", model_path, "--output-raw"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
test_text = "Hello, this is a test."
|
||||
stdout, stderr = process.communicate(input=test_text.encode('utf-8'), timeout=10)
|
||||
|
||||
if process.returncode == 0:
|
||||
print(f"✓ Synthesis successful: {len(stdout)} bytes of audio")
|
||||
return True
|
||||
else:
|
||||
print(f"✗ Synthesis failed (exit code {process.returncode})")
|
||||
print(f" Error: {stderr.decode()}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Synthesis error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if test_piper_installation():
|
||||
test_piper_synthesis()
|
||||
|
||||
print("\n" + "="*50)
|
||||
Reference in New Issue
Block a user