Rifd/Ultimate-Vocal-Remover-WebUI
5
1import audioread2import librosa3 4import os5import sys6import json7import time8from tqdm import tqdm9import pickle10import hashlib11import logging12import traceback13import shutil14import soundfile as sf15 16import torch17 18from gui_data.constants import *19from gui_data.old_data_check import file_check, remove_unneeded_yamls, remove_temps20from lib_v5.vr_network.model_param_init import ModelParameters21from lib_v5 import spec_utils22from pathlib import Path23from separate import SeperateAttributes, SeperateDemucs, SeperateMDX, SeperateVR, save_format24from typing import List25 26 27logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)28logging.info('UVR BEGIN')29 30PREVIOUS_PATCH_WIN = 'UVR_Patch_1_12_23_14_54'31 32is_dnd_compatible = True33banner_placement = -234 35def save_data(data):36 """37 Saves given data as a .pkl (pickle) file38 39 Paramters:40 data(dict):41 Dictionary containing all the necessary data to save42 """43 # Open data file, create it if it does not exist44 with open('data.pkl', 'wb') as data_file:45 pickle.dump(data, data_file)46 47def load_data() -> dict:48 """49 Loads saved pkl file and returns the stored data50 51 Returns(dict):52 Dictionary containing all the saved data53 """54 try:55 with open('data.pkl', 'rb') as data_file: # Open data file56 data = pickle.load(data_file)57 58 return data59 except (ValueError, FileNotFoundError):60 # Data File is corrupted or not found so recreate it61 62 save_data(data=DEFAULT_DATA)63 64 return load_data()65 66def load_model_hash_data(dictionary):67 '''Get the model hash dictionary'''68 69 with open(dictionary) as d:70 data = d.read()71 72 return json.loads(data)73 74# Change the current working directory to the directory75# this file sits in76if getattr(sys, 'frozen', False):77 # If the application is run as a bundle, the PyInstaller bootloader78 # extends the sys module by a flag frozen=True and sets the app79 # path into variable _MEIPASS'.80 BASE_PATH = sys._MEIPASS81else:82 BASE_PATH = os.path.dirname(os.path.abspath(__file__))83 84os.chdir(BASE_PATH) # Change the current working directory to the base path85 86debugger = []87 88#--Constants--89#Models90MODELS_DIR = os.path.join(BASE_PATH, 'models')91VR_MODELS_DIR = os.path.join(MODELS_DIR, 'VR_Models')92MDX_MODELS_DIR = os.path.join(MODELS_DIR, 'MDX_Net_Models')93DEMUCS_MODELS_DIR = os.path.join(MODELS_DIR, 'Demucs_Models')94DEMUCS_NEWER_REPO_DIR = os.path.join(DEMUCS_MODELS_DIR, 'v3_v4_repo')95MDX_MIXER_PATH = os.path.join(BASE_PATH, 'lib_v5', 'mixer.ckpt')96 97#Cache & Parameters98VR_HASH_DIR = os.path.join(VR_MODELS_DIR, 'model_data')99VR_HASH_JSON = os.path.join(VR_MODELS_DIR, 'model_data', 'model_data.json')100MDX_HASH_DIR = os.path.join(MDX_MODELS_DIR, 'model_data')101MDX_HASH_JSON = os.path.join(MDX_MODELS_DIR, 'model_data', 'model_data.json')102DEMUCS_MODEL_NAME_SELECT = os.path.join(DEMUCS_MODELS_DIR, 'model_data', 'model_name_mapper.json')103MDX_MODEL_NAME_SELECT = os.path.join(MDX_MODELS_DIR, 'model_data', 'model_name_mapper.json')104ENSEMBLE_CACHE_DIR = os.path.join(BASE_PATH, 'gui_data', 'saved_ensembles')105SETTINGS_CACHE_DIR = os.path.join(BASE_PATH, 'gui_data', 'saved_settings')106VR_PARAM_DIR = os.path.join(BASE_PATH, 'lib_v5', 'vr_network', 'modelparams')107SAMPLE_CLIP_PATH = os.path.join(BASE_PATH, 'temp_sample_clips')108ENSEMBLE_TEMP_PATH = os.path.join(BASE_PATH, 'ensemble_temps')109 110#Style111ICON_IMG_PATH = os.path.join(BASE_PATH, 'gui_data', 'img', 'GUI-Icon.ico')112FONT_PATH = os.path.join(BASE_PATH, 'gui_data', 'fonts', 'centurygothic', 'GOTHIC.TTF')#ensemble_temps113 114#Other115COMPLETE_CHIME = os.path.join(BASE_PATH, 'gui_data', 'complete_chime.wav')116FAIL_CHIME = os.path.join(BASE_PATH, 'gui_data', 'fail_chime.wav')117CHANGE_LOG = os.path.join(BASE_PATH, 'gui_data', 'change_log.txt')118SPLASH_DOC = os.path.join(BASE_PATH, 'tmp', 'splash.txt')119 120file_check(os.path.join(MODELS_DIR, 'Main_Models'), VR_MODELS_DIR)121file_check(os.path.join(DEMUCS_MODELS_DIR, 'v3_repo'), DEMUCS_NEWER_REPO_DIR)122remove_unneeded_yamls(DEMUCS_MODELS_DIR)123 124remove_temps(ENSEMBLE_TEMP_PATH)125remove_temps(SAMPLE_CLIP_PATH)126remove_temps(os.path.join(BASE_PATH, 'img'))127 128if not os.path.isdir(ENSEMBLE_TEMP_PATH):129 os.mkdir(ENSEMBLE_TEMP_PATH)130 131if not os.path.isdir(SAMPLE_CLIP_PATH):132 os.mkdir(SAMPLE_CLIP_PATH)133 134model_hash_table = {}135data = load_data()136 137class ModelData():138 def __init__(self, model_name: str, 139 selected_process_method=ENSEMBLE_MODE, 140 is_secondary_model=False, 141 primary_model_primary_stem=None, 142 is_primary_model_primary_stem_only=False, 143 is_primary_model_secondary_stem_only=False, 144 is_pre_proc_model=False,145 is_dry_check=False):146 147 self.is_gpu_conversion = 0 if root.is_gpu_conversion_var.get() else -1148 self.is_normalization = root.is_normalization_var.get()149 self.is_primary_stem_only = root.is_primary_stem_only_var.get()150 self.is_secondary_stem_only = root.is_secondary_stem_only_var.get()151 self.is_denoise = root.is_denoise_var.get()152 self.mdx_batch_size = 1 if root.mdx_batch_size_var.get() == DEF_OPT else int(root.mdx_batch_size_var.get())153 self.is_mdx_ckpt = False154 self.wav_type_set = root.wav_type_set155 self.mp3_bit_set = root.mp3_bit_set_var.get()156 self.save_format = root.save_format_var.get()157 self.is_invert_spec = root.is_invert_spec_var.get()158 self.is_mixer_mode = root.is_mixer_mode_var.get()159 self.demucs_stems = root.demucs_stems_var.get()160 self.demucs_source_list = []161 self.demucs_stem_count = 0162 self.mixer_path = MDX_MIXER_PATH163 self.model_name = model_name164 self.process_method = selected_process_method165 self.model_status = False if self.model_name == CHOOSE_MODEL or self.model_name == NO_MODEL else True166 self.primary_stem = None167 self.secondary_stem = None168 self.is_ensemble_mode = False169 self.ensemble_primary_stem = None170 self.ensemble_secondary_stem = None171 self.primary_model_primary_stem = primary_model_primary_stem172 self.is_secondary_model = is_secondary_model173 self.secondary_model = None174 self.secondary_model_scale = None175 self.demucs_4_stem_added_count = 0176 self.is_demucs_4_stem_secondaries = False177 self.is_4_stem_ensemble = False178 self.pre_proc_model = None179 self.pre_proc_model_activated = False180 self.is_pre_proc_model = is_pre_proc_model181 self.is_dry_check = is_dry_check182 self.model_samplerate = 44100183 self.model_capacity = 32, 128184 self.is_vr_51_model = False185 self.is_demucs_pre_proc_model_inst_mix = False186 self.manual_download_Button = None187 self.secondary_model_4_stem = []188 self.secondary_model_4_stem_scale = []189 self.secondary_model_4_stem_names = []190 self.secondary_model_4_stem_model_names_list = []191 self.all_models = []192 self.secondary_model_other = None193 self.secondary_model_scale_other = None194 self.secondary_model_bass = None195 self.secondary_model_scale_bass = None196 self.secondary_model_drums = None197 self.secondary_model_scale_drums = None198 199 if selected_process_method == ENSEMBLE_MODE:200 partitioned_name = model_name.partition(ENSEMBLE_PARTITION)201 self.process_method = partitioned_name[0]202 self.model_name = partitioned_name[2]203 self.model_and_process_tag = model_name204 self.ensemble_primary_stem, self.ensemble_secondary_stem = root.return_ensemble_stems()205 self.is_ensemble_mode = True if not is_secondary_model and not is_pre_proc_model else False206 self.is_4_stem_ensemble = True if root.ensemble_main_stem_var.get() == FOUR_STEM_ENSEMBLE and self.is_ensemble_mode else False207 self.pre_proc_model_activated = root.is_demucs_pre_proc_model_activate_var.get() if not self.ensemble_primary_stem == VOCAL_STEM else False208 209 if self.process_method == VR_ARCH_TYPE:210 self.is_secondary_model_activated = root.vr_is_secondary_model_activate_var.get() if not self.is_secondary_model else False211 self.aggression_setting = float(int(root.aggression_setting_var.get())/100)212 self.is_tta = root.is_tta_var.get()213 self.is_post_process = root.is_post_process_var.get()214 self.window_size = int(root.window_size_var.get())215 self.batch_size = 1 if root.batch_size_var.get() == DEF_OPT else int(root.batch_size_var.get())216 self.crop_size = int(root.crop_size_var.get())217 self.is_high_end_process = 'mirroring' if root.is_high_end_process_var.get() else 'None'218 self.post_process_threshold = float(root.post_process_threshold_var.get())219 self.model_capacity = 32, 128220 self.model_path = os.path.join(VR_MODELS_DIR, f"{self.model_name}.pth")221 self.get_model_hash()222 if self.model_hash:223 self.model_data = self.get_model_data(VR_HASH_DIR, root.vr_hash_MAPPER) if not self.model_hash == WOOD_INST_MODEL_HASH else WOOD_INST_PARAMS224 if self.model_data:225 vr_model_param = os.path.join(VR_PARAM_DIR, "{}.json".format(self.model_data["vr_model_param"]))226 self.primary_stem = self.model_data["primary_stem"]227 self.secondary_stem = STEM_PAIR_MAPPER[self.primary_stem]228 self.vr_model_param = ModelParameters(vr_model_param)229 self.model_samplerate = self.vr_model_param.param['sr']230 if "nout" in self.model_data.keys() and "nout_lstm" in self.model_data.keys():231 self.model_capacity = self.model_data["nout"], self.model_data["nout_lstm"]232 self.is_vr_51_model = True233 else:234 self.model_status = False235 236 if self.process_method == MDX_ARCH_TYPE:237 self.is_secondary_model_activated = root.mdx_is_secondary_model_activate_var.get() if not is_secondary_model else False238 self.margin = int(root.margin_var.get())239 self.chunks = root.determine_auto_chunks(root.chunks_var.get(), self.is_gpu_conversion) if root.is_chunk_mdxnet_var.get() else 0240 self.get_mdx_model_path()241 self.get_model_hash()242 if self.model_hash:243 self.model_data = self.get_model_data(MDX_HASH_DIR, root.mdx_hash_MAPPER)244 if self.model_data:245 self.compensate = self.model_data["compensate"] if root.compensate_var.get() == AUTO_SELECT else float(root.compensate_var.get())246 self.mdx_dim_f_set = self.model_data["mdx_dim_f_set"]247 self.mdx_dim_t_set = self.model_data["mdx_dim_t_set"]248 self.mdx_n_fft_scale_set = self.model_data["mdx_n_fft_scale_set"]249 self.primary_stem = self.model_data["primary_stem"]250 self.secondary_stem = STEM_PAIR_MAPPER[self.primary_stem]251 else:252 self.model_status = False253 254 if self.process_method == DEMUCS_ARCH_TYPE:255 self.is_secondary_model_activated = root.demucs_is_secondary_model_activate_var.get() if not is_secondary_model else False256 if not self.is_ensemble_mode:257 self.pre_proc_model_activated = root.is_demucs_pre_proc_model_activate_var.get() if not root.demucs_stems_var.get() in [VOCAL_STEM, INST_STEM] else False258 self.overlap = float(root.overlap_var.get())259 self.margin_demucs = int(root.margin_demucs_var.get())260 self.chunks_demucs = root.determine_auto_chunks(root.chunks_demucs_var.get(), self.is_gpu_conversion)261 self.shifts = int(root.shifts_var.get())262 self.is_split_mode = root.is_split_mode_var.get()263 self.segment = root.segment_var.get()264 self.is_chunk_demucs = root.is_chunk_demucs_var.get()265 self.is_demucs_combine_stems = root.is_demucs_combine_stems_var.get()266 self.is_primary_stem_only = root.is_primary_stem_only_var.get() if self.is_ensemble_mode else root.is_primary_stem_only_Demucs_var.get() 267 self.is_secondary_stem_only = root.is_secondary_stem_only_var.get() if self.is_ensemble_mode else root.is_secondary_stem_only_Demucs_var.get()268 self.get_demucs_model_path()269 self.get_demucs_model_data()270 271 self.model_basename = os.path.splitext(os.path.basename(self.model_path))[0] if self.model_status else None272 self.pre_proc_model_activated = self.pre_proc_model_activated if not self.is_secondary_model else False273 274 self.is_primary_model_primary_stem_only = is_primary_model_primary_stem_only275 self.is_primary_model_secondary_stem_only = is_primary_model_secondary_stem_only276 277 if self.is_secondary_model_activated and self.model_status:278 if (not self.is_ensemble_mode and root.demucs_stems_var.get() == ALL_STEMS and self.process_method == DEMUCS_ARCH_TYPE) or self.is_4_stem_ensemble:279 for key in DEMUCS_4_SOURCE_LIST:280 self.secondary_model_data(key)281 self.secondary_model_4_stem.append(self.secondary_model)282 self.secondary_model_4_stem_scale.append(self.secondary_model_scale)283 self.secondary_model_4_stem_names.append(key)284 self.demucs_4_stem_added_count = sum(i is not None for i in self.secondary_model_4_stem)285 self.is_secondary_model_activated = False if all(i is None for i in self.secondary_model_4_stem) else True286 self.demucs_4_stem_added_count = self.demucs_4_stem_added_count - 1 if self.is_secondary_model_activated else self.demucs_4_stem_added_count287 if self.is_secondary_model_activated:288 self.secondary_model_4_stem_model_names_list = [None if i is None else i.model_basename for i in self.secondary_model_4_stem]289 self.is_demucs_4_stem_secondaries = True 290 else:291 primary_stem = self.ensemble_primary_stem if self.is_ensemble_mode and self.process_method == DEMUCS_ARCH_TYPE else self.primary_stem292 self.secondary_model_data(primary_stem)293 294 if self.process_method == DEMUCS_ARCH_TYPE and not is_secondary_model:295 if self.demucs_stem_count >= 3 and self.pre_proc_model_activated:296 self.pre_proc_model_activated = True297 self.pre_proc_model = root.process_determine_demucs_pre_proc_model(self.primary_stem)298 self.is_demucs_pre_proc_model_inst_mix = root.is_demucs_pre_proc_model_inst_mix_var.get() if self.pre_proc_model else False299 300 def secondary_model_data(self, primary_stem):301 secondary_model_data = root.process_determine_secondary_model(self.process_method, primary_stem, self.is_primary_stem_only, self.is_secondary_stem_only)302 self.secondary_model = secondary_model_data[0]303 self.secondary_model_scale = secondary_model_data[1]304 self.is_secondary_model_activated = False if not self.secondary_model else True305 if self.secondary_model:306 self.is_secondary_model_activated = False if self.secondary_model.model_basename == self.model_basename else True307 308 def get_mdx_model_path(self):309 310 if self.model_name.endswith(CKPT):311 # self.chunks = 0312 # self.is_mdx_batch_mode = True313 self.is_mdx_ckpt = True314 315 ext = '' if self.is_mdx_ckpt else ONNX316 317 for file_name, chosen_mdx_model in root.mdx_name_select_MAPPER.items():318 if self.model_name in chosen_mdx_model:319 self.model_path = os.path.join(MDX_MODELS_DIR, f"{file_name}{ext}")320 break321 else:322 self.model_path = os.path.join(MDX_MODELS_DIR, f"{self.model_name}{ext}")323 324 self.mixer_path = os.path.join(MDX_MODELS_DIR, f"mixer_val.ckpt")325 326 def get_demucs_model_path(self):327 328 demucs_newer = [True for x in DEMUCS_NEWER_TAGS if x in self.model_name]329 demucs_model_dir = DEMUCS_NEWER_REPO_DIR if demucs_newer else DEMUCS_MODELS_DIR330 331 for file_name, chosen_model in root.demucs_name_select_MAPPER.items():332 if self.model_name in chosen_model:333 self.model_path = os.path.join(demucs_model_dir, file_name)334 break335 else:336 self.model_path = os.path.join(DEMUCS_NEWER_REPO_DIR, f'{self.model_name}.yaml')337 338 def get_demucs_model_data(self):339 340 self.demucs_version = DEMUCS_V4341 342 for key, value in DEMUCS_VERSION_MAPPER.items():343 if value in self.model_name:344 self.demucs_version = key345 346 self.demucs_source_list = DEMUCS_2_SOURCE if DEMUCS_UVR_MODEL in self.model_name else DEMUCS_4_SOURCE347 self.demucs_source_map = DEMUCS_2_SOURCE_MAPPER if DEMUCS_UVR_MODEL in self.model_name else DEMUCS_4_SOURCE_MAPPER348 self.demucs_stem_count = 2 if DEMUCS_UVR_MODEL in self.model_name else 4349 350 if not self.is_ensemble_mode:351 self.primary_stem = PRIMARY_STEM if self.demucs_stems == ALL_STEMS else self.demucs_stems352 self.secondary_stem = STEM_PAIR_MAPPER[self.primary_stem]353 354 def get_model_data(self, model_hash_dir, hash_mapper):355 model_settings_json = os.path.join(model_hash_dir, "{}.json".format(self.model_hash))356 357 if os.path.isfile(model_settings_json):358 return json.load(open(model_settings_json))359 else:360 for hash, settings in hash_mapper.items():361 if self.model_hash in hash:362 return settings363 else:364 return self.get_model_data_from_popup()365 366 def get_model_data_from_popup(self):367 return None368 369 def get_model_hash(self):370 self.model_hash = None371 372 if not os.path.isfile(self.model_path):373 self.model_status = False374 self.model_hash is None375 else:376 if model_hash_table:377 for (key, value) in model_hash_table.items():378 if self.model_path == key:379 self.model_hash = value380 break381 382 if not self.model_hash:383 try:384 with open(self.model_path, 'rb') as f:385 f.seek(- 10000 * 1024, 2)386 self.model_hash = hashlib.md5(f.read()).hexdigest()387 except:388 self.model_hash = hashlib.md5(open(self.model_path,'rb').read()).hexdigest()389 390 table_entry = {self.model_path: self.model_hash}391 model_hash_table.update(table_entry)392 393 394class Ensembler():395 def __init__(self, is_manual_ensemble=False):396 self.is_save_all_outputs_ensemble = root.is_save_all_outputs_ensemble_var.get()397 chosen_ensemble_name = '{}'.format(root.chosen_ensemble_var.get().replace(" ", "_")) if not root.chosen_ensemble_var.get() == CHOOSE_ENSEMBLE_OPTION else 'Ensembled'398 ensemble_algorithm = root.ensemble_type_var.get().partition("/")399 ensemble_main_stem_pair = root.ensemble_main_stem_var.get().partition("/")400 time_stamp = round(time.time())401 self.audio_tool = MANUAL_ENSEMBLE402 self.main_export_path = Path(root.export_path_var.get())403 self.chosen_ensemble = f"_{chosen_ensemble_name}" if root.is_append_ensemble_name_var.get() else ''404 ensemble_folder_name = self.main_export_path if self.is_save_all_outputs_ensemble else ENSEMBLE_TEMP_PATH405 self.ensemble_folder_name = os.path.join(ensemble_folder_name, '{}_Outputs_{}'.format(chosen_ensemble_name, time_stamp))406 self.is_testing_audio = f"{time_stamp}_" if root.is_testing_audio_var.get() else ''407 self.primary_algorithm = ensemble_algorithm[0]408 self.secondary_algorithm = ensemble_algorithm[2]409 self.ensemble_primary_stem = ensemble_main_stem_pair[0]410 self.ensemble_secondary_stem = ensemble_main_stem_pair[2]411 self.is_normalization = root.is_normalization_var.get()412 self.wav_type_set = root.wav_type_set413 self.mp3_bit_set = root.mp3_bit_set_var.get()414 self.save_format = root.save_format_var.get()415 if not is_manual_ensemble:416 os.mkdir(self.ensemble_folder_name)417 418 def ensemble_outputs(self, audio_file_base, export_path, stem, is_4_stem=False, is_inst_mix=False):419 """Processes the given outputs and ensembles them with the chosen algorithm"""420 421 if is_4_stem:422 algorithm = root.ensemble_type_var.get()423 stem_tag = stem424 else:425 if is_inst_mix:426 algorithm = self.secondary_algorithm427 stem_tag = f"{self.ensemble_secondary_stem} {INST_STEM}"428 else:429 algorithm = self.primary_algorithm if stem == PRIMARY_STEM else self.secondary_algorithm430 stem_tag = self.ensemble_primary_stem if stem == PRIMARY_STEM else self.ensemble_secondary_stem431 432 stem_outputs = self.get_files_to_ensemble(folder=export_path, prefix=audio_file_base, suffix=f"_({stem_tag}).wav")433 audio_file_output = f"{self.is_testing_audio}{audio_file_base}{self.chosen_ensemble}_({stem_tag})"434 stem_save_path = os.path.join('{}'.format(self.main_export_path),'{}.wav'.format(audio_file_output))435 436 if stem_outputs:437 spec_utils.ensemble_inputs(stem_outputs, algorithm, self.is_normalization, self.wav_type_set, stem_save_path)438 save_format(stem_save_path, self.save_format, self.mp3_bit_set)439 440 if self.is_save_all_outputs_ensemble:441 for i in stem_outputs:442 save_format(i, self.save_format, self.mp3_bit_set)443 else:444 for i in stem_outputs:445 try:446 os.remove(i)447 except Exception as e:448 print(e)449 450 def ensemble_manual(self, audio_inputs, audio_file_base, is_bulk=False):451 """Processes the given outputs and ensembles them with the chosen algorithm"""452 453 is_mv_sep = True454 455 if is_bulk:456 number_list = list(set([os.path.basename(i).split("_")[0] for i in audio_inputs]))457 for n in number_list:458 current_list = [i for i in audio_inputs if os.path.basename(i).startswith(n)]459 audio_file_base = os.path.basename(current_list[0]).split('.wav')[0]460 stem_testing = "instrum" if "Instrumental" in audio_file_base else "vocals"461 if is_mv_sep:462 audio_file_base = audio_file_base.split("_")463 audio_file_base = f"{audio_file_base[1]}_{audio_file_base[2]}_{stem_testing}"464 self.ensemble_manual_process(current_list, audio_file_base, is_bulk)465 else:466 self.ensemble_manual_process(audio_inputs, audio_file_base, is_bulk)467 468 def ensemble_manual_process(self, audio_inputs, audio_file_base, is_bulk):469 470 algorithm = root.choose_algorithm_var.get()471 algorithm_text = "" if is_bulk else f"_({root.choose_algorithm_var.get()})"472 stem_save_path = os.path.join('{}'.format(self.main_export_path),'{}{}{}.wav'.format(self.is_testing_audio, audio_file_base, algorithm_text))473 spec_utils.ensemble_inputs(audio_inputs, algorithm, self.is_normalization, self.wav_type_set, stem_save_path)474 save_format(stem_save_path, self.save_format, self.mp3_bit_set)475 476 def get_files_to_ensemble(self, folder="", prefix="", suffix=""):477 """Grab all the files to be ensembled"""478 479 return [os.path.join(folder, i) for i in os.listdir(folder) if i.startswith(prefix) and i.endswith(suffix)]480 481 482def secondary_stem(stem):483 """Determines secondary stem"""484 485 for key, value in STEM_PAIR_MAPPER.items():486 if stem in key:487 secondary_stem = value488 489 return secondary_stem490 491 492class UVRInterface:493 def __init__(self) -> None:494 pass495 496 def assemble_model_data(self, model=None, arch_type=ENSEMBLE_MODE, is_dry_check=False) -> List[ModelData]:497 if arch_type == ENSEMBLE_STEM_CHECK:498 model_data = self.model_data_table499 missing_models = [model.model_status for model in model_data if not model.model_status]500 501 if missing_models or not model_data:502 model_data: List[ModelData] = [ModelData(model_name, is_dry_check=is_dry_check) for model_name in self.ensemble_model_list]503 self.model_data_table = model_data504 505 if arch_type == ENSEMBLE_MODE:506 model_data: List[ModelData] = [ModelData(model_name) for model_name in self.ensemble_listbox_get_all_selected_models()]507 if arch_type == ENSEMBLE_CHECK:508 model_data: List[ModelData] = [ModelData(model)]509 if arch_type == VR_ARCH_TYPE or arch_type == VR_ARCH_PM:510 model_data: List[ModelData] = [ModelData(model, VR_ARCH_TYPE)]511 if arch_type == MDX_ARCH_TYPE:512 model_data: List[ModelData] = [ModelData(model, MDX_ARCH_TYPE)]513 if arch_type == DEMUCS_ARCH_TYPE:514 model_data: List[ModelData] = [ModelData(model, DEMUCS_ARCH_TYPE)]#515 516 return model_data517 518 def create_sample(self, audio_file, sample_path=SAMPLE_CLIP_PATH):519 try:520 with audioread.audio_open(audio_file) as f:521 track_length = int(f.duration)522 except Exception as e:523 print('Audioread failed to get duration. Trying Librosa...')524 y, sr = librosa.load(audio_file, mono=False, sr=44100)525 track_length = int(librosa.get_duration(y=y, sr=sr))526 527 clip_duration = int(root.model_sample_mode_duration_var.get())528 529 if track_length >= clip_duration:530 offset_cut = track_length//3531 off_cut = offset_cut + track_length532 if not off_cut >= clip_duration:533 offset_cut = 0534 name_apped = f'{clip_duration}_second_'535 else:536 offset_cut, clip_duration = 0, track_length537 name_apped = ''538 539 sample = librosa.load(audio_file, offset=offset_cut, duration=clip_duration, mono=False, sr=44100)[0].T540 audio_sample = os.path.join(sample_path, f'{os.path.splitext(os.path.basename(audio_file))[0]}_{name_apped}sample.wav')541 sf.write(audio_sample, sample, 44100)542 543 return audio_sample544 545 def verify_audio(self, audio_file, is_process=True, sample_path=None):546 is_good = False547 error_data = ''548 549 if os.path.isfile(audio_file):550 try:551 librosa.load(audio_file, duration=3, mono=False, sr=44100) if not type(sample_path) is str else self.create_sample(audio_file, sample_path)552 is_good = True553 except Exception as e:554 error_name = f'{type(e).__name__}'555 traceback_text = ''.join(traceback.format_tb(e.__traceback__))556 message = f'{error_name}: "{e}"\n{traceback_text}"'557 if is_process:558 audio_base_name = os.path.basename(audio_file)559 self.error_log_var.set(f'Error Loading the Following File:\n\n\"{audio_base_name}\"\n\nRaw Error Details:\n\n{message}')560 else:561 error_data = AUDIO_VERIFICATION_CHECK(audio_file, message)562 563 if is_process:564 return is_good565 else:566 return is_good, error_data567 568 def cached_sources_clear(self):569 self.vr_cache_source_mapper = {}570 self.mdx_cache_source_mapper = {}571 self.demucs_cache_source_mapper = {}572 573 def cached_model_source_holder(self, process_method, sources, model_name=None):574 if process_method == VR_ARCH_TYPE:575 self.vr_cache_source_mapper = {**self.vr_cache_source_mapper, **{model_name: sources}}576 if process_method == MDX_ARCH_TYPE:577 self.mdx_cache_source_mapper = {**self.mdx_cache_source_mapper, **{model_name: sources}}578 if process_method == DEMUCS_ARCH_TYPE:579 self.demucs_cache_source_mapper = {**self.demucs_cache_source_mapper, **{model_name: sources}}580 581 def cached_source_callback(self, process_method, model_name=None):582 model, sources = None, None583 584 if process_method == VR_ARCH_TYPE:585 mapper = self.vr_cache_source_mapper586 if process_method == MDX_ARCH_TYPE:587 mapper = self.mdx_cache_source_mapper588 if process_method == DEMUCS_ARCH_TYPE:589 mapper = self.demucs_cache_source_mapper590 591 for key, value in mapper.items():592 if model_name in key:593 model = key594 sources = value595 596 return model, sources597 598 def cached_source_model_list_check(self, model_list: List[ModelData]):599 model: ModelData600 primary_model_names = lambda process_method:[model.model_basename if model.process_method == process_method else None for model in model_list]601 secondary_model_names = lambda process_method:[model.secondary_model.model_basename if model.is_secondary_model_activated and model.process_method == process_method else None for model in model_list]602 603 self.vr_primary_model_names = primary_model_names(VR_ARCH_TYPE)604 self.mdx_primary_model_names = primary_model_names(MDX_ARCH_TYPE)605 self.demucs_primary_model_names = primary_model_names(DEMUCS_ARCH_TYPE)606 self.vr_secondary_model_names = secondary_model_names(VR_ARCH_TYPE)607 self.mdx_secondary_model_names = secondary_model_names(MDX_ARCH_TYPE)608 self.demucs_secondary_model_names = [model.secondary_model.model_basename if model.is_secondary_model_activated and model.process_method == DEMUCS_ARCH_TYPE and not model.secondary_model is None else None for model in model_list]609 self.demucs_pre_proc_model_name = [model.pre_proc_model.model_basename if model.pre_proc_model else None for model in model_list]#list(dict.fromkeys())610 611 for model in model_list:612 if model.process_method == DEMUCS_ARCH_TYPE and model.is_demucs_4_stem_secondaries:613 if not model.is_4_stem_ensemble:614 self.demucs_secondary_model_names = model.secondary_model_4_stem_model_names_list615 break616 else:617 for i in model.secondary_model_4_stem_model_names_list:618 self.demucs_secondary_model_names.append(i)619 620 self.all_models = self.vr_primary_model_names + self.mdx_primary_model_names + self.demucs_primary_model_names + self.vr_secondary_model_names + self.mdx_secondary_model_names + self.demucs_secondary_model_names + self.demucs_pre_proc_model_name621 622 def process(self, model_name, arch_type, audio_file, export_path, is_model_sample_mode=False, is_4_stem_ensemble=False, set_progress_func=None, console_write=print) -> SeperateAttributes:623 stime = time.perf_counter()624 time_elapsed = lambda:f'Time Elapsed: {time.strftime("%H:%M:%S", time.gmtime(int(time.perf_counter() - stime)))}'625 626 if arch_type==ENSEMBLE_MODE:627 model_list, ensemble = self.assemble_model_data(), Ensembler()628 export_path = ensemble.ensemble_folder_name629 is_ensemble = True630 else:631 model_list = self.assemble_model_data(model_name, arch_type)632 is_ensemble = False633 self.cached_source_model_list_check(model_list)634 model = model_list[0]635 636 if self.verify_audio(audio_file):637 audio_file = self.create_sample(audio_file) if is_model_sample_mode else audio_file638 else:639 print(f'"{os.path.basename(audio_file)}\" is missing or currupted.\n')640 exit()641 642 audio_file_base = f"{os.path.splitext(os.path.basename(audio_file))[0]}"643 audio_file_base = audio_file_base if is_ensemble else f"{round(time.time())}_{audio_file_base}"644 audio_file_base = audio_file_base if not is_ensemble else f"{audio_file_base}_{model.model_basename}"645 if not is_ensemble:646 audio_file_base = f"{audio_file_base}_{model.model_basename}"647 648 if not is_ensemble:649 export_path = os.path.join(Path(export_path), model.model_basename, os.path.splitext(os.path.basename(audio_file))[0])650 if not os.path.isdir(export_path):651 os.makedirs(export_path) 652 653 if set_progress_func is None:654 pbar = tqdm(total=1)655 self._progress = 0656 def set_progress_func(step, inference_iterations=0):657 progress_curr = step + inference_iterations658 pbar.update(progress_curr-self._progress)659 self._progress = progress_curr660 661 def postprocess():662 pbar.close()663 else:664 def postprocess():665 pass666 667 process_data = {668 'model_data': model,669 'export_path': export_path,670 'audio_file_base': audio_file_base,671 'audio_file': audio_file,672 'set_progress_bar': set_progress_func,673 'write_to_console': lambda progress_text, base_text='': console_write(base_text + progress_text),674 'process_iteration': lambda:None,675 'cached_source_callback': self.cached_source_callback,676 'cached_model_source_holder': self.cached_model_source_holder,677 'list_all_models': self.all_models,678 'is_ensemble_master': is_ensemble,679 'is_4_stem_ensemble': is_ensemble and is_4_stem_ensemble680 }681 if model.process_method == VR_ARCH_TYPE:682 seperator = SeperateVR(model, process_data)683 if model.process_method == MDX_ARCH_TYPE:684 seperator = SeperateMDX(model, process_data)685 if model.process_method == DEMUCS_ARCH_TYPE:686 seperator = SeperateDemucs(model, process_data)687 688 seperator.seperate()689 postprocess()690 691 if is_ensemble:692 audio_file_base = audio_file_base.replace(f"_{model.model_basename}", "")693 console_write(ENSEMBLING_OUTPUTS)694 695 if is_4_stem_ensemble:696 for output_stem in DEMUCS_4_SOURCE_LIST:697 ensemble.ensemble_outputs(audio_file_base, export_path, output_stem, is_4_stem=True)698 else:699 if not root.is_secondary_stem_only_var.get():700 ensemble.ensemble_outputs(audio_file_base, export_path, PRIMARY_STEM)701 if not root.is_primary_stem_only_var.get():702 ensemble.ensemble_outputs(audio_file_base, export_path, SECONDARY_STEM)703 ensemble.ensemble_outputs(audio_file_base, export_path, SECONDARY_STEM, is_inst_mix=True)704 705 console_write(DONE)706 707 if is_model_sample_mode:708 if os.path.isfile(audio_file):709 os.remove(audio_file)710 711 torch.cuda.empty_cache()712 713 if is_ensemble and len(os.listdir(export_path)) == 0:714 shutil.rmtree(export_path)715 console_write(f'Process Complete, using time: {time_elapsed()}\nOutput path: {export_path}')716 self.cached_sources_clear()717 return seperator718 719 720class RootWrapper:721 def __init__(self, var) -> None:722 self.var=var723 724 def set(self, val):725 self.var=val726 727 def get(self):728 return self.var729 730class FakeRoot:731 def __init__(self) -> None:732 self.wav_type_set = 'PCM_16'733 self.vr_hash_MAPPER = load_model_hash_data(VR_HASH_JSON)734 self.mdx_hash_MAPPER = load_model_hash_data(MDX_HASH_JSON)735 self.mdx_name_select_MAPPER = load_model_hash_data(MDX_MODEL_NAME_SELECT)736 self.demucs_name_select_MAPPER = load_model_hash_data(DEMUCS_MODEL_NAME_SELECT)737 738 def __getattribute__(self, __name: str):739 try:740 return super().__getattribute__(__name)741 except AttributeError:742 wrapped=RootWrapper(None)743 super().__setattr__(__name, wrapped)744 return wrapped745 746 def load_saved_settings(self, loaded_setting: dict, process_method=None):747 """Loads user saved application settings or resets to default"""748 749 for key, value in DEFAULT_DATA.items():750 if not key in loaded_setting.keys():751 loaded_setting = {**loaded_setting, **{key:value}}752 loaded_setting['batch_size'] = DEF_OPT753 754 is_ensemble = True if process_method == ENSEMBLE_MODE else False755 756 if not process_method or process_method == VR_ARCH_PM or is_ensemble:757 self.vr_model_var.set(loaded_setting['vr_model'])758 self.aggression_setting_var.set(loaded_setting['aggression_setting'])759 self.window_size_var.set(loaded_setting['window_size'])760 self.batch_size_var.set(loaded_setting['batch_size'])761 self.crop_size_var.set(loaded_setting['crop_size'])762 self.is_tta_var.set(loaded_setting['is_tta'])763 self.is_output_image_var.set(loaded_setting['is_output_image'])764 self.is_post_process_var.set(loaded_setting['is_post_process'])765 self.is_high_end_process_var.set(loaded_setting['is_high_end_process'])766 self.post_process_threshold_var.set(loaded_setting['post_process_threshold'])767 self.vr_voc_inst_secondary_model_var.set(loaded_setting['vr_voc_inst_secondary_model'])768 self.vr_other_secondary_model_var.set(loaded_setting['vr_other_secondary_model'])769 self.vr_bass_secondary_model_var.set(loaded_setting['vr_bass_secondary_model'])770 self.vr_drums_secondary_model_var.set(loaded_setting['vr_drums_secondary_model'])771 self.vr_is_secondary_model_activate_var.set(loaded_setting['vr_is_secondary_model_activate'])772 self.vr_voc_inst_secondary_model_scale_var.set(loaded_setting['vr_voc_inst_secondary_model_scale'])773 self.vr_other_secondary_model_scale_var.set(loaded_setting['vr_other_secondary_model_scale'])774 self.vr_bass_secondary_model_scale_var.set(loaded_setting['vr_bass_secondary_model_scale'])775 self.vr_drums_secondary_model_scale_var.set(loaded_setting['vr_drums_secondary_model_scale'])776 777 if not process_method or process_method == DEMUCS_ARCH_TYPE or is_ensemble:778 self.demucs_model_var.set(loaded_setting['demucs_model'])779 self.segment_var.set(loaded_setting['segment'])780 self.overlap_var.set(loaded_setting['overlap'])781 self.shifts_var.set(loaded_setting['shifts'])782 self.chunks_demucs_var.set(loaded_setting['chunks_demucs'])783 self.margin_demucs_var.set(loaded_setting['margin_demucs'])784 self.is_chunk_demucs_var.set(loaded_setting['is_chunk_demucs'])785 self.is_chunk_mdxnet_var.set(loaded_setting['is_chunk_mdxnet'])786 self.is_primary_stem_only_Demucs_var.set(loaded_setting['is_primary_stem_only_Demucs'])787 self.is_secondary_stem_only_Demucs_var.set(loaded_setting['is_secondary_stem_only_Demucs'])788 self.is_split_mode_var.set(loaded_setting['is_split_mode'])789 self.is_demucs_combine_stems_var.set(loaded_setting['is_demucs_combine_stems'])790 self.demucs_voc_inst_secondary_model_var.set(loaded_setting['demucs_voc_inst_secondary_model'])791 self.demucs_other_secondary_model_var.set(loaded_setting['demucs_other_secondary_model'])792 self.demucs_bass_secondary_model_var.set(loaded_setting['demucs_bass_secondary_model'])793 self.demucs_drums_secondary_model_var.set(loaded_setting['demucs_drums_secondary_model'])794 self.demucs_is_secondary_model_activate_var.set(loaded_setting['demucs_is_secondary_model_activate'])795 self.demucs_voc_inst_secondary_model_scale_var.set(loaded_setting['demucs_voc_inst_secondary_model_scale'])796 self.demucs_other_secondary_model_scale_var.set(loaded_setting['demucs_other_secondary_model_scale'])797 self.demucs_bass_secondary_model_scale_var.set(loaded_setting['demucs_bass_secondary_model_scale'])798 self.demucs_drums_secondary_model_scale_var.set(loaded_setting['demucs_drums_secondary_model_scale'])799 self.demucs_stems_var.set(loaded_setting['demucs_stems'])800 # self.update_stem_checkbox_labels(self.demucs_stems_var.get(), demucs=True)801 self.demucs_pre_proc_model_var.set(data['demucs_pre_proc_model'])802 self.is_demucs_pre_proc_model_activate_var.set(data['is_demucs_pre_proc_model_activate'])803 self.is_demucs_pre_proc_model_inst_mix_var.set(data['is_demucs_pre_proc_model_inst_mix'])804 805 if not process_method or process_method == MDX_ARCH_TYPE or is_ensemble:806 self.mdx_net_model_var.set(loaded_setting['mdx_net_model'])807 self.chunks_var.set(loaded_setting['chunks'])808 self.margin_var.set(loaded_setting['margin'])809 self.compensate_var.set(loaded_setting['compensate'])810 self.is_denoise_var.set(loaded_setting['is_denoise'])811 self.is_invert_spec_var.set(loaded_setting['is_invert_spec'])812 self.is_mixer_mode_var.set(loaded_setting['is_mixer_mode'])813 self.mdx_batch_size_var.set(loaded_setting['mdx_batch_size'])814 self.mdx_voc_inst_secondary_model_var.set(loaded_setting['mdx_voc_inst_secondary_model'])815 self.mdx_other_secondary_model_var.set(loaded_setting['mdx_other_secondary_model'])816 self.mdx_bass_secondary_model_var.set(loaded_setting['mdx_bass_secondary_model'])817 self.mdx_drums_secondary_model_var.set(loaded_setting['mdx_drums_secondary_model'])818 self.mdx_is_secondary_model_activate_var.set(loaded_setting['mdx_is_secondary_model_activate'])819 self.mdx_voc_inst_secondary_model_scale_var.set(loaded_setting['mdx_voc_inst_secondary_model_scale'])820 self.mdx_other_secondary_model_scale_var.set(loaded_setting['mdx_other_secondary_model_scale'])821 self.mdx_bass_secondary_model_scale_var.set(loaded_setting['mdx_bass_secondary_model_scale'])822 self.mdx_drums_secondary_model_scale_var.set(loaded_setting['mdx_drums_secondary_model_scale'])823 824 if not process_method or is_ensemble:825 self.is_save_all_outputs_ensemble_var.set(loaded_setting['is_save_all_outputs_ensemble'])826 self.is_append_ensemble_name_var.set(loaded_setting['is_append_ensemble_name'])827 self.chosen_audio_tool_var.set(loaded_setting['chosen_audio_tool'])828 self.choose_algorithm_var.set(loaded_setting['choose_algorithm'])829 self.time_stretch_rate_var.set(loaded_setting['time_stretch_rate'])830 self.pitch_rate_var.set(loaded_setting['pitch_rate'])831 self.is_primary_stem_only_var.set(loaded_setting['is_primary_stem_only'])832 self.is_secondary_stem_only_var.set(loaded_setting['is_secondary_stem_only'])833 self.is_testing_audio_var.set(loaded_setting['is_testing_audio'])834 self.is_add_model_name_var.set(loaded_setting['is_add_model_name'])835 self.is_accept_any_input_var.set(loaded_setting["is_accept_any_input"])836 self.is_task_complete_var.set(loaded_setting['is_task_complete'])837 self.is_create_model_folder_var.set(loaded_setting['is_create_model_folder'])838 self.mp3_bit_set_var.set(loaded_setting['mp3_bit_set'])839 self.save_format_var.set(loaded_setting['save_format'])840 self.wav_type_set_var.set(loaded_setting['wav_type_set'])841 self.user_code_var.set(loaded_setting['user_code'])842 843 self.is_gpu_conversion_var.set(loaded_setting['is_gpu_conversion'])844 self.is_normalization_var.set(loaded_setting['is_normalization'])845 self.help_hints_var.set(loaded_setting['help_hints_var'])846 847 self.model_sample_mode_var.set(loaded_setting['model_sample_mode'])848 self.model_sample_mode_duration_var.set(loaded_setting['model_sample_mode_duration'])849 850 851root = FakeRoot()852root.load_saved_settings(DEFAULT_DATA)