feat: Add embedded backend packaging for all-in-one deployment
- Add backend/run_server.py entry point for embedded deployment - Add backend/build.py PyInstaller script for backend packaging - Modify config.py to support frozen executable paths - Extend client/config.json with backend configuration section - Add backend sidecar management in Electron main process - Add Whisper model download progress reporting - Update build-client.bat with --embedded-backend flag - Update DEPLOYMENT.md with all-in-one deployment documentation This enables packaging frontend and backend into a single executable for simplified enterprise deployment. Backward compatible with existing separate deployment mode (backend.embedded: false). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,20 @@
|
||||
import os
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def get_base_dir() -> str:
|
||||
"""Get base directory, supporting PyInstaller frozen executables."""
|
||||
if getattr(sys, "frozen", False):
|
||||
# Running as PyInstaller bundle
|
||||
return os.path.dirname(sys.executable)
|
||||
else:
|
||||
# Running as script - go up two levels from app/config.py to backend/
|
||||
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
class Settings:
|
||||
# Server Configuration
|
||||
BACKEND_HOST: str = os.getenv("BACKEND_HOST", "0.0.0.0")
|
||||
@@ -49,16 +60,30 @@ class Settings:
|
||||
"""Return supported audio formats as a set."""
|
||||
return set(self.SUPPORTED_AUDIO_FORMATS.split(","))
|
||||
|
||||
def get_template_dir(self, base_dir: str) -> str:
|
||||
"""Get template directory path, resolving relative paths."""
|
||||
def get_template_dir(self, base_dir: str | None = None) -> str:
|
||||
"""Get template directory path, resolving relative paths.
|
||||
|
||||
Args:
|
||||
base_dir: Base directory for relative paths. If None, uses get_base_dir()
|
||||
which supports frozen executables.
|
||||
"""
|
||||
if base_dir is None:
|
||||
base_dir = get_base_dir()
|
||||
if self.TEMPLATE_DIR:
|
||||
if os.path.isabs(self.TEMPLATE_DIR):
|
||||
return self.TEMPLATE_DIR
|
||||
return os.path.join(base_dir, self.TEMPLATE_DIR)
|
||||
return os.path.join(base_dir, "template")
|
||||
|
||||
def get_record_dir(self, base_dir: str) -> str:
|
||||
"""Get record directory path, resolving relative paths."""
|
||||
def get_record_dir(self, base_dir: str | None = None) -> str:
|
||||
"""Get record directory path, resolving relative paths.
|
||||
|
||||
Args:
|
||||
base_dir: Base directory for relative paths. If None, uses get_base_dir()
|
||||
which supports frozen executables.
|
||||
"""
|
||||
if base_dir is None:
|
||||
base_dir = get_base_dir()
|
||||
if self.RECORD_DIR:
|
||||
if os.path.isabs(self.RECORD_DIR):
|
||||
return self.RECORD_DIR
|
||||
|
||||
Reference in New Issue
Block a user