current workign version using chatterbox.
This commit is contained in:
parent
aeb0f7b638
commit
948712bb3f
|
@ -359,7 +359,7 @@ The API uses the following directory structure (configurable in `app/config.py`)
|
||||||
- **Temporary Files**: `{PROJECT_ROOT}/tts_temp_outputs/`
|
- **Temporary Files**: `{PROJECT_ROOT}/tts_temp_outputs/`
|
||||||
|
|
||||||
### CORS Settings
|
### CORS Settings
|
||||||
- Allowed Origins: `http://localhost:8001`, `http://127.0.0.1:8001`
|
- Allowed Origins: `http://localhost:8001`, `http://127.0.0.1:8001` (plus any `FRONTEND_HOST:FRONTEND_PORT` when using `start_servers.py`)
|
||||||
- Allowed Methods: All
|
- Allowed Methods: All
|
||||||
- Allowed Headers: All
|
- Allowed Headers: All
|
||||||
- Credentials: Enabled
|
- Credentials: Enabled
|
||||||
|
|
|
@ -58,7 +58,7 @@ The application uses environment variables for configuration. Three `.env` files
|
||||||
- `VITE_DEV_SERVER_HOST`: Frontend development server host
|
- `VITE_DEV_SERVER_HOST`: Frontend development server host
|
||||||
|
|
||||||
#### CORS Configuration
|
#### CORS Configuration
|
||||||
- `CORS_ORIGINS`: Comma-separated list of allowed origins
|
- `CORS_ORIGINS`: Comma-separated list of allowed origins. When using `start_servers.py` with the default `FRONTEND_HOST=0.0.0.0` and no explicit `CORS_ORIGINS`, CORS will allow all origins (wildcard) to simplify development.
|
||||||
|
|
||||||
#### Device Configuration
|
#### Device Configuration
|
||||||
- `DEVICE`: Device for TTS model (auto, cpu, cuda, mps)
|
- `DEVICE`: Device for TTS model (auto, cpu, cuda, mps)
|
||||||
|
@ -101,7 +101,7 @@ CORS_ORIGINS=http://localhost:3000
|
||||||
### Common Issues
|
### Common Issues
|
||||||
|
|
||||||
1. **Permission Errors**: Ensure the `PROJECT_ROOT` directory is writable
|
1. **Permission Errors**: Ensure the `PROJECT_ROOT` directory is writable
|
||||||
2. **CORS Errors**: Check that your frontend URL is in `CORS_ORIGINS`
|
2. **CORS Errors**: Check that your frontend URL is in `CORS_ORIGINS`. (When using `start_servers.py`, your specified `FRONTEND_HOST:FRONTEND_PORT` will be auto‑included.)
|
||||||
3. **Model Loading Errors**: Verify `DEVICE` setting matches your hardware
|
3. **Model Loading Errors**: Verify `DEVICE` setting matches your hardware
|
||||||
4. **Path Errors**: Ensure all path variables point to existing, accessible directories
|
4. **Path Errors**: Ensure all path variables point to existing, accessible directories
|
||||||
|
|
||||||
|
|
|
@ -149,5 +149,5 @@ The application automatically:
|
||||||
- **"Skipping unknown speaker"**: Configure speaker in `speaker_data/speakers.yaml`
|
- **"Skipping unknown speaker"**: Configure speaker in `speaker_data/speakers.yaml`
|
||||||
- **"Sample file not found"**: Verify audio files exist in `speaker_data/speaker_samples/`
|
- **"Sample file not found"**: Verify audio files exist in `speaker_data/speaker_samples/`
|
||||||
- **Memory issues**: Use model reinitialization options for long content
|
- **Memory issues**: Use model reinitialization options for long content
|
||||||
- **CORS errors**: Check frontend/backend port configuration
|
- **CORS errors**: Check frontend/backend port configuration (frontend origin is auto-included when using `start_servers.py`)
|
||||||
- **Import errors**: Run `python import_helper.py` to check dependencies
|
- **Import errors**: Run `python import_helper.py` to check dependencies
|
||||||
|
|
|
@ -6,20 +6,34 @@ from dotenv import load_dotenv
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
# Project root - can be overridden by environment variable
|
# Project root - can be overridden by environment variable
|
||||||
PROJECT_ROOT = Path(os.getenv("PROJECT_ROOT", Path(__file__).parent.parent.parent)).resolve()
|
PROJECT_ROOT = Path(
|
||||||
|
os.getenv("PROJECT_ROOT", Path(__file__).parent.parent.parent)
|
||||||
|
).resolve()
|
||||||
|
|
||||||
# Directory paths
|
# Directory paths
|
||||||
SPEAKER_DATA_BASE_DIR = Path(os.getenv("SPEAKER_DATA_BASE_DIR", str(PROJECT_ROOT / "speaker_data")))
|
SPEAKER_DATA_BASE_DIR = Path(
|
||||||
SPEAKER_SAMPLES_DIR = Path(os.getenv("SPEAKER_SAMPLES_DIR", str(SPEAKER_DATA_BASE_DIR / "speaker_samples")))
|
os.getenv("SPEAKER_DATA_BASE_DIR", str(PROJECT_ROOT / "speaker_data"))
|
||||||
SPEAKERS_YAML_FILE = Path(os.getenv("SPEAKERS_YAML_FILE", str(SPEAKER_DATA_BASE_DIR / "speakers.yaml")))
|
)
|
||||||
|
SPEAKER_SAMPLES_DIR = Path(
|
||||||
|
os.getenv("SPEAKER_SAMPLES_DIR", str(SPEAKER_DATA_BASE_DIR / "speaker_samples"))
|
||||||
|
)
|
||||||
|
SPEAKERS_YAML_FILE = Path(
|
||||||
|
os.getenv("SPEAKERS_YAML_FILE", str(SPEAKER_DATA_BASE_DIR / "speakers.yaml"))
|
||||||
|
)
|
||||||
|
|
||||||
# TTS temporary output path (used by DialogProcessorService)
|
# TTS temporary output path (used by DialogProcessorService)
|
||||||
TTS_TEMP_OUTPUT_DIR = Path(os.getenv("TTS_TEMP_OUTPUT_DIR", str(PROJECT_ROOT / "tts_temp_outputs")))
|
TTS_TEMP_OUTPUT_DIR = Path(
|
||||||
|
os.getenv("TTS_TEMP_OUTPUT_DIR", str(PROJECT_ROOT / "tts_temp_outputs"))
|
||||||
|
)
|
||||||
|
|
||||||
# Final dialog output path (used by Dialog router and served by main app)
|
# Final dialog output path (used by Dialog router and served by main app)
|
||||||
# These are stored within the 'backend' directory to be easily servable.
|
# These are stored within the 'backend' directory to be easily servable.
|
||||||
DIALOG_OUTPUT_PARENT_DIR = PROJECT_ROOT / "backend"
|
DIALOG_OUTPUT_PARENT_DIR = PROJECT_ROOT / "backend"
|
||||||
DIALOG_GENERATED_DIR = Path(os.getenv("DIALOG_GENERATED_DIR", str(DIALOG_OUTPUT_PARENT_DIR / "tts_generated_dialogs")))
|
DIALOG_GENERATED_DIR = Path(
|
||||||
|
os.getenv(
|
||||||
|
"DIALOG_GENERATED_DIR", str(DIALOG_OUTPUT_PARENT_DIR / "tts_generated_dialogs")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Alias for clarity and backward compatibility
|
# Alias for clarity and backward compatibility
|
||||||
DIALOG_OUTPUT_DIR = DIALOG_GENERATED_DIR
|
DIALOG_OUTPUT_DIR = DIALOG_GENERATED_DIR
|
||||||
|
@ -29,8 +43,26 @@ HOST = os.getenv("HOST", "0.0.0.0")
|
||||||
PORT = int(os.getenv("PORT", "8000"))
|
PORT = int(os.getenv("PORT", "8000"))
|
||||||
RELOAD = os.getenv("RELOAD", "true").lower() == "true"
|
RELOAD = os.getenv("RELOAD", "true").lower() == "true"
|
||||||
|
|
||||||
# CORS configuration
|
# CORS configuration: determine allowed origins based on env & frontend binding
|
||||||
CORS_ORIGINS = [origin.strip() for origin in os.getenv("CORS_ORIGINS", "http://localhost:8001,http://127.0.0.1:8001").split(",")]
|
_cors_env = os.getenv("CORS_ORIGINS", "")
|
||||||
|
_frontend_host = os.getenv("FRONTEND_HOST")
|
||||||
|
_frontend_port = os.getenv("FRONTEND_PORT")
|
||||||
|
|
||||||
|
# If the dev server is bound to 0.0.0.0 (all interfaces), allow all origins
|
||||||
|
if _frontend_host == "0.0.0.0": # dev convenience when binding wildcard
|
||||||
|
CORS_ORIGINS = ["*"]
|
||||||
|
elif _cors_env:
|
||||||
|
# parse comma-separated origins, strip whitespace
|
||||||
|
CORS_ORIGINS = [origin.strip() for origin in _cors_env.split(",") if origin.strip()]
|
||||||
|
else:
|
||||||
|
# default to allow all origins in development
|
||||||
|
CORS_ORIGINS = ["*"]
|
||||||
|
|
||||||
|
# Auto-include specific frontend origin when not using wildcard CORS
|
||||||
|
if CORS_ORIGINS != ["*"] and _frontend_host and _frontend_port:
|
||||||
|
_frontend_origin = f"http://{_frontend_host.strip()}:{_frontend_port.strip()}"
|
||||||
|
if _frontend_origin not in CORS_ORIGINS:
|
||||||
|
CORS_ORIGINS.append(_frontend_origin)
|
||||||
|
|
||||||
# Device configuration
|
# Device configuration
|
||||||
DEVICE = os.getenv("DEVICE", "auto")
|
DEVICE = os.getenv("DEVICE", "auto")
|
||||||
|
|
|
@ -13,8 +13,15 @@ const getEnvVar = (name, defaultValue) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// API Configuration
|
// API Configuration
|
||||||
export const API_BASE_URL = getEnvVar('VITE_API_BASE_URL', 'http://localhost:8000');
|
// Default to the same hostname as the frontend, on port 8000 (override via VITE_API_BASE_URL*)
|
||||||
export const API_BASE_URL_WITH_PREFIX = getEnvVar('VITE_API_BASE_URL_WITH_PREFIX', 'http://localhost:8000/api');
|
const _defaultHost = (typeof window !== 'undefined' && window.location?.hostname) || 'localhost';
|
||||||
|
const _defaultPort = getEnvVar('VITE_API_BASE_URL_PORT', '8000');
|
||||||
|
const _defaultBase = `http://${_defaultHost}:${_defaultPort}`;
|
||||||
|
export const API_BASE_URL = getEnvVar('VITE_API_BASE_URL', _defaultBase);
|
||||||
|
export const API_BASE_URL_WITH_PREFIX = getEnvVar(
|
||||||
|
'VITE_API_BASE_URL_WITH_PREFIX',
|
||||||
|
`${_defaultBase}/api`
|
||||||
|
);
|
||||||
|
|
||||||
// For file serving (same as API_BASE_URL since files are served from the same server)
|
// For file serving (same as API_BASE_URL since files are served from the same server)
|
||||||
export const API_BASE_URL_FOR_FILES = API_BASE_URL;
|
export const API_BASE_URL_FOR_FILES = API_BASE_URL;
|
||||||
|
|
|
@ -28,3 +28,6 @@ dd3552d9-f4e8-49ed-9892-f9e67afcf23c:
|
||||||
2cdd6d3d-c533-44bf-a5f6-cc83bd089d32:
|
2cdd6d3d-c533-44bf-a5f6-cc83bd089d32:
|
||||||
name: Grace
|
name: Grace
|
||||||
sample_path: speaker_samples/2cdd6d3d-c533-44bf-a5f6-cc83bd089d32.wav
|
sample_path: speaker_samples/2cdd6d3d-c533-44bf-a5f6-cc83bd089d32.wav
|
||||||
|
3d3e85db-3d67-4488-94b2-ffc189fbb287:
|
||||||
|
name: RCB
|
||||||
|
sample_path: speaker_samples/3d3e85db-3d67-4488-94b2-ffc189fbb287.wav
|
||||||
|
|
|
@ -14,28 +14,37 @@ from pathlib import Path
|
||||||
# Try to load environment variables, but don't fail if dotenv is not available
|
# Try to load environment variables, but don't fail if dotenv is not available
|
||||||
try:
|
try:
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("python-dotenv not installed, using system environment variables only")
|
print("python-dotenv not installed, using system environment variables only")
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
BACKEND_PORT = int(os.getenv('BACKEND_PORT', '8000'))
|
BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
|
||||||
BACKEND_HOST = os.getenv('BACKEND_HOST', '0.0.0.0')
|
BACKEND_HOST = os.getenv("BACKEND_HOST", "0.0.0.0")
|
||||||
FRONTEND_PORT = int(os.getenv('FRONTEND_PORT', '8001'))
|
# Frontend host/port (for dev server binding)
|
||||||
FRONTEND_HOST = os.getenv('FRONTEND_HOST', '127.0.0.1')
|
FRONTEND_PORT = int(os.getenv("FRONTEND_PORT", "8001"))
|
||||||
|
FRONTEND_HOST = os.getenv("FRONTEND_HOST", "0.0.0.0")
|
||||||
|
|
||||||
|
# Export frontend host/port so backend CORS config can pick them up automatically
|
||||||
|
os.environ["FRONTEND_HOST"] = FRONTEND_HOST
|
||||||
|
os.environ["FRONTEND_PORT"] = str(FRONTEND_PORT)
|
||||||
|
|
||||||
# Get project root directory
|
# Get project root directory
|
||||||
PROJECT_ROOT = Path(__file__).parent.absolute()
|
PROJECT_ROOT = Path(__file__).parent.absolute()
|
||||||
|
|
||||||
|
|
||||||
def run_backend():
|
def run_backend():
|
||||||
"""Run the backend FastAPI server"""
|
"""Run the backend FastAPI server"""
|
||||||
os.chdir(PROJECT_ROOT / "backend")
|
os.chdir(PROJECT_ROOT / "backend")
|
||||||
cmd = [
|
cmd = [
|
||||||
sys.executable, "-m", "uvicorn",
|
sys.executable,
|
||||||
|
"-m",
|
||||||
|
"uvicorn",
|
||||||
"app.main:app",
|
"app.main:app",
|
||||||
"--reload",
|
"--reload",
|
||||||
f"--host={BACKEND_HOST}",
|
f"--host={BACKEND_HOST}",
|
||||||
f"--port={BACKEND_PORT}"
|
f"--port={BACKEND_PORT}",
|
||||||
]
|
]
|
||||||
|
|
||||||
print(f"\n{'='*50}")
|
print(f"\n{'='*50}")
|
||||||
|
@ -48,9 +57,10 @@ def run_backend():
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
bufsize=1
|
bufsize=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_frontend():
|
def run_frontend():
|
||||||
"""Run the frontend development server"""
|
"""Run the frontend development server"""
|
||||||
frontend_dir = PROJECT_ROOT / "frontend"
|
frontend_dir = PROJECT_ROOT / "frontend"
|
||||||
|
@ -71,15 +81,17 @@ def run_frontend():
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
bufsize=1
|
bufsize=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def print_process_output(process, prefix):
|
def print_process_output(process, prefix):
|
||||||
"""Print process output with a prefix"""
|
"""Print process output with a prefix"""
|
||||||
for line in iter(process.stdout.readline, ''):
|
for line in iter(process.stdout.readline, ""):
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
print(f"{prefix} | {line}", end='')
|
print(f"{prefix} | {line}", end="")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function to start both servers"""
|
"""Main function to start both servers"""
|
||||||
|
@ -96,14 +108,10 @@ def main():
|
||||||
|
|
||||||
# Create threads to monitor and print output
|
# Create threads to monitor and print output
|
||||||
backend_monitor = threading.Thread(
|
backend_monitor = threading.Thread(
|
||||||
target=print_process_output,
|
target=print_process_output, args=(backend_process, "BACKEND"), daemon=True
|
||||||
args=(backend_process, "BACKEND"),
|
|
||||||
daemon=True
|
|
||||||
)
|
)
|
||||||
frontend_monitor = threading.Thread(
|
frontend_monitor = threading.Thread(
|
||||||
target=print_process_output,
|
target=print_process_output, args=(frontend_process, "FRONTEND"), daemon=True
|
||||||
args=(frontend_process, "FRONTEND"),
|
|
||||||
daemon=True
|
|
||||||
)
|
)
|
||||||
|
|
||||||
backend_monitor.start()
|
backend_monitor.start()
|
||||||
|
@ -134,5 +142,6 @@ def main():
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
signal_handler(None, None)
|
signal_handler(None, None)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Reference in New Issue