137 lines
4.7 KiB
Python
137 lines
4.7 KiB
Python
import os
|
||
import json
|
||
from pathlib import Path
|
||
from dotenv import load_dotenv
|
||
|
||
# 基础路径配置
|
||
BASE_DIR = Path(__file__).parent.parent.parent
|
||
REPO_DIR = BASE_DIR.parent
|
||
UPLOAD_DIR = BASE_DIR / "uploads"
|
||
AUDIO_DIR = UPLOAD_DIR / "audio"
|
||
TEMP_UPLOAD_DIR = UPLOAD_DIR / "temp_audio"
|
||
MARKDOWN_DIR = UPLOAD_DIR / "markdown"
|
||
CLIENT_DIR = UPLOAD_DIR / "clients"
|
||
EXTERNAL_APPS_DIR = UPLOAD_DIR / "external_apps"
|
||
USER_DIR = UPLOAD_DIR / "user"
|
||
LEGACY_VOICEPRINT_DIR = USER_DIR / "voiceprint"
|
||
LEGACY_AVATAR_DIR = USER_DIR / "avatar"
|
||
VOICEPRINT_DIR = USER_DIR
|
||
AVATAR_DIR = USER_DIR
|
||
|
||
|
||
def _load_env_file(dotenv_path: Path) -> None:
|
||
if dotenv_path.exists():
|
||
load_dotenv(dotenv_path=dotenv_path, override=False)
|
||
|
||
|
||
# 优先读取仓库根目录 .env,再读取 backend/.env;
|
||
# 已存在的环境变量(例如 Docker Compose 注入)保持最高优先级。
|
||
_load_env_file(REPO_DIR / ".env")
|
||
_load_env_file(BASE_DIR / ".env")
|
||
|
||
|
||
def _get_env(*names: str, default: str | None = None, allow_blank: bool = True) -> str | None:
|
||
for name in names:
|
||
value = os.getenv(name)
|
||
if value is None:
|
||
continue
|
||
value = value.strip() if isinstance(value, str) else value
|
||
if value == "" and not allow_blank:
|
||
continue
|
||
return value
|
||
return default
|
||
|
||
|
||
def _get_int_env(*names: str, default: int) -> int:
|
||
raw_value = _get_env(*names, default=str(default), allow_blank=False)
|
||
try:
|
||
return int(raw_value) if raw_value is not None else default
|
||
except (TypeError, ValueError):
|
||
return default
|
||
|
||
|
||
def _normalize_base_url(value: str | None) -> str:
|
||
normalized = str(value or "").strip().rstrip("/")
|
||
return normalized or "http://localhost"
|
||
|
||
|
||
def get_user_data_dir(user_id: int | str) -> Path:
|
||
return USER_DIR / str(user_id)
|
||
|
||
|
||
def get_user_voiceprint_dir(user_id: int | str) -> Path:
|
||
return get_user_data_dir(user_id) / "voiceprint"
|
||
|
||
|
||
def get_user_avatar_dir(user_id: int | str) -> Path:
|
||
return get_user_data_dir(user_id) / "avatar"
|
||
|
||
# 文件上传配置
|
||
ALLOWED_EXTENSIONS = {".mp3", ".wav", ".m4a", ".mpeg", ".mp4"}
|
||
ALLOWED_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
|
||
ALLOWED_VOICEPRINT_EXTENSIONS = {".wav"}
|
||
ALLOWED_CLIENT_EXTENSIONS = {".apk", ".exe", ".dmg", ".deb", ".rpm", ".pkg", ".msi", ".zip", ".tar.gz"}
|
||
MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB
|
||
MAX_IMAGE_SIZE = 10 * 1024 * 1024 # 10MB
|
||
MAX_CLIENT_SIZE = 500 * 1024 * 1024 # 500MB for client installers
|
||
|
||
# 确保上传目录存在
|
||
UPLOAD_DIR.mkdir(exist_ok=True)
|
||
AUDIO_DIR.mkdir(exist_ok=True)
|
||
MARKDOWN_DIR.mkdir(exist_ok=True)
|
||
CLIENT_DIR.mkdir(exist_ok=True)
|
||
EXTERNAL_APPS_DIR.mkdir(exist_ok=True)
|
||
USER_DIR.mkdir(exist_ok=True)
|
||
LEGACY_VOICEPRINT_DIR.mkdir(exist_ok=True)
|
||
LEGACY_AVATAR_DIR.mkdir(exist_ok=True)
|
||
|
||
|
||
# 数据库配置
|
||
DATABASE_CONFIG = {
|
||
'host': _get_env('DB_HOST', 'MYSQL_HOST', default='127.0.0.1', allow_blank=False),
|
||
'user': _get_env('DB_USER', 'MYSQL_USER', default='root', allow_blank=False),
|
||
'password': _get_env('DB_PASSWORD', 'MYSQL_PASSWORD', default=''),
|
||
'database': _get_env('DB_NAME', 'MYSQL_DATABASE', default='imeeting', allow_blank=False),
|
||
'port': _get_int_env('DB_PORT', 'MYSQL_PORT', default=3306),
|
||
'charset': 'utf8mb4'
|
||
}
|
||
|
||
# API配置
|
||
API_CONFIG = {
|
||
'host': _get_env('API_HOST', default='0.0.0.0', allow_blank=False),
|
||
'port': _get_int_env('API_PORT', default=8000)
|
||
}
|
||
|
||
# 七牛云配置
|
||
# QINIU_ACCESS_KEY = os.getenv('QINIU_ACCESS_KEY', 'A0tp96HCtg-wZCughTgi5vc2pJnw3btClwxRE_e8')
|
||
# QINIU_SECRET_KEY = os.getenv('QINIU_SECRET_KEY', 'Lj-MSHpaVbmzpS86kMIjmwikvYOT9iPBjCk9hm6k')
|
||
# QINIU_BUCKET = os.getenv('QINIU_BUCKET', 'imeeting_dev')
|
||
# QINIU_DOMAIN = os.getenv('QINIU_DOMAIN', 't0vogyxkz.hn-bkt.clouddn.com')
|
||
|
||
# 应用配置
|
||
APP_CONFIG = {
|
||
'base_url': _normalize_base_url(_get_env('BASE_URL', default='http://localhost', allow_blank=False))
|
||
}
|
||
|
||
# Redis配置
|
||
REDIS_CONFIG = {
|
||
'host': _get_env('REDIS_HOST', default='127.0.0.1', allow_blank=False),
|
||
'port': _get_int_env('REDIS_PORT', default=6379),
|
||
'db': _get_int_env('REDIS_DB', default=0),
|
||
'password': _get_env('REDIS_PASSWORD', default=''),
|
||
'decode_responses': True
|
||
}
|
||
|
||
# 转录轮询配置 - 用于 upload-audio-complete 接口
|
||
TRANSCRIPTION_POLL_CONFIG = {
|
||
'poll_interval': _get_int_env('TRANSCRIPTION_POLL_INTERVAL', default=10), # 轮询间隔:10秒
|
||
'max_wait_time': _get_int_env('TRANSCRIPTION_MAX_WAIT_TIME', default=1800), # 最大等待:30分钟
|
||
}
|
||
|
||
# 后台任务配置
|
||
BACKGROUND_TASK_CONFIG = {
|
||
'summary_workers': _get_int_env('SUMMARY_TASK_MAX_WORKERS', default=2),
|
||
'monitor_workers': _get_int_env('MONITOR_TASK_MAX_WORKERS', default=8),
|
||
'transcription_status_cache_ttl': _get_int_env('TRANSCRIPTION_STATUS_CACHE_TTL', default=3),
|
||
}
|