- 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.
95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
"""
|
|
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)
|