2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# --- START OF FILE core.py --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								import  os 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  sys 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# single thread doubles cuda performance - needs to be set before torch import 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# Check if CUDAExecutionProvider is likely intended 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								_cuda_intended  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  ' --execution-provider '  in  sys . argv : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        providers_index  =  sys . argv . index ( ' --execution-provider ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Check subsequent arguments until the next option (starts with '-') or end of list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  i  in  range ( providers_index  +  1 ,  len ( sys . argv ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  sys . argv [ i ] . startswith ( ' - ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ' cuda '  in  sys . argv [ i ] . lower ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                _cuda_intended  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    except  ValueError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pass  # --execution-provider not found 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# Less precise check if the above fails or isn't used (e.g. deprecated --gpu-vendor nvidia) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  not  _cuda_intended  and  any ( ' cuda '  in  arg . lower ( )  or  ' nvidia '  in  arg . lower ( )  for  arg  in  sys . argv ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     _cuda_intended  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  _cuda_intended : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( " [DLC.CORE] CUDA execution provider detected or inferred, setting OMP_NUM_THREADS=1. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    os . environ [ ' OMP_NUM_THREADS ' ]  =  ' 1 ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# reduce tensorflow log level 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								os . environ [ ' TF_CPP_MIN_LOG_LEVEL ' ]  =  ' 2 ' 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								import  warnings 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  typing  import  List ,  Optional 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								import  platform 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  signal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  shutil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  argparse 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  gc  # Garbage Collector 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# --- ONNX Runtime Version Check --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# Ensure ONNX Runtime is imported and check version compatibility if needed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# As of onnxruntime 1.19, the core APIs used here (get_available_providers, InferenceSession config) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# remain stable. No specific code changes are required *in this file* for 1.19 compatibility, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# assuming frame processors use standard SessionOptions/InferenceSession creation. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    import  onnxruntime 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # print(f"[DLC.CORE] Using ONNX Runtime version: {onnxruntime.__version__}") # Optional: uncomment for debug 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Example future check: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # from packaging import version 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # if version.parse(onnxruntime.__version__) < version.parse("1.19.0"): 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #     print(f"Warning: ONNX Runtime version {onnxruntime.__version__} is older than 1.19. Some features might differ.") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								except  ImportError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( " \033 [31m[DLC.CORE] Error: ONNX Runtime is not installed. Please install it (e.g., `pip install onnxruntime` or `pip install onnxruntime-gpu`). \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    sys . exit ( 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# --- PyTorch Conditional Import --- 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								_torch_available  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								_torch_cuda_available  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    import  torch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    _torch_available  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  torch . cuda . is_available ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        _torch_cuda_available  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								except  ImportError : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Warning only if CUDA EP might be used, otherwise PyTorch is optional 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  _cuda_intended : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( " [DLC.CORE] Warning: PyTorch not found or CUDA not available. GPU memory limiting via Torch is disabled. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pass  # Keep torch=None or handle appropriately 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# --- TensorFlow Conditional Import (for resource limiting) --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								_tensorflow_available  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    import  tensorflow 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    _tensorflow_available  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								except  ImportError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( " [DLC.CORE] Info: TensorFlow not found. GPU memory growth configuration for TensorFlow will be skipped. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    pass 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  modules . globals 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  modules . metadata 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  modules . ui  as  ui 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  modules . processors . frame . core  import  get_frame_processors_modules 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								from  modules . utilities  import  has_image_extension ,  is_image ,  is_video ,  detect_fps ,  create_video ,  extract_frames ,  get_temp_frame_paths ,  restore_audio ,  create_temp ,  move_temp ,  clean_temp ,  normalize_output_path 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 13:47:12 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# Configuration for GPU Memory Limit (0.8 = 80%) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								GPU_MEMORY_LIMIT_FRACTION  =  0.8 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# Check if ROCM is chosen early, before parse_args if possible, or handle after 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								_is_rocm_selected  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# A simple check; parse_args will give the definitive list later 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  any ( ' rocm '  in  arg . lower ( )  for  arg  in  sys . argv ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    _is_rocm_selected  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  _is_rocm_selected  and  _torch_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # If ROCM is selected, torch might interfere or not be needed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Let's keep the behavior of unloading it for safety, as ROCm support in PyTorch can be complex. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( " [DLC.CORE] ROCM detected or selected, unloading PyTorch to prevent potential conflicts. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    del  torch 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    _torch_available  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    _torch_cuda_available  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    gc . collect ( )  # Try to explicitly collect garbage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 00:15:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								warnings . filterwarnings ( ' ignore ' ,  category = FutureWarning ,  module = ' insightface ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								warnings . filterwarnings ( ' ignore ' ,  category = UserWarning ,  module = ' torchvision ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  parse_args ( )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    signal . signal ( signal . SIGINT ,  lambda  signal_number ,  frame :  destroy ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    program  =  argparse . ArgumentParser ( formatter_class = lambda  prog :  argparse . ArgumentDefaultsHelpFormatter ( prog ,  max_help_position = 40 ) )  # Wider help 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -s ' ,  ' --source ' ,  help = ' Path to the source image file ' ,  dest = ' source_path ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -t ' ,  ' --target ' ,  help = ' Path to the target image or video file ' ,  dest = ' target_path ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -o ' ,  ' --output ' ,  help = ' Path for the output file or directory ' ,  dest = ' output_path ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Frame processors - Updated choices might be needed if new processors are added 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    available_processors  =  [ ' face_swapper ' ,  ' face_enhancer ' ]  # Dynamically get these if possible in future 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --frame-processor ' ,  help = ' Pipeline of frame processors ' ,  dest = ' frame_processor ' ,  default = [ ' face_swapper ' ] ,  choices = available_processors ,  nargs = ' + ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --keep-fps ' ,  help = ' Keep the original frames per second (FPS) of the target video ' ,  dest = ' keep_fps ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --keep-audio ' ,  help = ' Keep the original audio of the target video (requires --keep-fps for perfect sync) ' ,  dest = ' keep_audio ' ,  action = ' store_true ' ,  default = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --keep-frames ' ,  help = ' Keep the temporary extracted frames after processing ' ,  dest = ' keep_frames ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --many-faces ' ,  help = ' Process all detected faces in the target, not just the most similar ' ,  dest = ' many_faces ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --nsfw-filter ' ,  help = ' Enable NSFW content filtering (experimental, image-only currently) ' ,  dest = ' nsfw_filter ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --map-faces ' ,  help = ' EXPERIMENTAL: Map source faces to target faces based on order or index. Requires manual setup or specific naming conventions. ' ,  dest = ' map_faces ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --mouth-mask ' ,  help = ' Apply a mask over the mouth region during processing (specific to certain processors) ' ,  dest = ' mouth_mask ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --video-encoder ' ,  help = ' Encoder for the output video ' ,  dest = ' video_encoder ' ,  default = ' libx264 ' ,  choices = [ ' libx264 ' ,  ' libx265 ' ,  ' libvpx-vp9 ' ,  ' h264_nvenc ' ,  ' hevc_nvenc ' ] )  # Added NVENC options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --video-quality ' ,  help = ' Quality for the output video (lower value means higher quality, range depends on encoder) ' ,  dest = ' video_quality ' ,  type = int ,  default = 18 ,  metavar = ' [0-51 for x264/x265, 0-63 for vp9] ' )  # Adjusted range note 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -l ' ,  ' --lang ' ,  help = ' User interface language code (e.g.,  " en " ,  " es " ) ' ,  default = " en " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --live-mirror ' ,  help = ' Mirror the live camera preview (like a webcam) ' ,  dest = ' live_mirror ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --live-resizable ' ,  help = ' Allow resizing the live camera preview window ' ,  dest = ' live_resizable ' ,  action = ' store_true ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --max-memory ' ,  help = ' DEPRECATED (use with caution): Approx. maximum CPU RAM in GB. Less effective than GPU limits. ' ,  dest = ' max_memory ' ,  type = int )  # Removed default, let suggest_max_memory handle it dynamically if needed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Execution Provider - Updated based on ONNX Runtime 1.19 common providers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --execution-provider ' ,  help = ' Execution provider(s) to use (e.g., cuda, cpu, rocm, dml, coreml). Order determines priority. ' ,  dest = ' execution_provider ' ,  default = suggest_execution_providers ( ) ,  choices = get_available_execution_providers_short ( ) ,  nargs = ' + ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --execution-threads ' ,  help = ' Number of threads for the execution provider ' ,  dest = ' execution_threads ' ,  type = int ,  default = suggest_execution_threads ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -v ' ,  ' --version ' ,  action = ' version ' ,  version = f ' { modules . metadata . name }   { modules . metadata . version }  (ONNX Runtime:  { onnxruntime . __version__ } ) ' )  # Added ORT version 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # register deprecated args 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' -f ' ,  ' --face ' ,  help = argparse . SUPPRESS ,  dest = ' source_path_deprecated ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --cpu-cores ' ,  help = argparse . SUPPRESS ,  dest = ' cpu_cores_deprecated ' ,  type = int ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --gpu-vendor ' ,  help = argparse . SUPPRESS ,  dest = ' gpu_vendor_deprecated ' ,  choices = [ ' apple ' ,  ' nvidia ' ,  ' amd ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    program . add_argument ( ' --gpu-threads ' ,  help = argparse . SUPPRESS ,  dest = ' gpu_threads_deprecated ' ,  type = int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    args  =  program . parse_args ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Set default for max_memory if not provided 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  args . max_memory  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        args . max_memory  =  suggest_max_memory ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Process deprecated args first 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    handle_deprecated_args ( args ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Assign to globals 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . source_path  =  args . source_path 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . target_path  =  args . target_path 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . output_path  =  normalize_output_path ( modules . globals . source_path ,  modules . globals . target_path ,  args . output_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . frame_processors  =  args . frame_processor 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Headless mode is determined by the presence of CLI args for paths 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . headless  =  bool ( args . source_path  or  args . target_path  or  args . output_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . keep_fps  =  args . keep_fps 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . keep_audio  =  args . keep_audio  # Note: keep_audio without keep_fps can cause sync issues 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . keep_frames  =  args . keep_frames 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . many_faces  =  args . many_faces 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . mouth_mask  =  args . mouth_mask 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-21 03:02:00 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . nsfw_filter  =  args . nsfw_filter 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 07:07:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . map_faces  =  args . map_faces 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . video_encoder  =  args . video_encoder 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . video_quality  =  args . video_quality 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-22 01:35:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . live_mirror  =  args . live_mirror 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . live_resizable  =  args . live_resizable 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . max_memory  =  args . max_memory  # Still set, but primarily for CPU RAM limit now 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . execution_providers  =  decode_execution_providers ( args . execution_provider )  # Decode selected short names 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . execution_threads  =  args . execution_threads 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-07 14:04:18 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    modules . globals . lang  =  args . lang 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Update derived globals 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    modules . globals . fp_ui  =  { proc :  ( proc  in  modules . globals . frame_processors )  for  proc  in  available_processors }  # Simplified UI state init 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Validate keep_audio / keep_fps combination 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  modules . globals . keep_audio  and  not  modules . globals . keep_fps  and  not  modules . globals . headless : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         # Only warn in interactive mode, CLI users are expected to know 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( " \033 [33mWarning: --keep-audio is enabled but --keep-fps is disabled. This might cause audio/video synchronization issues. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  modules . globals . keep_audio  and  not  modules . globals . target_path : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         print ( " \033 [33mWarning: --keep-audio is enabled but no target video path is provided. Audio cannot be kept. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         modules . globals . keep_audio  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  handle_deprecated_args ( args :  argparse . Namespace )  - >  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Handles deprecated arguments and updates corresponding new arguments if necessary. """ 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  args . source_path_deprecated : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        print ( ' \033 [33mArgument -f/--face is deprecated. Use -s/--source instead. \033 [0m ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  args . source_path :  # Only override if --source wasn't set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            args . source_path  =  args . source_path_deprecated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # Re-evaluate output path based on deprecated source (normalize_output_path handles this later) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Track if execution_threads was explicitly set by the user via --execution-threads 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # This requires checking sys.argv as argparse doesn't directly expose this. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    threads_explicitly_set  =  ' --execution-threads '  in  sys . argv 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  args . cpu_cores_deprecated  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        print ( ' \033 [33mArgument --cpu-cores is deprecated. Use --execution-threads instead. \033 [0m ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Only override if --execution-threads wasn't explicitly set 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  threads_explicitly_set : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            args . execution_threads  =  args . cpu_cores_deprecated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            threads_explicitly_set  =  True  # Mark as set now 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  args . gpu_threads_deprecated  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        print ( ' \033 [33mArgument --gpu-threads is deprecated. Use --execution-threads instead. \033 [0m ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Only override if --execution-threads wasn't explicitly set (by user or cpu-cores) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  threads_explicitly_set : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             args . execution_threads  =  args . gpu_threads_deprecated 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             threads_explicitly_set  =  True  # Mark as set 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Handle --gpu-vendor deprecation by modifying execution_provider list *if not explicitly set* 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ep_explicitly_set  =  ' --execution-provider '  in  sys . argv 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  args . gpu_vendor_deprecated : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( f ' \033 [33mArgument --gpu-vendor  { args . gpu_vendor_deprecated }  is deprecated. Use --execution-provider instead. \033 [0m ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  ep_explicitly_set : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            provider_map  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                # Map vendor to preferred execution provider short names 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ' apple ' :  [ ' coreml ' ,  ' cpu ' ] ,  # CoreML first 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ' nvidia ' :  [ ' cuda ' ,  ' cpu ' ] ,   # CUDA first 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ' amd ' :  [ ' rocm ' ,  ' cpu ' ]       # ROCm first 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # 'intel': ['openvino', 'cpu'] # Example if OpenVINO support is relevant 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  args . gpu_vendor_deprecated  in  provider_map : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                suggested_providers  =  provider_map [ args . gpu_vendor_deprecated ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                print ( f " Mapping deprecated --gpu-vendor  { args . gpu_vendor_deprecated }  to --execution-provider  { '   ' . join ( suggested_providers ) } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                args . execution_provider  =  suggested_providers  # Set the list of short names 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 print ( f ' \033 [33mWarning: Unknown --gpu-vendor  { args . gpu_vendor_deprecated } . Default execution providers will be used. \033 [0m ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             print ( f ' \033 [33mWarning: --gpu-vendor  { args . gpu_vendor_deprecated }  is ignored because --execution-provider was explicitly set. \033 [0m ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  get_available_execution_providers_full ( )  - >  List [ str ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Returns the full names of available ONNX Runtime execution providers. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  onnxruntime . get_available_providers ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    except  AttributeError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Fallback for very old versions or unexpected issues 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( " \033 [33mWarning: Could not dynamically get available providers. Falling back to common defaults. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Provide a reasonable guess 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        defaults  =  [ ' CPUExecutionProvider ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  _cuda_intended :  defaults . insert ( 0 ,  ' CUDAExecutionProvider ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  _is_rocm_selected :  defaults . insert ( 0 ,  ' ROCMExecutionProvider ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Add others based on platform if needed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  defaults 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  get_available_execution_providers_short ( )  - >  List [ str ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Returns the short names (lowercase) of available ONNX Runtime execution providers. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    full_names  =  get_available_execution_providers_full ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  [ name . replace ( ' ExecutionProvider ' ,  ' ' ) . lower ( )  for  name  in  full_names ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  decode_execution_providers ( selected_short_names :  List [ str ] )  - >  List [ str ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Converts selected short names back to full ONNX Runtime provider names, preserving order and checking availability. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    available_full_names  =  get_available_execution_providers_full ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    available_short_map  =  { name . replace ( ' ExecutionProvider ' ,  ' ' ) . lower ( ) :  name  for  name  in  available_full_names } 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    decoded_providers  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    valid_short_names_found  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  short_name  in  selected_short_names : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        name_lower  =  short_name . lower ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  name_lower  in  available_short_map : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            full_name  =  available_short_map [ name_lower ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  full_name  not  in  decoded_providers :  # Avoid duplicates 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                decoded_providers . append ( full_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                valid_short_names_found . append ( name_lower ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            print ( f " \033 [33mWarning: Requested execution provider  ' { short_name } '  is not available or not recognized. Skipping. \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  not  decoded_providers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( " \033 [33mWarning: No valid execution providers selected or available. Falling back to CPU. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ' CPUExecutionProvider '  in  available_full_names : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            decoded_providers  =  [ ' CPUExecutionProvider ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            valid_short_names_found . append ( ' cpu ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             print ( " \033 [31mError: CPUExecutionProvider is not available in this build of ONNX Runtime. Cannot proceed. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             sys . exit ( 1 )  # Critical error 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    print ( f " [DLC.CORE] Using execution providers:  { valid_short_names_found }  (Full names:  { decoded_providers } ) " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  decoded_providers 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  suggest_max_memory ( )  - >  int : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Suggests a default max CPU RAM limit in GB. Less critical now with GPU limits. """ 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  psutil 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        total_ram_gb  =  psutil . virtual_memory ( ) . total  /  ( 1024  * *  3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Suggest slightly less than half of total RAM, capped at a reasonable upper limit (e.g., 64GB) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # and a minimum (e.g., 4GB) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        suggested  =  max ( 4 ,  min ( int ( total_ram_gb  *  0.4 ) ,  64 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # print(f"[DLC.CORE] Auto-suggesting max_memory: {suggested} GB (based on total system RAM: {total_ram_gb:.1f} GB)") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  suggested 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    except  ( ImportError ,  OSError ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print ( " [DLC.CORE] Info: psutil not found or failed. Using fallback default for max_memory suggestion (16 GB). " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Fallback defaults similar to original code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  platform . system ( ) . lower ( )  ==  ' darwin ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  8  # Increased macOS default slightly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  16  # Keep higher default for Linux/Windows 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  suggest_execution_providers ( )  - >  List [ str ] : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Suggests a default list of execution providers based on availability and platform. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    available_short  =  get_available_execution_providers_short ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    preferred_providers  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Prioritize GPU providers if available 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ' cuda '  in  available_short : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        preferred_providers . append ( ' cuda ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  ' rocm '  in  available_short : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        preferred_providers . append ( ' rocm ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  ' dml '  in  available_short  and  platform . system ( ) . lower ( )  ==  ' windows ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         preferred_providers . append ( ' dml ' )  # DirectML on Windows 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  ' coreml '  in  available_short  and  platform . system ( ) . lower ( )  ==  ' darwin ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         preferred_providers . append ( ' coreml ' )  # CoreML on macOS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Always include CPU as a fallback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ' cpu '  in  available_short : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        preferred_providers . append ( ' cpu ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  available_short :  # If CPU is somehow missing, add the first available one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        preferred_providers . append ( available_short [ 0 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # If list is empty (shouldn't happen if get_available works), default to cpu 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  not  preferred_providers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  [ ' cpu ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # print(f"[DLC.CORE] Suggested execution providers: {preferred_providers}") # Optional debug info 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  preferred_providers 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  suggest_execution_threads ( )  - >  int : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Suggests a sensible default number of execution threads based on CPU cores. """ 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        logical_cores  =  os . cpu_count ( )  or  4  # Default to 4 if cpu_count fails 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Use slightly fewer threads than logical cores, capped. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Good balance between parallelism and overhead. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        suggested_threads  =  max ( 1 ,  min ( logical_cores  -  1  if  logical_cores  >  1  else  1 ,  16 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Don't suggest 1 for CUDA/ROCm implicitly here, let user override or frame processors decide. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # The SessionOptions in the processors should handle provider-specific thread settings if needed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # print(f"[DLC.CORE] Auto-suggesting execution_threads: {suggested_threads} (based on {logical_cores} logical cores)") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  suggested_threads 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    except  NotImplementedError : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        print ( " [DLC.CORE] Warning: os.cpu_count() not implemented. Using fallback default for execution_threads (4). " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  4  # Fallback 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  limit_gpu_memory ( fraction :  float )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Attempts to limit GPU memory usage, primarily via PyTorch if CUDA is used. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Check if CUDAExecutionProvider is in the *actually selected* providers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ' CUDAExecutionProvider '  in  modules . globals . execution_providers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  _torch_cuda_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Ensure CUDA is initialized if needed (might not be necessary, but safe) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  not  torch . cuda . is_initialized ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     torch . cuda . init ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                device_count  =  torch . cuda . device_count ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  device_count  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Limit memory on the default device (usually device 0) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Note: This limits PyTorch's allocation pool. ONNX Runtime might manage 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # its CUDA memory somewhat separately, but this can still help prevent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # PyTorch from grabbing everything. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( f " [DLC.CORE] Attempting to limit PyTorch CUDA memory fraction to  { fraction : .1% }  on device 0 " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    torch . cuda . set_per_process_memory_fraction ( fraction ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Optional: Check memory after setting limit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    total_mem  =  torch . cuda . get_device_properties ( 0 ) . total_memory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    reserved_mem  =  torch . cuda . memory_reserved ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    allocated_mem  =  torch . cuda . memory_allocated ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( f " [DLC.CORE] PyTorch CUDA memory limit hint set. Device 0 Total:  { total_mem  /  1024 * * 3 : .2f }  GB.  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                          f " PyTorch Reserved:  { reserved_mem  /  1024 * * 3 : .2f }  GB, Allocated:  { allocated_mem  /  1024 * * 3 : .2f }  GB. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( " \033 [33mWarning: PyTorch reports no CUDA devices available, cannot set memory limit. \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            except  RuntimeError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 print ( f " \033 [33mWarning: PyTorch CUDA runtime error during memory limit setting (may already be initialized?):  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                print ( f " \033 [33mWarning: Failed to set PyTorch CUDA memory fraction:  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # Only warn if PyTorch CUDA specifically isn't available, but CUDA EP was chosen. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  _cuda_intended :  # Check original intent 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                print ( " \033 [33mWarning: CUDAExecutionProvider selected, but PyTorch CUDA is not available. Cannot apply PyTorch memory limit. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Add future limits for other providers if ONNX Runtime API supports it directly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Example placeholder for potential future ONNX Runtime API: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # elif 'ROCMExecutionProvider' in modules.globals.execution_providers: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #     try: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         # Hypothetical ONNX Runtime API 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         ort_options = onnxruntime.SessionOptions() 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         ort_options.add_provider_options('rocm', {'gpu_mem_limit': str(int(total_mem_bytes * fraction))}) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         print("[DLC.CORE] Note: ROCm memory limit set via ONNX Runtime provider options (if API exists).") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #     except Exception as e: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         print(f"\033[33mWarning: Failed to set ROCm memory limit via hypothetical ORT options: {e}\033[0m") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # else: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #     print("[DLC.CORE] GPU memory limit not applied (PyTorch CUDA not used or unavailable).") 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  limit_resources ( )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Limits system resources like CPU RAM (best effort) and sets TensorFlow GPU options. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 1. Limit CPU RAM (Best-effort, OS-dependent) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  modules . globals . max_memory  and  modules . globals . max_memory  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        limit_gb  =  modules . globals . max_memory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        limit_bytes  =  limit_gb  *  ( 1024  * *  3 ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        current_system  =  platform . system ( ) . lower ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  current_system  ==  ' linux '  or  current_system  ==  ' darwin ' : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                import  resource 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                # RLIMIT_AS (virtual memory) is often more effective than RLIMIT_DATA 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    soft ,  hard  =  resource . getrlimit ( resource . RLIMIT_AS ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Set soft limit; hard limit usually requires root. Don't exceed current hard limit. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    new_soft  =  min ( limit_bytes ,  hard ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    resource . setrlimit ( resource . RLIMIT_AS ,  ( new_soft ,  hard ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( f " [DLC.CORE] Limited process virtual memory (CPU RAM approximation) soft limit towards ~ { limit_gb }  GB. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                except  ( ValueError ,  resource . error )  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( f " \033 [33mWarning: Failed to set virtual memory limit (RLIMIT_AS):  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Fallback attempt using RLIMIT_DATA (less effective for total memory) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         soft_data ,  hard_data  =  resource . getrlimit ( resource . RLIMIT_DATA ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         new_soft_data  =  min ( limit_bytes ,  hard_data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         resource . setrlimit ( resource . RLIMIT_DATA ,  ( new_soft_data ,  hard_data ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         print ( f " [DLC.CORE] Limited process data segment (partial CPU RAM) soft limit towards ~ { limit_gb }  GB. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    except  ( ValueError ,  resource . error )  as  e_data : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         print ( f " \033 [33mWarning: Failed to set data segment limit (RLIMIT_DATA):  { e_data } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            elif  current_system  ==  ' windows ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Windows memory limiting is complex. SetProcessWorkingSetSizeEx is more of a suggestion. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Job Objects are the robust way but much more involved. Keep the hint for now. 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                import  ctypes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                kernel32  =  ctypes . windll . kernel32 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                process_handle  =  kernel32 . GetCurrentProcess ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Flags: QUOTA_LIMITS_HARDWS_ENABLE (1) requires special privileges, use 0 for min/max hint only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Using min=1MB, max=limit_bytes. Returns non-zero on success. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                min_ws  =  ctypes . c_size_t ( 1024  *  1024 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                max_ws  =  ctypes . c_size_t ( limit_bytes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  not  kernel32 . SetProcessWorkingSetSizeEx ( process_handle ,  min_ws ,  max_ws ,  0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    error_code  =  ctypes . get_last_error ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    print ( f " \033 [33mWarning: Failed to set process working set size hint (Windows). Error code:  { error_code } . This limit may not be enforced. \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    print ( f " [DLC.CORE] Requested process working set size hint (Windows memory guidance) max ~ { limit_gb }  GB. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 print ( f " \033 [33mWarning: CPU RAM limiting not implemented for platform  { current_system } . --max-memory ignored. \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        except  ImportError : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             print ( f " \033 [33mWarning:  ' resource '  module (Unix) not available. Cannot limit CPU RAM via setrlimit. \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             print ( f " \033 [33mWarning: An unexpected error occurred during CPU RAM limiting:  { e } \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # else: 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    #     print("[DLC.CORE] Info: CPU RAM limit (--max-memory) not set or disabled.") 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 2. Configure TensorFlow GPU memory (if TensorFlow is installed) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  _tensorflow_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            gpus  =  tensorflow . config . experimental . list_physical_devices ( ' GPU ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  gpus : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                configured_gpus  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                for  gpu  in  gpus : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        # Allow memory growth instead of pre-allocating everything 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        tensorflow . config . experimental . set_memory_growth ( gpu ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        # print(f"[DLC.CORE] Enabled TensorFlow memory growth for GPU: {gpu.name}") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        configured_gpus  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    except  RuntimeError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        # Memory growth must be set before GPUs have been initialized 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                        print ( f " \033 [33mWarning: Could not set TensorFlow memory growth for  { gpu . name }  (may already be initialized):  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    except  Exception  as  e_inner :  # Catch other potential TF config errors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                         print ( f " \033 [33mWarning: Error configuring TensorFlow memory growth for  { gpu . name } :  { e_inner } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  configured_gpus  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     print ( f " [DLC.CORE] Enabled TensorFlow memory growth for  { configured_gpus }  GPU(s). " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # else: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            #     print("[DLC.CORE] No TensorFlow physical GPUs detected.") 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            print ( f " \033 [33mWarning: Error listing or configuring TensorFlow GPU devices:  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # else: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #     print("[DLC.CORE] TensorFlow not available, skipping TF GPU configuration.") 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  release_resources ( )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Releases resources, especially GPU memory caches. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Clear PyTorch CUDA cache if applicable and PyTorch CUDA is available 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ' CUDAExecutionProvider '  in  modules . globals . execution_providers  and  _torch_cuda_available : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            torch . cuda . empty_cache ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # print("[DLC.CORE] Cleared PyTorch CUDA cache.") # Optional: uncomment for verbose logging 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             print ( f " \033 [33mWarning: Failed to clear PyTorch CUDA cache:  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Add potential cleanup for other frameworks or ONNX Runtime sessions if needed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # (Usually session objects going out of scope and gc.collect() is sufficient for ORT C++ backend) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Explicitly run garbage collection 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # This helps release Python-level objects, which might then trigger 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # the release of underlying resources (like ONNX Runtime session memory) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    gc . collect ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # print("[DLC.CORE] Ran garbage collector.") # Optional: uncomment for verbose logging 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  pre_check ( )  - >  bool : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Performs essential pre-run checks for dependencies and versions. """ 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  sys . version_info  <  ( 3 ,  9 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( ' Python version is not supported - please upgrade to Python 3.9 or higher. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  False 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    if  not  shutil . which ( ' ffmpeg ' ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( ' ffmpeg command not found in PATH. Please install ffmpeg and ensure it is accessible. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  False 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # ONNX Runtime was checked at import time, but double check here if needed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # The import would have failed earlier if it's not installed. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # print(f"[DLC.CORE] Using ONNX Runtime version: {onnxruntime.__version__}") 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # TensorFlow check (optional, only issue warning if unavailable) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  not  _tensorflow_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( ' TensorFlow not found. Some features like GPU memory growth setting will be skipped. ' ,  scope = ' INFO ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Decide if TF is strictly required by any processor. If so, change to error and return False. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Currently, it seems only used for optional resource limiting. 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Check PyTorch availability *only if* CUDA EP is selected 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ' CUDAExecutionProvider '  in  modules . globals . execution_providers : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								         if  not  _torch_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' CUDAExecutionProvider selected, but PyTorch is not installed. Install PyTorch with CUDA support (see PyTorch website). ' ,  scope = ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             return  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         if  not  _torch_cuda_available : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' CUDAExecutionProvider selected, but torch.cuda.is_available() is False. Check PyTorch CUDA installation, GPU drivers, and CUDA toolkit compatibility. ' ,  scope = ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             return  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Check if selected video encoder potentially requires specific hardware/drivers (e.g., NVENC) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  modules . globals . video_encoder  in  [ ' h264_nvenc ' ,  ' hevc_nvenc ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # This check is basic. FFmpeg needs to be compiled with NVENC support, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # and NVIDIA drivers must be installed. We can't easily verify this from Python. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Just issue an informational note. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( f " Selected video encoder  ' { modules . globals . video_encoder } '  requires an NVIDIA GPU and correctly configured FFmpeg/drivers. " ,  scope = ' INFO ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ' CUDAExecutionProvider '  not  in  modules . globals . execution_providers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( f " Warning: NVENC encoder selected, but CUDAExecutionProvider is not active. Ensure FFmpeg can access the GPU independently. " ,  scope = ' WARN ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  True 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  update_status ( message :  str ,  scope :  str  =  ' DLC.CORE ' )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Prints status messages and updates UI if not headless. """ 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    formatted_message  =  f ' [ { scope } ]  { message } ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    print ( formatted_message ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-16 21:03:14 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  not  modules . globals . headless : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Ensure ui module and update_status function exist and are callable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  hasattr ( ui ,  ' update_status ' )  and  callable ( ui . update_status ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Use a mechanism that's safe for cross-thread UI updates if necessary 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # (e.g., queue or wx.CallAfter if using wxPython) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Assuming direct call is okay for now based on original structure. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ui . update_status ( message )  # Pass the original message without scope prefix 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Avoid crashing core process for UI update errors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                print ( f " [DLC.CORE] Error updating UI status:  { e } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # else: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #      print("[DLC.CORE] UI or ui.update_status not available for status update.") 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  start ( )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Main processing logic: routes to image or video processing. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Ensure frame processors are ready (this also initializes them) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        active_processors  =  get_frame_processors_modules ( modules . globals . frame_processors ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  active_processors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( " No valid frame processors selected or loaded. Aborting. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        all_processors_initialized  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  frame_processor  in  active_processors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( f ' Initializing frame processor:  { getattr ( frame_processor ,  " NAME " ,  " UnknownProcessor " ) } ... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # The pre_start method should handle model loading and initial setup. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # It might raise exceptions or return False on failure. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  hasattr ( frame_processor ,  ' pre_start ' )  or  not  callable ( frame_processor . pre_start ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f ' Processor  { getattr ( frame_processor ,  " NAME " ,  " UnknownProcessor " ) }  lacks a pre_start method. ' ,  ' WARN ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 continue  # Or treat as failure? 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 07:07:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  not  frame_processor . pre_start ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                update_status ( f ' Initialization failed for  { getattr ( frame_processor ,  " NAME " ,  " UnknownProcessor " ) } . Aborting. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                all_processors_initialized  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break  # Stop initialization if one fails 
							 
						 
					
						
							
								
									
										
										
										
											2024-09-10 07:07:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  not  all_processors_initialized : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  # Abort if any processor failed to initialize 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( f " Error during frame processor initialization:  { e } " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        traceback . print_exc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # --- Route based on target type --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  not  modules . globals . target_path  or  not  os . path . exists ( modules . globals . target_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( f " Target path  ' { modules . globals . target_path } '  not found or not specified. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  has_image_extension ( modules . globals . target_path )  and  is_image ( modules . globals . target_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        process_image_target ( active_processors ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    elif  is_video ( modules . globals . target_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        process_video_target ( active_processors ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( f " Target path  ' { modules . globals . target_path } '  is not a recognized image or video file. " ,  " ERROR " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  process_image_target ( active_processors :  List )  - >  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Handles processing when the target is an image. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    update_status ( ' Processing image target... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # NSFW check (basic, for image only) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  modules . globals . nsfw_filter : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								         update_status ( ' Checking image for NSFW content... ' ,  ' NSFW ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         # Assuming ui.check_and_ignore_nsfw is suitable for this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         if  ui . check_and_ignore_nsfw ( modules . globals . target_path ,  destroy ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' NSFW content detected and processing skipped. ' ,  ' NSFW ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             return  # Stop processing 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Ensure source path exists if needed by processors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  modules . globals . source_path  or  not  os . path . exists ( modules . globals . source_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             # Face swapping requires a source, enhancer might not. Check processor needs? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             if  any ( proc . NAME  ==  ' face_swapper '  for  proc  in  active_processors ) :  # Example check 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f " Source image path  ' { modules . globals . source_path } '  not found or not specified, required for face swapping. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Ensure output directory exists 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        output_dir  =  os . path . dirname ( modules . globals . output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  output_dir  and  not  os . path . exists ( output_dir ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 os . makedirs ( output_dir ,  exist_ok = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 print ( f " [DLC.CORE] Created output directory:  { output_dir } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             except  OSError  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f " Error creating output directory  ' { output_dir } ' :  { e } " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Copy target to output path first to preserve metadata if possible and safe 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        final_output_path  =  modules . globals . output_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        temp_output_path  =  None  # Use a temp path if overwriting source/target directly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Avoid overwriting input files directly during processing if they are the same as output 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  os . path . abspath ( modules . globals . target_path )  ==  os . path . abspath ( final_output_path )  or  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								           ( modules . globals . source_path  and  os . path . abspath ( modules . globals . source_path )  ==  os . path . abspath ( final_output_path ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            temp_output_path  =  os . path . join ( output_dir ,  f " temp_image_ { os . path . basename ( final_output_path ) } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            print ( f " [DLC.CORE] Output path conflicts with input, using temporary file:  { temp_output_path } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shutil . copy2 ( modules . globals . target_path ,  temp_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            current_processing_file  =  temp_output_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # Copy target to final destination to start 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            shutil . copy2 ( modules . globals . target_path ,  final_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            current_processing_file  =  final_output_path 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Apply processors sequentially to the current file path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        source_for_processing  =  modules . globals . source_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        output_for_processing  =  current_processing_file  # Processors modify this file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  frame_processor  in  active_processors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            processor_name  =  getattr ( frame_processor ,  " NAME " ,  " UnknownProcessor " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            update_status ( f ' Applying  { processor_name } ... ' ,  processor_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                # Pass source, input_path (current state), output_path (same as input for in-place modification) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                frame_processor . process_image ( source_for_processing ,  output_for_processing ,  output_for_processing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                release_resources ( )  # Release memory after each processor step 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 update_status ( f ' Error during  { processor_name }  processing:  { e } ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 traceback . print_exc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # Optionally clean up temp file and abort 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 if  temp_output_path  and  os . path . exists ( temp_output_path ) :  os . remove ( temp_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # If a temporary file was used, move it to the final destination 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  temp_output_path : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                shutil . move ( temp_output_path ,  final_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                print ( f " [DLC.CORE] Moved temporary result to final output:  { final_output_path } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f " Error moving temporary file to final output:  { e } " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # Temp file might still exist, leave it for inspection? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Final check if output exists and is an image 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  os . path . exists ( final_output_path )  and  is_image ( final_output_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' Processing image finished successfully. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' Processing image failed: Output file not found or invalid after processing. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( f ' An unexpected error occurred during image processing:  { e } ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        traceback . print_exc ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Clean up potentially corrupted output/temp file? Be cautious. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # if temp_output_path and os.path.exists(temp_output_path): os.remove(temp_output_path) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # if os.path.exists(final_output_path) and current_processing_file == final_output_path: # Careful not to delete original if copy failed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								              # Consider what to do on failure - delete potentially corrupt output? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								def  process_video_target ( active_processors :  List )  - >  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Handles processing when the target is a video. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    update_status ( ' Processing video target... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Basic check for source if needed (similar to image processing) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  not  modules . globals . source_path  or  not  os . path . exists ( modules . globals . source_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         if  any ( proc . NAME  ==  ' face_swapper '  for  proc  in  active_processors ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( f " Source image path  ' { modules . globals . source_path } '  not found or not specified, required for face swapping. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # NSFW Check (Could be enhanced to sample frames, currently basic/skipped for video) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  modules . globals . nsfw_filter : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( ' NSFW check for video is basic/experimental. Checking first frame... ' ,  ' NSFW ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Consider implementing frame sampling for a more robust check if needed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # if ui.check_and_ignore_nsfw(modules.globals.target_path, destroy): # This might not work well for video 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #     update_status('NSFW content potentially detected (based on first frame check). Skipping.', 'NSFW') 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #     return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( ' NSFW check passed or skipped for video. ' ,  ' NSFW INFO ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    temp_output_video_path  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    temp_frame_dir  =  None  # Keep track of temp frame directory 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # --- Frame Extraction --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # map_faces might imply frames are already extracted or handled differently 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  not  modules . globals . map_faces : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            update_status ( ' Creating temporary resources for video frames... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # create_temp should return the path to the temp directory created 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            temp_frame_dir  =  create_temp ( modules . globals . target_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  temp_frame_dir : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( " Failed to create temporary directory for frames. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( ' Extracting video frames... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # extract_frames needs the temp directory path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # It should also ideally set modules.globals.video_fps based on the extracted video 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            extract_frames ( modules . globals . target_path ,  temp_frame_dir )  # Pass temp dir 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( ' Frame extraction complete. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' Skipping frame extraction due to --map-faces flag. ' ,  ' INFO ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             # Assuming frames are already in the expected temp location or handled by processors 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             temp_frame_dir  =  os . path . join ( modules . globals . TEMP_DIRECTORY ,  os . path . basename ( modules . globals . target_path ) )  # Need consistent temp path logic 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Get paths to frames (extracted or pre-existing) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        temp_frame_paths  =  get_temp_frame_paths ( modules . globals . target_path )  # This needs to know the temp dir structure 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  not  temp_frame_paths : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            update_status ( ' No frames found to process. Check temp folder or extraction step. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # Clean up if temp dir was created 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  temp_frame_dir  and  not  modules . globals . keep_frames :  clean_temp ( modules . globals . target_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( f ' Processing  { len ( temp_frame_paths ) }  frames... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # --- Frame Processing --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        source_for_processing  =  modules . globals . source_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  frame_processor  in  active_processors : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            processor_name  =  getattr ( frame_processor ,  " NAME " ,  " UnknownProcessor " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( f ' Applying  { processor_name } ... ' ,  processor_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # process_video should modify frames in-place in the temp directory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # It needs the source path and the list of frame paths 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                frame_processor . process_video ( source_for_processing ,  temp_frame_paths ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                release_resources ( )  # Release memory after each processor completes its pass 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f ' Error during  { processor_name }  frame processing:  { e } ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 traceback . print_exc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # Abort processing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # Clean up temp frames if not keeping them 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 if  temp_frame_dir  and  not  modules . globals . keep_frames :  clean_temp ( modules . globals . target_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # --- Video Creation --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( ' Reconstructing video from processed frames... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        fps  =  modules . globals . video_fps  # Should be set by extract_frames or detected earlier 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  modules . globals . keep_fps : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # Use the FPS detected during extraction (should be stored in globals.video_fps) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  fps  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                update_status ( ' Original FPS not detected during extraction, attempting fallback detection... ' ,  ' WARN ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                detected_fps  =  detect_fps ( modules . globals . target_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  detected_fps  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    fps  =  detected_fps 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    modules . globals . video_fps  =  fps  # Store it back 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    update_status ( f ' Using fallback detected FPS:  { fps : .2f } ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    fps  =  30.0  # Ultimate fallback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    update_status ( " Could not detect FPS, using default 30. " ,  " WARN " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 update_status ( f ' Using original detected FPS:  { fps : .2f } ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            fps  =  30.0  # Use default fps if not keeping original 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( f ' Using fixed FPS:  { fps : .2f } ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Define a temporary path for the video created *without* audio 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        output_dir  =  os . path . dirname ( modules . globals . output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  output_dir :  output_dir  =  ' . '  # Handle case where output is in current dir 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        temp_output_video_filename  =  f " temp_ { os . path . basename ( modules . globals . output_path ) } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Ensure the temp filename doesn't clash if multiple runs happen concurrently (less likely in this app) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        temp_output_video_path  =  os . path . join ( output_dir ,  temp_output_video_filename ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # create_video needs the target path (for context?), fps, and the *temp* output path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # It internally uses get_temp_frame_paths based on the target_path context. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        create_video ( modules . globals . target_path ,  fps ,  temp_output_video_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # --- Audio Handling --- 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        final_output_path  =  modules . globals . output_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  modules . globals . keep_audio : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            update_status ( ' Restoring audio... ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  not  modules . globals . keep_fps : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                update_status ( ' Audio restoration may cause sync issues as FPS was not kept. ' ,  ' WARN ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # restore_audio needs: original video (with audio), temp video (no audio), final output path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            restore_success  =  restore_audio ( modules . globals . target_path ,  temp_output_video_path ,  final_output_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  restore_success : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                update_status ( ' Audio restoration complete. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                # Remove the intermediate temp video *after* successful audio merge 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  os . path . exists ( temp_output_video_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    try :  os . remove ( temp_output_video_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    except  OSError  as  e :  print ( f " \033 [33mWarning: Could not remove intermediate video file  { temp_output_video_path } :  { e } \033 [0m " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                temp_output_video_path  =  None  # Mark as removed 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                update_status ( ' Audio restoration failed. The output video will be silent. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                # Audio failed, move the silent video to the final path as a fallback? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                update_status ( ' Moving silent video to final output path as fallback. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    shutil . move ( temp_output_video_path ,  final_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    temp_output_video_path  =  None  # Mark as moved 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     update_status ( f " Error moving silent video to final output:  { e } " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     # Both audio failed and move failed, temp video might still exist 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # No audio requested, move the temp video to the final output path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( ' Moving temporary video to final output path (no audio). ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  os . path . abspath ( temp_output_video_path )  ==  os . path . abspath ( final_output_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     update_status ( " Temporary path is the same as final path, no move needed. " ,  " INFO " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                     temp_output_video_path  =  None  # No deletion needed later 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    # Ensure target directory exists (should already, but double check) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    os . makedirs ( os . path . dirname ( final_output_path ) ,  exist_ok = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    shutil . move ( temp_output_video_path ,  final_output_path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    temp_output_video_path  =  None  # Mark as moved successfully 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( f " Error moving temporary video to final output:  { e } " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # The temp video might still exist 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # --- Validation --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  os . path . exists ( final_output_path )  and  is_video ( final_output_path ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            update_status ( ' Processing video finished successfully. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             update_status ( ' Processing video failed: Output file not found or invalid after processing. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( f ' An unexpected error occurred during video processing:  { e } ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  traceback 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        traceback . print_exc ( )  # Print detailed traceback for debugging 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    finally : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # --- Cleanup --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Clean up temporary frames if they exist and keep_frames is false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  temp_frame_dir  and  os . path . exists ( temp_frame_dir )  and  not  modules . globals . keep_frames : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( " Cleaning up temporary frames... " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             clean_temp ( modules . globals . target_path )  # clean_temp uses target_path context to find the dir 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # Clean up intermediate temp video file if it still exists (e.g., audio failed and move failed) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  temp_output_video_path  and  os . path . exists ( temp_output_video_path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 os . remove ( temp_output_video_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 print ( f " [DLC.CORE] Removed intermediate temporary video file:  { temp_output_video_path } " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								             except  OSError  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 print ( f " \033 [33mWarning: Could not remove intermediate temporary video file  { temp_output_video_path } :  { e } \033 [0m " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  destroy ( to_quit :  bool  =  True )  - >  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Cleans up temporary files, releases resources, and optionally exits. """ 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    update_status ( " Cleaning up temporary resources... " ,  " CLEANUP " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # Use the context of target_path to find the temp directory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  modules . globals . target_path  and  not  modules . globals . keep_frames : 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        clean_temp ( modules . globals . target_path ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    release_resources ( )  # Final resource release (GPU cache, GC) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    update_status ( " Cleanup complete. " ,  " CLEANUP " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  to_quit : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        print ( " [DLC.CORE] Exiting application. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        os . _exit ( 0 )  # Use os._exit for a more forceful exit if sys.exit hangs (e.g., due to threads) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # sys.exit(0) # Standard exit 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-24 21:36:57 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  run ( )  - >  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Parses arguments, sets up the environment, performs checks, and starts processing or UI. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parse_args ( )  # Parse arguments first to set globals like execution_providers, paths, etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Apply GPU Memory Limit early, requires execution_providers to be set by parse_args 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        limit_gpu_memory ( GPU_MEMORY_LIMIT_FRACTION ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Limit other resources (CPU RAM approximation, TF GPU options) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Call this *after* potential PyTorch limit and TensorFlow import check 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        limit_resources ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Perform pre-checks (dependencies like Python version, ffmpeg, libraries, provider checks) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( " Performing pre-run checks... " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  pre_check ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( " Pre-run checks failed. Please see messages above. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # destroy(to_quit=True) # Don't call destroy here, let the main try/finally handle it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  # Exit run() function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        update_status ( " Pre-run checks passed. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Pre-check frame processors (model downloads, requirements within processors) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # This needs globals to be set by parse_args and should happen before starting work. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        active_processor_modules  =  get_frame_processors_modules ( modules . globals . frame_processors ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        all_processors_reqs_met  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  frame_processor_module  in  active_processor_modules : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            processor_name  =  getattr ( frame_processor_module ,  " NAME " ,  " UnknownProcessor " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( f ' Checking requirements for  { processor_name } ... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  hasattr ( frame_processor_module ,  ' pre_check ' )  and  callable ( frame_processor_module . pre_check ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  not  frame_processor_module . pre_check ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    update_status ( f ' Requirements check failed for  { processor_name } . See processor messages for details. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    all_processors_reqs_met  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    # Don't break early, check all processors to report all issues 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                update_status ( f ' Processor  { processor_name }  does not have a pre_check method. Assuming requirements met. ' ,  ' WARN ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  not  all_processors_reqs_met : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             update_status ( ' Some frame processors failed requirement checks. Please resolve the issues and retry. ' ,  ' ERROR ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             # destroy(to_quit=True) # Let finally handle cleanup 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								             return 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        update_status ( " All frame processor requirements met. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # --- Start processing (headless) or launch UI --- 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  modules . globals . headless : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # Check for essential paths in headless mode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  modules . globals . source_path : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( " Error: Headless mode requires --source argument. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # program.print_help() # Can't access program object here easily 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 print ( " Use -h or --help for usage details. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  modules . globals . target_path : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( " Error: Headless mode requires --target argument. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 print ( " Use -h or --help for usage details. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  modules . globals . output_path : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 update_status ( " Error: Headless mode requires --output argument. " ,  " ERROR " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 print ( " Use -h or --help for usage details. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( ' Running in headless mode. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            start ( )  # Execute the main processing logic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # destroy() will be called by the finally block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # --- Launch UI --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            update_status ( ' Launching graphical user interface... ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # Ensure destroy is callable without arguments for the UI close button 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            destroy_wrapper  =  lambda :  destroy ( to_quit = True ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                # Pass start (processing function) and destroy (cleanup) to the UI 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                window  =  ui . init ( start ,  destroy_wrapper ,  modules . globals . lang ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  window : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    window . mainloop ( )  # Start the UI event loop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    update_status ( " UI initialization failed. " ,  " ERROR " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                 update_status ( f " Error initializing or running the UI:  { e } " ,  " FATAL " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 traceback . print_exc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # Attempt cleanup even if UI fails 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                 # destroy(to_quit=True) # Let finally handle it 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    except  Exception  as  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         # Catch any unexpected errors during setup or execution 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         update_status ( f " A critical error occurred:  { e } " ,  " FATAL " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         import  traceback 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         traceback . print_exc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         # Ensure cleanup happens regardless of success or failure 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         destroy ( to_quit = True )  # Clean up and exit 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# --- Main execution entry point --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								if  __name__  ==  " __main__ " : 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # This ensures 'run()' is called only when the script is executed directly 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    run ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:56:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-03-27 02:00:43 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# --- END OF FILE core.py ---