aad1548348
- Extract all path/API config to config.py (single source of truth) - Add run.py / burn_only.py / run.bat / burn.bat entry points - burn_only: skip transcription/subtitle gen, fast reburn existing SRTs - Fix title_segments: use transcript keyword time for split point - Fix subtitle: each overlapping title shows max title_duration (not full clip) - Fix burn_only font size: default from 90 to 60 - Delete old run_lesson1.bat/py, temp debug scripts - Update README, ARCHITECTURE, CHANGELOG, add USAGE.md
130 lines
4.3 KiB
Python
130 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
环境配置和常量定义
|
|
|
|
所有硬编码路径和配置集中管理,确保可维护性
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import shutil
|
|
|
|
# ============== 项目根目录 ==============
|
|
def _get_project_root():
|
|
"""获取项目根目录"""
|
|
# Assume this file is in src/core/, so project root is 2 levels up
|
|
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
PROJECT_ROOT = _get_project_root()
|
|
|
|
# ============== FFmpeg路径(动态检测)==============
|
|
def _find_ffmpeg():
|
|
"""动态查找FFmpeg路径"""
|
|
# 1. Check local ffmpeg folder (for portable distribution)
|
|
# Direct: ffmpeg/bin/ffmpeg.exe
|
|
local_ffmpeg = os.path.join(PROJECT_ROOT, "ffmpeg", "bin")
|
|
if os.path.exists(os.path.join(local_ffmpeg, "ffmpeg.exe")):
|
|
return local_ffmpeg
|
|
|
|
# Nested: ffmpeg/ffmpeg-8.1-full_build/bin/ffmpeg.exe
|
|
ffmpeg_base = os.path.join(PROJECT_ROOT, "ffmpeg")
|
|
if os.path.isdir(ffmpeg_base):
|
|
for subdir in os.listdir(ffmpeg_base):
|
|
nested_path = os.path.join(ffmpeg_base, subdir, "bin")
|
|
if os.path.exists(os.path.join(nested_path, "ffmpeg.exe")):
|
|
return nested_path
|
|
|
|
# 2. Check system PATH
|
|
system_ffmpeg = shutil.which("ffmpeg")
|
|
if system_ffmpeg:
|
|
return os.path.dirname(system_ffmpeg)
|
|
|
|
# 3. Return empty - will fail later with clear error
|
|
return ""
|
|
|
|
FFMPEG_BIN = _find_ffmpeg()
|
|
FFMPEG_CMD = os.path.join(FFMPEG_BIN, "ffmpeg.exe") if FFMPEG_BIN else "ffmpeg"
|
|
FFPROBE_CMD = os.path.join(FFMPEG_BIN, "ffprobe.exe") if FFMPEG_BIN else "ffprobe"
|
|
|
|
# ============== Whisper模型(动态检测)==============
|
|
def _find_whisper_model():
|
|
"""查找Whisper模型路径"""
|
|
# 1. Check local whisper_models folder
|
|
local_models = os.path.join(PROJECT_ROOT, "whisper_models")
|
|
if os.path.exists(local_models):
|
|
# Find any model folder
|
|
for name in os.listdir(local_models):
|
|
model_path = os.path.join(local_models, name)
|
|
if os.path.isdir(model_path):
|
|
return model_path.replace('\\', '/')
|
|
|
|
# 2. Check environment variable
|
|
env_path = os.environ.get("WHISPER_MODEL_PATH")
|
|
if env_path and os.path.exists(env_path):
|
|
return env_path.replace('\\', '/')
|
|
|
|
# 3. Default path (for this user's environment)
|
|
default_path = r"D:/AI/LM-Models/faster-whisper/large-v3"
|
|
if os.path.exists(default_path):
|
|
return default_path.replace('\\', '/')
|
|
|
|
return ""
|
|
|
|
WHISPER_MODEL_PATH = _find_whisper_model()
|
|
|
|
# ============== 输出目录默认值 ==============
|
|
DEFAULT_OUTPUT_DIR = os.path.join(PROJECT_ROOT, "output")
|
|
|
|
# ============== 视频参数默认值 ==============
|
|
DEFAULT_VIDEO_PARAMS = {
|
|
"fade_duration": 1,
|
|
"title_duration": 3,
|
|
"title_fontsize": 60,
|
|
"title_color": "FFFF00",
|
|
"subtitle_fontsize": 24,
|
|
"subtitle_color": "FFFFFF",
|
|
"use_fast_whisper": True,
|
|
"whisper_model": "large",
|
|
}
|
|
|
|
# ============== API配置 ==============
|
|
DEFAULT_API_HOST = "https://ark.cn-beijing.volces.com/api/coding/v3"
|
|
API_KEY_ENVS = ["VOLCENGINE_API_KEY", "MINIMAX_API_KEY"]
|
|
|
|
# ============== LLM配置 ==============
|
|
LLM_MODEL = "doubao-seed-2.0-lite"
|
|
LLM_TIMEOUT = 60
|
|
LLM_MAX_RETRIES = 3
|
|
LLM_TITLE_TIMEOUT = 60
|
|
LLM_VALIDATE_TIMEOUT = 30
|
|
|
|
# ============== 字幕样式 ==============
|
|
SUBTITLE_STYLE = "FontName=微软雅黑,FontSize=24,PrimaryColour=&H00FFFFFF"
|
|
|
|
# ============== Windows控制台编码 ==============
|
|
def setup_windows_encoding():
|
|
"""Windows控制台UTF-8编码设置"""
|
|
if sys.platform == 'win32':
|
|
import io
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
|
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
|
|
|
# ============== FFmpeg PATH设置 ==============
|
|
def setup_ffmpeg_path():
|
|
"""将FFmpeg添加到PATH(仅当使用本地FFmpeg时)"""
|
|
if FFMPEG_BIN and FFMPEG_BIN not in os.environ.get('PATH', ''):
|
|
os.environ['PATH'] = FFMPEG_BIN + os.pathsep + os.environ.get('PATH', '')
|
|
|
|
# ============== 环境初始化 ==============
|
|
def init_environment():
|
|
"""初始化环境设置"""
|
|
setup_windows_encoding()
|
|
setup_ffmpeg_path()
|
|
|
|
def get_api_key():
|
|
"""获取API密钥"""
|
|
for env_name in API_KEY_ENVS:
|
|
key = os.environ.get(env_name)
|
|
if key:
|
|
return key
|
|
return None |