MogensR commited on
Commit
ca3b25f
·
1 Parent(s): d034be2

Create app_config.py

Browse files
Files changed (1) hide show
  1. app_config.py +246 -0
app_config.py ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Application Configuration Module
3
+ Centralizes all application configuration and environment variable handling
4
+
5
+ Note: Named 'app_config.py' to avoid conflicts with existing 'Configs/' folder
6
+ """
7
+
8
+ import os
9
+ from dataclasses import dataclass, asdict
10
+ from typing import Dict, Any, Optional
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ @dataclass
16
+ class ProcessingConfig:
17
+ """
18
+ Main processing configuration with environment variable defaults
19
+ """
20
+ # Frame processing settings
21
+ keyframe_interval: int = int(os.getenv('KEYFRAME_INTERVAL', '5'))
22
+ frame_skip: int = int(os.getenv('FRAME_SKIP', '1'))
23
+
24
+ # Memory management
25
+ memory_cleanup_interval: int = int(os.getenv('MEMORY_CLEANUP_INTERVAL', '30'))
26
+
27
+ # Video constraints
28
+ max_video_length: int = int(os.getenv('MAX_VIDEO_LENGTH', '300')) # seconds
29
+ max_video_resolution: str = os.getenv('MAX_VIDEO_RESOLUTION', '1920x1080')
30
+
31
+ # Quality settings
32
+ quality_preset: str = os.getenv('QUALITY_PRESET', 'balanced')
33
+
34
+ # Model settings
35
+ sam2_model_size: str = os.getenv('SAM2_MODEL_SIZE', 'large') # tiny, small, base, large
36
+ matanyone_precision: str = os.getenv('MATANYONE_PRECISION', 'fp32') # fp16, fp32
37
+
38
+ # Processing settings
39
+ temporal_consistency: bool = os.getenv('TEMPORAL_CONSISTENCY', 'true').lower() == 'true'
40
+ edge_refinement: bool = os.getenv('EDGE_REFINEMENT', 'true').lower() == 'true'
41
+
42
+ # Output settings
43
+ output_format: str = os.getenv('OUTPUT_FORMAT', 'mp4')
44
+ output_quality: str = os.getenv('OUTPUT_QUALITY', 'high') # low, medium, high
45
+ preserve_audio: bool = os.getenv('PRESERVE_AUDIO', 'true').lower() == 'true'
46
+
47
+ # Cache settings
48
+ model_cache_dir: str = os.getenv('MODEL_CACHE_DIR', '/tmp/model_cache')
49
+ temp_dir: str = os.getenv('TEMP_DIR', '/tmp')
50
+ cleanup_temp_files: bool = os.getenv('CLEANUP_TEMP_FILES', 'true').lower() == 'true'
51
+
52
+ # Performance settings
53
+ max_concurrent_processes: int = int(os.getenv('MAX_CONCURRENT_PROCESSES', '1'))
54
+ gpu_memory_fraction: float = float(os.getenv('GPU_MEMORY_FRACTION', '0.8'))
55
+
56
+ # Debug settings
57
+ debug_mode: bool = os.getenv('DEBUG_MODE', 'false').lower() == 'true'
58
+ save_intermediate_results: bool = os.getenv('SAVE_INTERMEDIATE_RESULTS', 'false').lower() == 'true'
59
+
60
+ def __post_init__(self):
61
+ """Validate configuration after initialization"""
62
+ self._validate_config()
63
+ self._create_directories()
64
+ if self.debug_mode:
65
+ self._log_config()
66
+
67
+ def _validate_config(self):
68
+ """Validate configuration values"""
69
+ # Validate frame settings
70
+ if self.keyframe_interval < 1:
71
+ logger.warning(f"keyframe_interval must be >= 1, got {self.keyframe_interval}. Setting to 1.")
72
+ self.keyframe_interval = 1
73
+
74
+ if self.frame_skip < 1:
75
+ logger.warning(f"frame_skip must be >= 1, got {self.frame_skip}. Setting to 1.")
76
+ self.frame_skip = 1
77
+
78
+ # Validate memory settings
79
+ if self.memory_cleanup_interval < 1:
80
+ logger.warning(f"memory_cleanup_interval must be >= 1, got {self.memory_cleanup_interval}. Setting to 10.")
81
+ self.memory_cleanup_interval = 10
82
+
83
+ # Validate video constraints
84
+ if self.max_video_length < 1:
85
+ logger.warning(f"max_video_length must be >= 1, got {self.max_video_length}. Setting to 60.")
86
+ self.max_video_length = 60
87
+
88
+ # Validate resolution format
89
+ if 'x' not in self.max_video_resolution:
90
+ logger.warning(f"Invalid resolution format: {self.max_video_resolution}. Setting to 1920x1080.")
91
+ self.max_video_resolution = '1920x1080'
92
+
93
+ # Validate quality preset
94
+ valid_presets = ['fast', 'balanced', 'high', 'ultra']
95
+ if self.quality_preset not in valid_presets:
96
+ logger.warning(f"Invalid quality preset: {self.quality_preset}. Setting to 'balanced'.")
97
+ self.quality_preset = 'balanced'
98
+
99
+ # Validate model settings
100
+ valid_sam2_sizes = ['tiny', 'small', 'base', 'large']
101
+ if self.sam2_model_size not in valid_sam2_sizes:
102
+ logger.warning(f"Invalid SAM2 model size: {self.sam2_model_size}. Setting to 'large'.")
103
+ self.sam2_model_size = 'large'
104
+
105
+ valid_precisions = ['fp16', 'fp32']
106
+ if self.matanyone_precision not in valid_precisions:
107
+ logger.warning(f"Invalid precision: {self.matanyone_precision}. Setting to 'fp32'.")
108
+ self.matanyone_precision = 'fp32'
109
+
110
+ # Validate output settings
111
+ valid_formats = ['mp4', 'avi', 'mov', 'webm']
112
+ if self.output_format not in valid_formats:
113
+ logger.warning(f"Invalid output format: {self.output_format}. Setting to 'mp4'.")
114
+ self.output_format = 'mp4'
115
+
116
+ valid_qualities = ['low', 'medium', 'high']
117
+ if self.output_quality not in valid_qualities:
118
+ logger.warning(f"Invalid output quality: {self.output_quality}. Setting to 'high'.")
119
+ self.output_quality = 'high'
120
+
121
+ # Validate performance settings
122
+ if self.max_concurrent_processes < 1:
123
+ logger.warning(f"max_concurrent_processes must be >= 1, got {self.max_concurrent_processes}. Setting to 1.")
124
+ self.max_concurrent_processes = 1
125
+
126
+ if not (0.1 <= self.gpu_memory_fraction <= 1.0):
127
+ logger.warning(f"gpu_memory_fraction must be between 0.1 and 1.0, got {self.gpu_memory_fraction}. Setting to 0.8.")
128
+ self.gpu_memory_fraction = 0.8
129
+
130
+ def _create_directories(self):
131
+ """Create necessary directories if they don't exist"""
132
+ import os
133
+ directories = [self.model_cache_dir, self.temp_dir]
134
+
135
+ for directory in directories:
136
+ try:
137
+ os.makedirs(directory, exist_ok=True)
138
+ logger.debug(f"Ensured directory exists: {directory}")
139
+ except Exception as e:
140
+ logger.error(f"Failed to create directory {directory}: {e}")
141
+
142
+ def _log_config(self):
143
+ """Log current configuration in debug mode"""
144
+ logger.info("=== Processing Configuration ===")
145
+ for key, value in asdict(self).items():
146
+ logger.info(f"{key}: {value}")
147
+ logger.info("===============================")
148
+
149
+ def to_dict(self) -> Dict[str, Any]:
150
+ """Convert configuration to dictionary"""
151
+ return asdict(self)
152
+
153
+ def get_quality_settings(self) -> Dict[str, Any]:
154
+ """Get quality-specific settings based on preset"""
155
+ quality_maps = {
156
+ 'fast': {
157
+ 'keyframe_interval': max(self.keyframe_interval, 10),
158
+ 'frame_skip': max(self.frame_skip, 2),
159
+ 'edge_refinement': False,
160
+ 'temporal_consistency': False,
161
+ 'model_precision': 'fp16'
162
+ },
163
+ 'balanced': {
164
+ 'keyframe_interval': self.keyframe_interval,
165
+ 'frame_skip': self.frame_skip,
166
+ 'edge_refinement': True,
167
+ 'temporal_consistency': True,
168
+ 'model_precision': 'fp32'
169
+ },
170
+ 'high': {
171
+ 'keyframe_interval': max(self.keyframe_interval // 2, 1),
172
+ 'frame_skip': 1,
173
+ 'edge_refinement': True,
174
+ 'temporal_consistency': True,
175
+ 'model_precision': 'fp32'
176
+ },
177
+ 'ultra': {
178
+ 'keyframe_interval': 1,
179
+ 'frame_skip': 1,
180
+ 'edge_refinement': True,
181
+ 'temporal_consistency': True,
182
+ 'model_precision': 'fp32'
183
+ }
184
+ }
185
+
186
+ return quality_maps.get(self.quality_preset, quality_maps['balanced'])
187
+
188
+ def get_resolution_limits(self) -> tuple[int, int]:
189
+ """Get max width and height from resolution setting"""
190
+ try:
191
+ width, height = map(int, self.max_video_resolution.split('x'))
192
+ return width, height
193
+ except ValueError:
194
+ logger.error(f"Invalid resolution format: {self.max_video_resolution}")
195
+ return 1920, 1080
196
+
197
+ def is_high_performance_mode(self) -> bool:
198
+ """Check if configuration is set for high performance"""
199
+ return (
200
+ self.quality_preset in ['high', 'ultra'] and
201
+ self.edge_refinement and
202
+ self.temporal_consistency and
203
+ self.keyframe_interval <= 3
204
+ )
205
+
206
+ def get_memory_limits(self) -> Dict[str, float]:
207
+ """Get memory-related limits"""
208
+ return {
209
+ 'gpu_memory_fraction': self.gpu_memory_fraction,
210
+ 'cleanup_interval': self.memory_cleanup_interval,
211
+ 'max_concurrent': self.max_concurrent_processes
212
+ }
213
+
214
+ # Singleton instance for application-wide use
215
+ _config_instance: Optional[ProcessingConfig] = None
216
+
217
+ def get_config() -> ProcessingConfig:
218
+ """Get global configuration instance"""
219
+ global _config_instance
220
+ if _config_instance is None:
221
+ _config_instance = ProcessingConfig()
222
+ return _config_instance
223
+
224
+ def reload_config() -> ProcessingConfig:
225
+ """Reload configuration from environment variables"""
226
+ global _config_instance
227
+ _config_instance = ProcessingConfig()
228
+ logger.info("Configuration reloaded from environment variables")
229
+ return _config_instance
230
+
231
+ def update_config(**kwargs) -> ProcessingConfig:
232
+ """Update configuration with new values"""
233
+ global _config_instance
234
+ if _config_instance is None:
235
+ _config_instance = ProcessingConfig()
236
+
237
+ for key, value in kwargs.items():
238
+ if hasattr(_config_instance, key):
239
+ setattr(_config_instance, key, value)
240
+ logger.debug(f"Updated config: {key} = {value}")
241
+ else:
242
+ logger.warning(f"Unknown configuration key: {key}")
243
+
244
+ # Re-validate after updates
245
+ _config_instance._validate_config()
246
+ return _config_instance