Spaces:
Sleeping
Sleeping
| """Application configuration settings.""" | |
| from pydantic_settings import BaseSettings | |
| from pydantic import Field | |
| from pathlib import Path | |
| from typing import List, Dict, Any, Optional | |
| import os | |
| class Settings(BaseSettings): | |
| """Application settings with environment variable support.""" | |
| # Application settings | |
| app_name: str = "Video to Audio Extractor" | |
| app_version: str = "1.0.0" | |
| debug: bool = Field(default=False, env="DEBUG") | |
| # Storage configuration | |
| storage_type: str = Field(default="filesystem", env="STORAGE_TYPE") # "filesystem" or "r2" | |
| # File processing settings | |
| temp_dir: Path = Field(default=Path("/tmp/audio_extractor"), env="TEMP_DIR") | |
| max_direct_file_size_mb: float = Field(default=10.0, env="MAX_DIRECT_FILE_SIZE_MB") | |
| cleanup_interval_seconds: int = Field(default=3600, env="CLEANUP_INTERVAL_SECONDS") | |
| file_retention_hours: int = Field(default=2, env="FILE_RETENTION_HOURS") | |
| # Cloudflare R2 storage settings (optional, only needed if storage_type == "r2") | |
| cloudflare_r2_account_id: Optional[str] = Field(default=None, env="CLOUDFLARE_R2_ACCOUNT_ID") | |
| cloudflare_r2_access_key_id: Optional[str] = Field(default=None, env="CLOUDFLARE_R2_ACCESS_KEY_ID") | |
| cloudflare_r2_secret_access_key: Optional[str] = Field(default=None, env="CLOUDFLARE_R2_SECRET_ACCESS_KEY") | |
| cloudflare_r2_bucket_name: Optional[str] = Field(default=None, env="CLOUDFLARE_R2_BUCKET_NAME") | |
| # FFmpeg settings | |
| ffmpeg_path: str = Field(default="/usr/bin/ffmpeg", env="FFMPEG_PATH") | |
| ffmpeg_timeout_seconds: int = Field(default=1800, env="FFMPEG_TIMEOUT_SECONDS") # 30 minutes | |
| # Supported formats | |
| supported_video_formats: List[str] = Field( | |
| default=['.mp4', '.avi', '.mov', '.mkv', '.webm', '.flv', '.wmv', '.m4v'], | |
| env="SUPPORTED_VIDEO_FORMATS" | |
| ) | |
| supported_audio_formats: List[str] = Field( | |
| default=['mp3', 'aac', 'wav', 'flac', 'm4a', 'ogg'], | |
| env="SUPPORTED_AUDIO_FORMATS" | |
| ) | |
| # Quality presets | |
| quality_presets: Dict[str, Dict[str, Dict[str, Any]]] = { | |
| 'mp3': { | |
| 'high': {'bitrate': '320k', 'codec': 'libmp3lame'}, | |
| 'medium': {'bitrate': '192k', 'codec': 'libmp3lame'}, | |
| 'low': {'bitrate': '128k', 'codec': 'libmp3lame'} | |
| }, | |
| 'aac': { | |
| 'high': {'bitrate': '256k', 'codec': 'aac'}, | |
| 'medium': {'bitrate': '192k', 'codec': 'aac'}, | |
| 'low': {'bitrate': '128k', 'codec': 'aac'} | |
| }, | |
| 'wav': { | |
| 'high': {'codec': 'pcm_s24le'}, | |
| 'medium': {'codec': 'pcm_s16le'}, | |
| 'low': {'codec': 'pcm_s16le'} | |
| }, | |
| 'flac': { | |
| 'high': {'codec': 'flac', 'compression_level': 12}, | |
| 'medium': {'codec': 'flac', 'compression_level': 8}, | |
| 'low': {'codec': 'flac', 'compression_level': 0} | |
| }, | |
| 'm4a': { | |
| 'high': {'bitrate': '256k', 'codec': 'aac'}, | |
| 'medium': {'bitrate': '192k', 'codec': 'aac'}, | |
| 'low': {'bitrate': '128k', 'codec': 'aac'} | |
| }, | |
| 'ogg': { | |
| 'high': {'bitrate': '256k', 'codec': 'libvorbis'}, | |
| 'medium': {'bitrate': '192k', 'codec': 'libvorbis'}, | |
| 'low': {'bitrate': '128k', 'codec': 'libvorbis'} | |
| } | |
| } | |
| # MIME types | |
| audio_mime_types: Dict[str, str] = { | |
| 'mp3': 'audio/mpeg', | |
| 'aac': 'audio/aac', | |
| 'wav': 'audio/wav', | |
| 'flac': 'audio/flac', | |
| 'm4a': 'audio/mp4', | |
| 'ogg': 'audio/ogg' | |
| } | |
| # N8N Configuration | |
| n8n_base_url: str = Field(default="http://localhost:5678", env="N8N_BASE_URL") | |
| n8n_timeout: int = Field(default=30, env="N8N_TIMEOUT") | |
| n8n_enabled: bool = Field(default=True, env="N8N_ENABLED") | |
| # Authentication Configuration | |
| enforce_authentication: bool = Field(default=True, env="ENFORCE_AUTHENTICATION") | |
| enable_external_job_ids: bool = Field(default=True, env="ENABLE_EXTERNAL_JOB_IDS") | |
| jwt_validation_strict: bool = Field(default=False, env="JWT_VALIDATION_STRICT") | |
| class Config: | |
| env_file = ".env" | |
| env_file_encoding = "utf-8" | |
| case_sensitive = False | |
| def __init__(self, **kwargs): | |
| super().__init__(**kwargs) | |
| # Ensure temp directory exists (only for filesystem storage) | |
| if self.storage_type.lower() == "filesystem": | |
| self.temp_dir.mkdir(parents=True, exist_ok=True) | |
| # Validate R2 configuration if R2 storage is selected | |
| if self.storage_type.lower() == "r2": | |
| self._validate_r2_config() | |
| def _validate_r2_config(self): | |
| """Validate R2 configuration when R2 storage is selected.""" | |
| required_fields = [ | |
| 'cloudflare_r2_account_id', | |
| 'cloudflare_r2_access_key_id', | |
| 'cloudflare_r2_secret_access_key', | |
| 'cloudflare_r2_bucket_name' | |
| ] | |
| missing_fields = [] | |
| for field in required_fields: | |
| value = getattr(self, field) | |
| if not value: | |
| missing_fields.append(field.upper()) | |
| if missing_fields: | |
| raise ValueError( | |
| f"R2 storage selected but missing required environment variables: " | |
| f"{', '.join(missing_fields)}" | |
| ) | |
| # Singleton instance | |
| settings = Settings() |