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/`
|
||||
|
||||
### 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 Headers: All
|
||||
- Credentials: Enabled
|
||||
|
|
|
@ -58,7 +58,7 @@ The application uses environment variables for configuration. Three `.env` files
|
|||
- `VITE_DEV_SERVER_HOST`: Frontend development server host
|
||||
|
||||
#### 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`: Device for TTS model (auto, cpu, cuda, mps)
|
||||
|
@ -101,7 +101,7 @@ CORS_ORIGINS=http://localhost:3000
|
|||
### Common Issues
|
||||
|
||||
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
|
||||
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`
|
||||
- **"Sample file not found"**: Verify audio files exist in `speaker_data/speaker_samples/`
|
||||
- **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
|
||||
|
|
|
@ -6,20 +6,34 @@ from dotenv import load_dotenv
|
|||
load_dotenv()
|
||||
|
||||
# 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
|
||||
SPEAKER_DATA_BASE_DIR = Path(os.getenv("SPEAKER_DATA_BASE_DIR", str(PROJECT_ROOT / "speaker_data")))
|
||||
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")))
|
||||
SPEAKER_DATA_BASE_DIR = Path(
|
||||
os.getenv("SPEAKER_DATA_BASE_DIR", str(PROJECT_ROOT / "speaker_data"))
|
||||
)
|
||||
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_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)
|
||||
# These are stored within the 'backend' directory to be easily servable.
|
||||
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
|
||||
DIALOG_OUTPUT_DIR = DIALOG_GENERATED_DIR
|
||||
|
@ -29,8 +43,26 @@ HOST = os.getenv("HOST", "0.0.0.0")
|
|||
PORT = int(os.getenv("PORT", "8000"))
|
||||
RELOAD = os.getenv("RELOAD", "true").lower() == "true"
|
||||
|
||||
# CORS configuration
|
||||
CORS_ORIGINS = [origin.strip() for origin in os.getenv("CORS_ORIGINS", "http://localhost:8001,http://127.0.0.1:8001").split(",")]
|
||||
# CORS configuration: determine allowed origins based on env & frontend binding
|
||||
_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 = os.getenv("DEVICE", "auto")
|
||||
|
|
|
@ -13,8 +13,15 @@ const getEnvVar = (name, defaultValue) => {
|
|||
};
|
||||
|
||||
// API Configuration
|
||||
export const API_BASE_URL = getEnvVar('VITE_API_BASE_URL', 'http://localhost:8000');
|
||||
export const API_BASE_URL_WITH_PREFIX = getEnvVar('VITE_API_BASE_URL_WITH_PREFIX', 'http://localhost:8000/api');
|
||||
// Default to the same hostname as the frontend, on port 8000 (override via VITE_API_BASE_URL*)
|
||||
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)
|
||||
export const API_BASE_URL_FOR_FILES = API_BASE_URL;
|
||||
|
|
|
@ -28,3 +28,6 @@ dd3552d9-f4e8-49ed-9892-f9e67afcf23c:
|
|||
2cdd6d3d-c533-44bf-a5f6-cc83bd089d32:
|
||||
name: Grace
|
||||
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,101 +14,109 @@ from pathlib import Path
|
|||
# Try to load environment variables, but don't fail if dotenv is not available
|
||||
try:
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
except ImportError:
|
||||
print("python-dotenv not installed, using system environment variables only")
|
||||
|
||||
# Configuration
|
||||
BACKEND_PORT = int(os.getenv('BACKEND_PORT', '8000'))
|
||||
BACKEND_HOST = os.getenv('BACKEND_HOST', '0.0.0.0')
|
||||
FRONTEND_PORT = int(os.getenv('FRONTEND_PORT', '8001'))
|
||||
FRONTEND_HOST = os.getenv('FRONTEND_HOST', '127.0.0.1')
|
||||
BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
|
||||
BACKEND_HOST = os.getenv("BACKEND_HOST", "0.0.0.0")
|
||||
# Frontend host/port (for dev server binding)
|
||||
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
|
||||
PROJECT_ROOT = Path(__file__).parent.absolute()
|
||||
|
||||
|
||||
def run_backend():
|
||||
"""Run the backend FastAPI server"""
|
||||
os.chdir(PROJECT_ROOT / "backend")
|
||||
cmd = [
|
||||
sys.executable, "-m", "uvicorn",
|
||||
"app.main:app",
|
||||
"--reload",
|
||||
f"--host={BACKEND_HOST}",
|
||||
f"--port={BACKEND_PORT}"
|
||||
sys.executable,
|
||||
"-m",
|
||||
"uvicorn",
|
||||
"app.main:app",
|
||||
"--reload",
|
||||
f"--host={BACKEND_HOST}",
|
||||
f"--port={BACKEND_PORT}",
|
||||
]
|
||||
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Starting Backend Server at http://{BACKEND_HOST}:{BACKEND_PORT}")
|
||||
print(f"API docs available at http://{BACKEND_HOST}:{BACKEND_PORT}/docs")
|
||||
print(f"{'='*50}\n")
|
||||
|
||||
|
||||
return subprocess.Popen(
|
||||
cmd,
|
||||
cmd,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True,
|
||||
bufsize=1
|
||||
bufsize=1,
|
||||
)
|
||||
|
||||
|
||||
def run_frontend():
|
||||
"""Run the frontend development server"""
|
||||
frontend_dir = PROJECT_ROOT / "frontend"
|
||||
os.chdir(frontend_dir)
|
||||
|
||||
|
||||
cmd = [sys.executable, "start_dev_server.py"]
|
||||
env = os.environ.copy()
|
||||
env["VITE_DEV_SERVER_HOST"] = FRONTEND_HOST
|
||||
env["VITE_DEV_SERVER_PORT"] = str(FRONTEND_PORT)
|
||||
|
||||
|
||||
print(f"\n{'='*50}")
|
||||
print(f"Starting Frontend Server at http://{FRONTEND_HOST}:{FRONTEND_PORT}")
|
||||
print(f"{'='*50}\n")
|
||||
|
||||
|
||||
return subprocess.Popen(
|
||||
cmd,
|
||||
env=env,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True,
|
||||
bufsize=1
|
||||
bufsize=1,
|
||||
)
|
||||
|
||||
|
||||
def print_process_output(process, prefix):
|
||||
"""Print process output with a prefix"""
|
||||
for line in iter(process.stdout.readline, ''):
|
||||
for line in iter(process.stdout.readline, ""):
|
||||
if not line:
|
||||
break
|
||||
print(f"{prefix} | {line}", end='')
|
||||
print(f"{prefix} | {line}", end="")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function to start both servers"""
|
||||
print("\n🚀 Starting Chatterbox UI Development Environment")
|
||||
|
||||
|
||||
# Start the backend server
|
||||
backend_process = run_backend()
|
||||
|
||||
|
||||
# Give the backend a moment to start
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
# Start the frontend server
|
||||
frontend_process = run_frontend()
|
||||
|
||||
|
||||
# Create threads to monitor and print output
|
||||
backend_monitor = threading.Thread(
|
||||
target=print_process_output,
|
||||
args=(backend_process, "BACKEND"),
|
||||
daemon=True
|
||||
target=print_process_output, args=(backend_process, "BACKEND"), daemon=True
|
||||
)
|
||||
frontend_monitor = threading.Thread(
|
||||
target=print_process_output,
|
||||
args=(frontend_process, "FRONTEND"),
|
||||
daemon=True
|
||||
target=print_process_output, args=(frontend_process, "FRONTEND"), daemon=True
|
||||
)
|
||||
|
||||
|
||||
backend_monitor.start()
|
||||
frontend_monitor.start()
|
||||
|
||||
|
||||
# Setup signal handling for graceful shutdown
|
||||
def signal_handler(sig, frame):
|
||||
print("\n\n🛑 Shutting down servers...")
|
||||
|
@ -117,16 +125,16 @@ def main():
|
|||
# Threads are daemon, so they'll exit when the main thread exits
|
||||
print("✅ Servers stopped successfully")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
|
||||
# Print access information
|
||||
print("\n📋 Access Information:")
|
||||
print(f" • Frontend: http://{FRONTEND_HOST}:{FRONTEND_PORT}")
|
||||
print(f" • Backend API: http://{BACKEND_HOST}:{BACKEND_PORT}/api")
|
||||
print(f" • API Documentation: http://{BACKEND_HOST}:{BACKEND_PORT}/docs")
|
||||
print("\n⚠️ Press Ctrl+C to stop both servers\n")
|
||||
|
||||
|
||||
# Keep the main process running
|
||||
try:
|
||||
while True:
|
||||
|
@ -134,5 +142,6 @@ def main():
|
|||
except KeyboardInterrupt:
|
||||
signal_handler(None, None)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue