Spaces:
Running
Running
Avinyaa
commited on
Commit
Β·
5efbc82
1
Parent(s):
9acb9c3
- Dockerfile +12 -2
- README.md +40 -0
- app.py +12 -3
- app_config.py +53 -0
- startup.py +132 -0
- test.py +13 -1
- test_kokoro_install.py +93 -1
Dockerfile
CHANGED
@@ -2,9 +2,13 @@ FROM python:3.11
|
|
2 |
|
3 |
WORKDIR /app
|
4 |
|
5 |
-
# Set environment variables to fix Numba caching issues
|
6 |
ENV NUMBA_CACHE_DIR=/tmp/numba_cache
|
7 |
ENV NUMBA_DISABLE_JIT=1
|
|
|
|
|
|
|
|
|
8 |
|
9 |
# Install git, git-lfs, and espeak-ng for Kokoro TTS
|
10 |
RUN apt-get update && apt-get install -y git git-lfs espeak-ng && rm -rf /var/lib/apt/lists/*
|
@@ -12,6 +16,10 @@ RUN apt-get update && apt-get install -y git git-lfs espeak-ng && rm -rf /var/li
|
|
12 |
# Initialize git lfs
|
13 |
RUN git lfs install
|
14 |
|
|
|
|
|
|
|
|
|
15 |
COPY requirements.txt .
|
16 |
|
17 |
RUN pip install uv
|
@@ -22,4 +30,6 @@ COPY . .
|
|
22 |
# Expose the port
|
23 |
EXPOSE 7860
|
24 |
|
25 |
-
|
|
|
|
|
|
2 |
|
3 |
WORKDIR /app
|
4 |
|
5 |
+
# Set environment variables to fix Numba caching issues and configure HF cache
|
6 |
ENV NUMBA_CACHE_DIR=/tmp/numba_cache
|
7 |
ENV NUMBA_DISABLE_JIT=1
|
8 |
+
ENV HF_HOME=/tmp/hf_cache
|
9 |
+
ENV TRANSFORMERS_CACHE=/tmp/hf_cache
|
10 |
+
ENV HF_HUB_CACHE=/tmp/hf_cache
|
11 |
+
ENV TORCH_HOME=/tmp/torch_cache
|
12 |
|
13 |
# Install git, git-lfs, and espeak-ng for Kokoro TTS
|
14 |
RUN apt-get update && apt-get install -y git git-lfs espeak-ng && rm -rf /var/lib/apt/lists/*
|
|
|
16 |
# Initialize git lfs
|
17 |
RUN git lfs install
|
18 |
|
19 |
+
# Create cache directories with proper permissions
|
20 |
+
RUN mkdir -p /tmp/hf_cache /tmp/torch_cache /tmp/numba_cache && \
|
21 |
+
chmod -R 777 /tmp/hf_cache /tmp/torch_cache /tmp/numba_cache
|
22 |
+
|
23 |
COPY requirements.txt .
|
24 |
|
25 |
RUN pip install uv
|
|
|
30 |
# Expose the port
|
31 |
EXPOSE 7860
|
32 |
|
33 |
+
# Default command - use startup.py for debugging if needed
|
34 |
+
# CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
35 |
+
Alternative for debugging: CMD ["python", "startup.py"]
|
README.md
CHANGED
@@ -20,6 +20,7 @@ A FastAPI-based Text-to-Speech API using Kokoro, an open-weight TTS model with 8
|
|
20 |
- Docker support
|
21 |
- Lightweight and fast processing
|
22 |
- Apache-licensed weights
|
|
|
23 |
|
24 |
## About Kokoro
|
25 |
|
@@ -27,6 +28,22 @@ A FastAPI-based Text-to-Speech API using Kokoro, an open-weight TTS model with 8
|
|
27 |
|
28 |
## Setup
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
### Local Development
|
31 |
|
32 |
1. Install system dependencies:
|
@@ -200,5 +217,28 @@ Run the standalone test:
|
|
200 |
python test.py
|
201 |
```
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
This will generate audio files demonstrating Kokoro's capabilities.
|
204 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
- Docker support
|
21 |
- Lightweight and fast processing
|
22 |
- Apache-licensed weights
|
23 |
+
- Optimized for Hugging Face Spaces deployment
|
24 |
|
25 |
## About Kokoro
|
26 |
|
|
|
28 |
|
29 |
## Setup
|
30 |
|
31 |
+
### Hugging Face Spaces Deployment
|
32 |
+
|
33 |
+
This API is optimized for Hugging Face Spaces deployment. The Docker configuration automatically handles:
|
34 |
+
- Cache directory setup with proper permissions
|
35 |
+
- Environment variable configuration
|
36 |
+
- Model downloading and caching
|
37 |
+
|
38 |
+
Simply deploy to Hugging Face Spaces using the Docker SDK.
|
39 |
+
|
40 |
+
#### Troubleshooting on HF Spaces
|
41 |
+
|
42 |
+
If you encounter permission errors, you can use the diagnostic startup script:
|
43 |
+
|
44 |
+
1. Change the Dockerfile CMD to: `CMD ["python", "startup.py"]`
|
45 |
+
2. This will run diagnostics and show detailed information about the environment
|
46 |
+
|
47 |
### Local Development
|
48 |
|
49 |
1. Install system dependencies:
|
|
|
217 |
python test.py
|
218 |
```
|
219 |
|
220 |
+
Run the installation test:
|
221 |
+
```bash
|
222 |
+
python test_kokoro_install.py
|
223 |
+
```
|
224 |
+
|
225 |
+
For debugging on Hugging Face Spaces:
|
226 |
+
```bash
|
227 |
+
python startup.py
|
228 |
+
```
|
229 |
+
|
230 |
This will generate audio files demonstrating Kokoro's capabilities.
|
231 |
|
232 |
+
## Environment Variables
|
233 |
+
|
234 |
+
The following environment variables are automatically configured:
|
235 |
+
|
236 |
+
- `HF_HOME=/tmp/hf_cache` - Hugging Face cache directory
|
237 |
+
- `TRANSFORMERS_CACHE=/tmp/hf_cache` - Transformers cache
|
238 |
+
- `HF_HUB_CACHE=/tmp/hf_cache` - HF Hub cache
|
239 |
+
- `TORCH_HOME=/tmp/torch_cache` - PyTorch cache
|
240 |
+
- `NUMBA_CACHE_DIR=/tmp/numba_cache` - Numba cache
|
241 |
+
- `NUMBA_DISABLE_JIT=1` - Disable Numba JIT compilation
|
242 |
+
|
243 |
+
These are set automatically by the application for optimal performance on Hugging Face Spaces.
|
244 |
+
|
app.py
CHANGED
@@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
1 |
from fastapi import FastAPI, HTTPException, Form
|
2 |
from fastapi.responses import FileResponse
|
3 |
from pydantic import BaseModel
|
@@ -26,9 +29,14 @@ class KokoroTTSService:
|
|
26 |
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
27 |
logger.info(f"Using device: {self.device}")
|
28 |
|
|
|
|
|
|
|
29 |
try:
|
30 |
# Initialize Kokoro pipeline with default language
|
31 |
-
|
|
|
|
|
32 |
logger.info("Kokoro TTS pipeline loaded successfully")
|
33 |
except Exception as e:
|
34 |
logger.error(f"Failed to load Kokoro TTS pipeline: {e}")
|
@@ -39,11 +47,12 @@ class KokoroTTSService:
|
|
39 |
try:
|
40 |
# Create a unique filename for the output
|
41 |
output_filename = f"kokoro_output_{uuid.uuid4().hex}.wav"
|
42 |
-
output_path = os.path.join(
|
43 |
|
44 |
# Update pipeline language if different
|
45 |
if self.pipeline.lang_code != lang_code:
|
46 |
-
self.pipeline
|
|
|
47 |
|
48 |
# Generate speech using Kokoro
|
49 |
generator = self.pipeline(text, voice=voice)
|
|
|
1 |
+
# Import configuration first to setup cache directories
|
2 |
+
import app_config
|
3 |
+
|
4 |
from fastapi import FastAPI, HTTPException, Form
|
5 |
from fastapi.responses import FileResponse
|
6 |
from pydantic import BaseModel
|
|
|
29 |
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
30 |
logger.info(f"Using device: {self.device}")
|
31 |
|
32 |
+
if app_config.is_hf_spaces():
|
33 |
+
logger.info("Running on Hugging Face Spaces")
|
34 |
+
|
35 |
try:
|
36 |
# Initialize Kokoro pipeline with default language
|
37 |
+
# Explicitly specify the repo_id to avoid warnings
|
38 |
+
logger.info("Initializing Kokoro TTS pipeline...")
|
39 |
+
self.pipeline = KPipeline(lang_code='a', repo_id='hexgrad/Kokoro-82M')
|
40 |
logger.info("Kokoro TTS pipeline loaded successfully")
|
41 |
except Exception as e:
|
42 |
logger.error(f"Failed to load Kokoro TTS pipeline: {e}")
|
|
|
47 |
try:
|
48 |
# Create a unique filename for the output
|
49 |
output_filename = f"kokoro_output_{uuid.uuid4().hex}.wav"
|
50 |
+
output_path = os.path.join(app_config.get_temp_dir(), output_filename)
|
51 |
|
52 |
# Update pipeline language if different
|
53 |
if self.pipeline.lang_code != lang_code:
|
54 |
+
logger.info(f"Switching language from {self.pipeline.lang_code} to {lang_code}")
|
55 |
+
self.pipeline = KPipeline(lang_code=lang_code, repo_id='hexgrad/Kokoro-82M')
|
56 |
|
57 |
# Generate speech using Kokoro
|
58 |
generator = self.pipeline(text, voice=voice)
|
app_config.py
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Configuration for Kokoro TTS API, especially for Hugging Face Spaces deployment.
|
3 |
+
"""
|
4 |
+
|
5 |
+
import os
|
6 |
+
import tempfile
|
7 |
+
import logging
|
8 |
+
|
9 |
+
# Configure logging
|
10 |
+
logging.basicConfig(level=logging.INFO)
|
11 |
+
logger = logging.getLogger(__name__)
|
12 |
+
|
13 |
+
def setup_hf_cache():
|
14 |
+
"""Setup cache directories for Hugging Face Spaces"""
|
15 |
+
cache_dirs = {
|
16 |
+
'HF_HOME': '/tmp/hf_cache',
|
17 |
+
'TRANSFORMERS_CACHE': '/tmp/hf_cache',
|
18 |
+
'HF_HUB_CACHE': '/tmp/hf_cache',
|
19 |
+
'TORCH_HOME': '/tmp/torch_cache',
|
20 |
+
'NUMBA_CACHE_DIR': '/tmp/numba_cache'
|
21 |
+
}
|
22 |
+
|
23 |
+
# Set environment variables
|
24 |
+
for key, value in cache_dirs.items():
|
25 |
+
os.environ[key] = value
|
26 |
+
logger.info(f"Set {key} to {value}")
|
27 |
+
|
28 |
+
# Create directories
|
29 |
+
for cache_dir in set(cache_dirs.values()):
|
30 |
+
try:
|
31 |
+
os.makedirs(cache_dir, exist_ok=True)
|
32 |
+
# Ensure write permissions
|
33 |
+
os.chmod(cache_dir, 0o777)
|
34 |
+
logger.info(f"Created cache directory: {cache_dir}")
|
35 |
+
except Exception as e:
|
36 |
+
logger.warning(f"Could not create/modify {cache_dir}: {e}")
|
37 |
+
|
38 |
+
# Additional HF settings
|
39 |
+
os.environ['NUMBA_DISABLE_JIT'] = '1'
|
40 |
+
os.environ['HF_HUB_DISABLE_TELEMETRY'] = '1'
|
41 |
+
|
42 |
+
logger.info("Cache directories setup completed")
|
43 |
+
|
44 |
+
def get_temp_dir():
|
45 |
+
"""Get a writable temporary directory"""
|
46 |
+
return tempfile.gettempdir()
|
47 |
+
|
48 |
+
def is_hf_spaces():
|
49 |
+
"""Check if running on Hugging Face Spaces"""
|
50 |
+
return os.environ.get('SPACE_ID') is not None
|
51 |
+
|
52 |
+
# Initialize cache setup
|
53 |
+
setup_hf_cache()
|
startup.py
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Startup script for Kokoro TTS API on Hugging Face Spaces
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
import sys
|
8 |
+
import logging
|
9 |
+
import subprocess
|
10 |
+
|
11 |
+
# Configure logging
|
12 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
13 |
+
logger = logging.getLogger(__name__)
|
14 |
+
|
15 |
+
def check_environment():
|
16 |
+
"""Check the environment and permissions"""
|
17 |
+
logger.info("=== Environment Check ===")
|
18 |
+
|
19 |
+
# Check if running on HF Spaces
|
20 |
+
space_id = os.environ.get('SPACE_ID')
|
21 |
+
if space_id:
|
22 |
+
logger.info(f"Running on Hugging Face Spaces: {space_id}")
|
23 |
+
else:
|
24 |
+
logger.info("Not running on Hugging Face Spaces")
|
25 |
+
|
26 |
+
# Check Python version
|
27 |
+
logger.info(f"Python version: {sys.version}")
|
28 |
+
|
29 |
+
# Check available disk space
|
30 |
+
try:
|
31 |
+
result = subprocess.run(['df', '-h', '/tmp'], capture_output=True, text=True)
|
32 |
+
logger.info(f"Disk space in /tmp:\n{result.stdout}")
|
33 |
+
except Exception as e:
|
34 |
+
logger.warning(f"Could not check disk space: {e}")
|
35 |
+
|
36 |
+
# Check write permissions
|
37 |
+
test_dirs = ['/tmp', '/app', '.']
|
38 |
+
for test_dir in test_dirs:
|
39 |
+
try:
|
40 |
+
test_file = os.path.join(test_dir, 'test_write.tmp')
|
41 |
+
with open(test_file, 'w') as f:
|
42 |
+
f.write('test')
|
43 |
+
os.remove(test_file)
|
44 |
+
logger.info(f"β
Write permission OK: {test_dir}")
|
45 |
+
except Exception as e:
|
46 |
+
logger.warning(f"β Write permission failed: {test_dir} - {e}")
|
47 |
+
|
48 |
+
def setup_cache_dirs():
|
49 |
+
"""Setup cache directories with proper permissions"""
|
50 |
+
logger.info("=== Setting up cache directories ===")
|
51 |
+
|
52 |
+
cache_dirs = [
|
53 |
+
'/tmp/hf_cache',
|
54 |
+
'/tmp/torch_cache',
|
55 |
+
'/tmp/numba_cache'
|
56 |
+
]
|
57 |
+
|
58 |
+
for cache_dir in cache_dirs:
|
59 |
+
try:
|
60 |
+
os.makedirs(cache_dir, exist_ok=True)
|
61 |
+
os.chmod(cache_dir, 0o777)
|
62 |
+
logger.info(f"β
Created cache directory: {cache_dir}")
|
63 |
+
except Exception as e:
|
64 |
+
logger.error(f"β Failed to create {cache_dir}: {e}")
|
65 |
+
|
66 |
+
def check_dependencies():
|
67 |
+
"""Check if required packages are installed"""
|
68 |
+
logger.info("=== Checking dependencies ===")
|
69 |
+
|
70 |
+
required_packages = [
|
71 |
+
'kokoro',
|
72 |
+
'soundfile',
|
73 |
+
'torch',
|
74 |
+
'fastapi',
|
75 |
+
'uvicorn'
|
76 |
+
]
|
77 |
+
|
78 |
+
for package in required_packages:
|
79 |
+
try:
|
80 |
+
__import__(package)
|
81 |
+
logger.info(f"β
{package} is available")
|
82 |
+
except ImportError:
|
83 |
+
logger.error(f"β {package} is not available")
|
84 |
+
|
85 |
+
def test_kokoro():
|
86 |
+
"""Test Kokoro TTS functionality"""
|
87 |
+
logger.info("=== Testing Kokoro TTS ===")
|
88 |
+
|
89 |
+
try:
|
90 |
+
# Import after setting up environment
|
91 |
+
import app_config # This will setup cache dirs
|
92 |
+
from kokoro import KPipeline
|
93 |
+
|
94 |
+
logger.info("Initializing Kokoro pipeline...")
|
95 |
+
pipeline = KPipeline(lang_code='a', repo_id='hexgrad/Kokoro-82M')
|
96 |
+
logger.info("β
Kokoro pipeline initialized successfully")
|
97 |
+
|
98 |
+
# Test generation
|
99 |
+
logger.info("Testing speech generation...")
|
100 |
+
text = "Hello, this is a test."
|
101 |
+
generator = pipeline(text, voice='af_heart')
|
102 |
+
|
103 |
+
for i, (gs, ps, audio) in enumerate(generator):
|
104 |
+
logger.info(f"β
Generated audio segment {i}: gs={gs}, ps={ps}, audio shape: {audio.shape}")
|
105 |
+
break
|
106 |
+
|
107 |
+
logger.info("β
Kokoro TTS test completed successfully")
|
108 |
+
return True
|
109 |
+
|
110 |
+
except Exception as e:
|
111 |
+
logger.error(f"β Kokoro TTS test failed: {e}")
|
112 |
+
return False
|
113 |
+
|
114 |
+
def main():
|
115 |
+
"""Main startup function"""
|
116 |
+
logger.info("π Starting Kokoro TTS API setup...")
|
117 |
+
|
118 |
+
check_environment()
|
119 |
+
setup_cache_dirs()
|
120 |
+
check_dependencies()
|
121 |
+
|
122 |
+
if test_kokoro():
|
123 |
+
logger.info("π All checks passed! Starting the API...")
|
124 |
+
# Import and start the app
|
125 |
+
import uvicorn
|
126 |
+
uvicorn.run("app:app", host="0.0.0.0", port=7860, log_level="info")
|
127 |
+
else:
|
128 |
+
logger.error("β Setup failed. Please check the logs above.")
|
129 |
+
sys.exit(1)
|
130 |
+
|
131 |
+
if __name__ == "__main__":
|
132 |
+
main()
|
test.py
CHANGED
@@ -1,9 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from kokoro import KPipeline
|
2 |
import soundfile as sf
|
3 |
import torch
|
4 |
|
5 |
# Initialize Kokoro pipeline
|
6 |
-
pipeline = KPipeline(lang_code='a')
|
7 |
|
8 |
# Text to convert to speech
|
9 |
text = '''
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
# Configure cache directories for Hugging Face Spaces
|
4 |
+
os.environ['HF_HOME'] = '/tmp/hf_cache'
|
5 |
+
os.environ['TRANSFORMERS_CACHE'] = '/tmp/hf_cache'
|
6 |
+
os.environ['HF_HUB_CACHE'] = '/tmp/hf_cache'
|
7 |
+
os.environ['TORCH_HOME'] = '/tmp/torch_cache'
|
8 |
+
|
9 |
+
# Create cache directories
|
10 |
+
os.makedirs('/tmp/hf_cache', exist_ok=True)
|
11 |
+
os.makedirs('/tmp/torch_cache', exist_ok=True)
|
12 |
+
|
13 |
from kokoro import KPipeline
|
14 |
import soundfile as sf
|
15 |
import torch
|
16 |
|
17 |
# Initialize Kokoro pipeline
|
18 |
+
pipeline = KPipeline(lang_code='a', repo_id='hexgrad/Kokoro-82M')
|
19 |
|
20 |
# Text to convert to speech
|
21 |
text = '''
|
test_kokoro_install.py
CHANGED
@@ -1 +1,93 @@
|
|
1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
"""
|
3 |
+
Simple test script to verify Kokoro TTS installation and functionality.
|
4 |
+
"""
|
5 |
+
|
6 |
+
import os
|
7 |
+
|
8 |
+
# Configure cache directories for Hugging Face Spaces
|
9 |
+
os.environ['HF_HOME'] = '/tmp/hf_cache'
|
10 |
+
os.environ['TRANSFORMERS_CACHE'] = '/tmp/hf_cache'
|
11 |
+
os.environ['HF_HUB_CACHE'] = '/tmp/hf_cache'
|
12 |
+
os.environ['TORCH_HOME'] = '/tmp/torch_cache'
|
13 |
+
|
14 |
+
# Create cache directories
|
15 |
+
os.makedirs('/tmp/hf_cache', exist_ok=True)
|
16 |
+
os.makedirs('/tmp/torch_cache', exist_ok=True)
|
17 |
+
|
18 |
+
def test_kokoro_import():
|
19 |
+
"""Test if Kokoro can be imported"""
|
20 |
+
try:
|
21 |
+
from kokoro import KPipeline
|
22 |
+
import soundfile as sf
|
23 |
+
import torch
|
24 |
+
print("β
All required packages imported successfully!")
|
25 |
+
return True
|
26 |
+
except ImportError as e:
|
27 |
+
print(f"β Import error: {e}")
|
28 |
+
return False
|
29 |
+
|
30 |
+
def test_kokoro_pipeline():
|
31 |
+
"""Test if Kokoro pipeline can be initialized"""
|
32 |
+
try:
|
33 |
+
from kokoro import KPipeline
|
34 |
+
pipeline = KPipeline(lang_code='a', repo_id='hexgrad/Kokoro-82M')
|
35 |
+
print("β
Kokoro pipeline initialized successfully!")
|
36 |
+
return True
|
37 |
+
except Exception as e:
|
38 |
+
print(f"β Pipeline initialization error: {e}")
|
39 |
+
return False
|
40 |
+
|
41 |
+
def test_kokoro_generation():
|
42 |
+
"""Test if Kokoro can generate speech"""
|
43 |
+
try:
|
44 |
+
from kokoro import KPipeline
|
45 |
+
import soundfile as sf
|
46 |
+
|
47 |
+
pipeline = KPipeline(lang_code='a', repo_id='hexgrad/Kokoro-82M')
|
48 |
+
text = "Hello, this is a test of Kokoro TTS."
|
49 |
+
|
50 |
+
generator = pipeline(text, voice='af_heart')
|
51 |
+
|
52 |
+
for i, (gs, ps, audio) in enumerate(generator):
|
53 |
+
print(f"β
Generated audio segment {i}: gs={gs}, ps={ps}")
|
54 |
+
# Save test audio
|
55 |
+
sf.write('test_kokoro.wav', audio, 24000)
|
56 |
+
print("β
Test audio saved as 'test_kokoro.wav'")
|
57 |
+
break # Just test the first segment
|
58 |
+
|
59 |
+
return True
|
60 |
+
except Exception as e:
|
61 |
+
print(f"β Speech generation error: {e}")
|
62 |
+
return False
|
63 |
+
|
64 |
+
def main():
|
65 |
+
"""Run all tests"""
|
66 |
+
print("π€ Testing Kokoro TTS Installation")
|
67 |
+
print("=" * 40)
|
68 |
+
|
69 |
+
tests = [
|
70 |
+
("Import Test", test_kokoro_import),
|
71 |
+
("Pipeline Test", test_kokoro_pipeline),
|
72 |
+
("Generation Test", test_kokoro_generation)
|
73 |
+
]
|
74 |
+
|
75 |
+
passed = 0
|
76 |
+
total = len(tests)
|
77 |
+
|
78 |
+
for test_name, test_func in tests:
|
79 |
+
print(f"\nπ Running {test_name}...")
|
80 |
+
if test_func():
|
81 |
+
passed += 1
|
82 |
+
else:
|
83 |
+
print(f"β {test_name} failed!")
|
84 |
+
|
85 |
+
print(f"\nπ Results: {passed}/{total} tests passed")
|
86 |
+
|
87 |
+
if passed == total:
|
88 |
+
print("π All tests passed! Kokoro TTS is ready to use.")
|
89 |
+
else:
|
90 |
+
print("β οΈ Some tests failed. Please check the installation.")
|
91 |
+
|
92 |
+
if __name__ == "__main__":
|
93 |
+
main()
|