from __future__ import annotations import gc from pathlib import Path import torch from audio_separator.separator import Separator from .downloads import CustomModelRecord from .observability import log_level_number, normalize_log_level class RegisteredModelSeparator(Separator): """Adapter that lets the public package load trusted MDXC model+YAML pairs.""" def __init__(self, *args, custom_models: list[CustomModelRecord] | None = None, **kwargs): self._custom_models = {record.filename: record for record in (custom_models or [])} super().__init__(*args, **kwargs) def configure_cuda(self, ort_providers): self.logger.info("CUDA is available in Torch, configuring GPU inference") self.torch_device = torch.device("cuda") if "CUDAExecutionProvider" in ort_providers: self.onnx_execution_provider = ["CUDAExecutionProvider", "CPUExecutionProvider"] else: self.logger.warning("ONNX Runtime CUDA provider is unavailable; ONNX models will use CPU") self.onnx_execution_provider = ["CPUExecutionProvider"] def download_model_files(self, model_filename): record = self._custom_models.get(model_filename) if record is None: return super().download_model_files(model_filename) self.model_friendly_name = record.display_name self.model_is_uvr_vip = False return ( record.filename, record.architecture, record.display_name, str(record.model_path), str(record.config_path), ) def create_separator( output_dir: Path, model_dir: Path, custom_models: list[CustomModelRecord], output_format: str, ensemble_algorithm: str, single_stem: str | None, pitch_shift: int, chunk_duration: int | None, output_bitrate: str | None = None, sample_rate: int = 44100, normalization_threshold: float = 0.9, amplification_threshold: float = 0.0, log_level: str = "INFO", job_id: str | None = None, ) -> RegisteredModelSeparator: level_name = normalize_log_level(log_level) job_text = str(job_id or "unknown") return RegisteredModelSeparator( log_level=log_level_number(level_name), log_formatter=( "%(asctime)s - %(levelname)s - %(module)s - " f"job={job_text} - %(message)s" ), model_file_dir=str(model_dir), output_dir=str(output_dir), output_format=output_format, output_bitrate=output_bitrate, sample_rate=int(sample_rate), normalization_threshold=float(normalization_threshold), amplification_threshold=float(amplification_threshold), output_single_stem=single_stem, use_soundfile=False, use_autocast=bool(torch.cuda.is_available()), chunk_duration=chunk_duration, ensemble_algorithm=ensemble_algorithm, mdxc_params={ "segment_size": 256, "override_model_segment_size": False, "batch_size": 1, "overlap": 8, "pitch_shift": int(pitch_shift), }, custom_models=custom_models, ) def release_accelerators(separator=None) -> None: try: if separator is not None and getattr(separator, "model_instance", None) is not None: separator.model_instance.clear_gpu_cache() except Exception: pass del separator gc.collect() if torch.cuda.is_available(): torch.cuda.empty_cache() torch.cuda.ipc_collect()