Tadeas Kosek
n8n use passed token
3216021
"""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()