You've already forked FrameTour-RenderWorker
182 lines
5.0 KiB
Python
182 lines
5.0 KiB
Python
import os
|
|
from dataclasses import dataclass
|
|
from typing import Dict, List, Optional, Union
|
|
import logging
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
|
|
@dataclass
|
|
class FFmpegConfig:
|
|
"""FFmpeg相关配置"""
|
|
|
|
encoder_args: List[str]
|
|
video_args: List[str]
|
|
audio_args: List[str]
|
|
default_args: List[str]
|
|
old_ffmpeg: bool = False
|
|
re_encode_video_args: Optional[List[str]] = None
|
|
re_encode_encoder_args: Optional[List[str]] = None
|
|
|
|
# 新增配置选项,消除硬编码
|
|
max_download_workers: int = 8
|
|
progress_args: Optional[List[str]] = None
|
|
loglevel_args: Optional[List[str]] = None
|
|
null_audio_args: Optional[List[str]] = None
|
|
overlay_scale_mode: str = "scale2ref" # 新版本使用scale2ref,旧版本使用scale
|
|
amix_args: Optional[List[str]] = None
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "FFmpegConfig":
|
|
encoder_args = os.getenv("ENCODER_ARGS", "-c:v h264").split(" ")
|
|
video_args = os.getenv("VIDEO_ARGS", "-profile:v high -level:v 4").split(" ")
|
|
audio_args = ["-c:a", "aac", "-b:a", "128k", "-ar", "48000", "-ac", "2"]
|
|
default_args = ["-shortest"]
|
|
|
|
re_encode_video_args = None
|
|
re_encode_video_env = os.getenv("RE_ENCODE_VIDEO_ARGS")
|
|
if re_encode_video_env:
|
|
re_encode_video_args = re_encode_video_env.split(" ")
|
|
|
|
re_encode_encoder_args = None
|
|
re_encode_encoder_env = os.getenv("RE_ENCODE_ENCODER_ARGS")
|
|
if re_encode_encoder_env:
|
|
re_encode_encoder_args = re_encode_encoder_env.split(" ")
|
|
|
|
# 新增配置项的默认值
|
|
progress_args = ["-progress", "-"]
|
|
loglevel_args = ["-loglevel", "error"]
|
|
null_audio_args = ["-f", "lavfi", "-i", "anullsrc=cl=stereo:r=48000"]
|
|
amix_args = ["amix=duration=shortest:dropout_transition=0:normalize=0"]
|
|
overlay_scale_mode = (
|
|
"scale" if bool(os.getenv("OLD_FFMPEG", False)) else "scale2ref"
|
|
)
|
|
|
|
return cls(
|
|
encoder_args=encoder_args,
|
|
video_args=video_args,
|
|
audio_args=audio_args,
|
|
default_args=default_args,
|
|
old_ffmpeg=bool(os.getenv("OLD_FFMPEG", False)),
|
|
re_encode_video_args=re_encode_video_args,
|
|
re_encode_encoder_args=re_encode_encoder_args,
|
|
max_download_workers=int(os.getenv("MAX_DOWNLOAD_WORKERS", "8")),
|
|
progress_args=progress_args,
|
|
loglevel_args=loglevel_args,
|
|
null_audio_args=null_audio_args,
|
|
overlay_scale_mode=overlay_scale_mode,
|
|
amix_args=amix_args,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class APIConfig:
|
|
"""API相关配置"""
|
|
|
|
endpoint: str
|
|
access_key: str
|
|
timeout: int = 10
|
|
redirect_to_url: Optional[str] = None
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "APIConfig":
|
|
endpoint = os.getenv("API_ENDPOINT", "")
|
|
if not endpoint:
|
|
raise ValueError("API_ENDPOINT environment variable is required")
|
|
|
|
access_key = os.getenv("ACCESS_KEY", "")
|
|
if not access_key:
|
|
raise ValueError("ACCESS_KEY environment variable is required")
|
|
|
|
return cls(
|
|
endpoint=endpoint,
|
|
access_key=access_key,
|
|
timeout=int(os.getenv("API_TIMEOUT", "10")),
|
|
redirect_to_url=os.getenv("REDIRECT_TO_URL") or None,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class StorageConfig:
|
|
"""存储相关配置"""
|
|
|
|
template_dir: str
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "StorageConfig":
|
|
template_dir = os.getenv("TEMPLATE_DIR", "./template")
|
|
return cls(template_dir=template_dir)
|
|
|
|
|
|
@dataclass
|
|
class ServerConfig:
|
|
"""服务器相关配置"""
|
|
|
|
host: str = "0.0.0.0"
|
|
port: int = 9998
|
|
debug: bool = False
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "ServerConfig":
|
|
return cls(
|
|
host=os.getenv("HOST", "0.0.0.0"),
|
|
port=int(os.getenv("PORT", "9998")),
|
|
debug=bool(os.getenv("DEBUG", False)),
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class AppConfig:
|
|
"""应用总配置"""
|
|
|
|
ffmpeg: FFmpegConfig
|
|
api: APIConfig
|
|
storage: StorageConfig
|
|
server: ServerConfig
|
|
|
|
@classmethod
|
|
def from_env(cls) -> "AppConfig":
|
|
return cls(
|
|
ffmpeg=FFmpegConfig.from_env(),
|
|
api=APIConfig.from_env(),
|
|
storage=StorageConfig.from_env(),
|
|
server=ServerConfig.from_env(),
|
|
)
|
|
|
|
|
|
# 全局配置实例
|
|
_config: Optional[AppConfig] = None
|
|
|
|
|
|
def get_config() -> AppConfig:
|
|
"""获取全局配置实例"""
|
|
global _config
|
|
if _config is None:
|
|
_config = AppConfig.from_env()
|
|
return _config
|
|
|
|
|
|
def reload_config() -> AppConfig:
|
|
"""重新加载配置"""
|
|
global _config
|
|
_config = AppConfig.from_env()
|
|
return _config
|
|
|
|
|
|
# 向后兼容的配置获取函数
|
|
def get_ffmpeg_config() -> FFmpegConfig:
|
|
return get_config().ffmpeg
|
|
|
|
|
|
def get_api_config() -> APIConfig:
|
|
return get_config().api
|
|
|
|
|
|
def get_storage_config() -> StorageConfig:
|
|
return get_config().storage
|
|
|
|
|
|
def get_server_config() -> ServerConfig:
|
|
return get_config().server
|