UVRWUI Local (PATCH)
#11
by
Germanized
- opened
Patch Notes: UVR WebUI - LocalPatchByGermanized
Comparison Base: webUI.py
Patched Version: webUI(LocalPatchByGermanized).py
Author of Patch: Germanized
I. Core Functionality & Logic Changes
1. Imports
- Patched: Added
import shutilandimport wgetat the top of the file.- Base
webUI.pyimportedwgetlater in the main script block.
- Base
2. Class UVRWebUI - Initialization (__init__)
- Directory Creation:
- Base: Only creates
self.input_temp_dirusingos.mkdir(). Does not createself.export_path. - Patched:
- Creates
self.input_temp_dirusingos.makedirs(..., exist_ok=True). - Creates
self.export_pathusingos.makedirs(..., exist_ok=True). - Uses single quotes for directory path strings.
- Creates
- Base: Only creates
3. Class UVRWebUI - Model URL Fetching (get_models_url)
- Patched: Minor variable name changes in dictionary comprehension (e.g.,
model_namevsmodel,model_filename_partvsmodel_path). Logic remains identical. Uses single quotes for keys inzip.
4. Class UVRWebUI - Local Model Discovery (get_local_models)
- Error Handling & Directory Management:
- Base:
- Raises
ValueErrorifarchis unknown. - Assumes model directories exist; will fail if
os.listdir(model_dir)is called on a non-existent path. - Returns an unsorted list.
- Does not check if entries are files (could list subdirectories if they had the suffix).
- Raises
- Patched:
- Prints an error message to console and returns an empty list
[]ifarchis unknown (instead of raising an exception that stops Gradio). - Checks if
model_direxists. If not, creates it usingos.makedirs(..., exist_ok=True)and returns an empty list. - Includes a secondary check for
model_direxistence with a warning. - Returns a
sorted()list of model names. - Filters to ensure entries are files using
os.path.isfile().
- Prints an error message to console and returns an empty list
- Base:
5. Class UVRWebUI - Architecture Selection Update (arch_select_update)
- DEMUCS Architecture Handling:
- Base: If
DEMUCS_ARCH_TYPEis selected,raise gr.Error(f"{DEMUCS_ARCH_TYPE} not implempted"). - Patched:
- Sets a specific
model_update_labelfor Demucs. - Updates
arch_setting1andarch_setting2to be hidden (visible=False) and clears their choices/values, providing a cleaner UI when Demucs (which might not use these generic settings) is selected.
- Sets a specific
- Base: If
- Unknown Architecture Handling:
- Base:
raise gr.Error(f"Unkown arch type: {arch}"). - Patched: Displays a
gr.Error()in the UI and returns default/empty updates for the components to prevent UI breakage.
- Base:
- UI Feedback & Labels:
- Patched:
- Prints a warning to console if no local models are found for the selected architecture.
- Uses more specific labels for the
model_choicedropdown based on the selected architecture (e.g.,SELECT_VR_MODEL_MAIN_LABEL,CHOOSE_MDX_MODEL_MAIN_LABEL).
- Patched:
6. Class UVRWebUI - Model Selection Update (model_select_update)
- Handling "Choose Model" / Empty Selection:
- Base: If
model_name == CHOOSE_MODEL, returns[None for _ in range(4)]. - Patched:
- Handles
model_name == CHOOSE_MODELormodel_name is None(more robust). - If "Choose Model" is selected, returns specific
gr.update()calls to reset the stem-related checkbox and output component labels to their defaults (e.g.,PRIMARY_STEM only).
- Handles
- Base: If
- Model Data Assembly:
- Base:
model, = self.uvr.assemble_model_data(...)(assumes the method returns a list/tuple with exactly one item). - Patched:
model_data_list = self.uvr.assemble_model_data(...), then checksif not model_data_list: gr.Error(...), thenmodel = model_data_list[0]. More robust to empty returns.
- Base:
- Error Handling:
- Base: Raises
gr.Errorifmodel.model_statusis false. - Patched: Displays
gr.Errorifmodel_data_listis empty ormodel.model_statusis false, returning[None for _ in range(4)].
- Base: Raises
7. Class UVRWebUI - Exclusive Checkbox Logic (set_checkboxes_exclusive vs. Direct Handlers)
- Major Change:
- Base: Implements a
set_checkboxes_exclusivemethod which tries to manage exclusivity by passing all checkbox states to a handler. The logic withinnew_onchangeand howcallback_iinteracts withrootvariables for all checkboxes might not be perfectly aligned with Gradio's update model for ensuring allrootvariables are correctly set. - Patched:
- The
set_checkboxes_exclusivemethod, while defined, is not called indefine_layout. - Instead, two dedicated handler functions (
make_exclusive_primaryandmake_exclusive_secondary) are defined withindefine_layout. - These handlers are directly assigned to the
.changeevents ofself.primary_stem_onlyandself.secondary_stem_onlyrespectively. - This approach is more typical for Gradio and directly updates the
rootvariables and the other checkbox state.
- The
- Base: Implements a
8. Class UVRWebUI - Processing Logic (process)
- Gradio Progress:
- Base:
progress=gr.Progress().set_progress_funccallsprogress(progress_curr). - Patched:
progress=gr.Progress(track_tqdm=True).set_progress_funcis apassstatement (actual progress likely handled bytrack_tqdmif backend uses tqdm).
- Base:
- Input Audio Handling & Normalization:
- Base:
audio = (audio / np.iinfo(audio.dtype).max).astype(np.float32)(assumes integer input, could error on float).if len(audio.shape) > 1: audio = librosa.to_mono(audio.transpose(1, 0))(transposes then converts to mono).
- Patched:
- More robust normalization: checks
np.issubdtype(audio_data.dtype, np.integer)then normalizes. Also checksnp.issubdtype(audio_data.dtype, np.floating)and raises an error for unsupported types. - More robust mono conversion: Heuristic check for channel-first (
audio_data.shape[0] > 5) before transposing, then converts to mono.
- More robust normalization: checks
- Base:
- Input Filename Handling:
- Base: Directly uses
input_filenameto forminput_path. - Patched:
- Provides a default
input_filenameif empty ('audio_input.wav'). - Appends
.wavextension if the provided filename doesn't have a common audio extension. - Uses
os.path.basename(input_filename)when creatinginput_pathfor safety.
- Provides a default
- Base: Directly uses
- Temporary File Writing:
- Base:
soundfile.write(...)directly. - Patched:
soundfile.write(...)is wrapped in atry-exceptblock to catch errors.
- Base:
- Separator Object & Output Paths:
- Base: Typo
seperator = uvr.process(...). Assumesseperatorobject and its attributes are always valid when constructing output paths. No explicit checks for file existence before reading output stems. - Patched:
- Correct spelling:
separator = self.uvr.process(...). - Checks
if separator is None:after processing and returns an error message. - Before constructing output paths, checks if
separator.export_path,separator.audio_file_base, andseparator.primary_stem/secondary_stemare notNone. - Checks
if os.path.exists(...)for primary/secondary stem WAV files before attempting to read them withsoundfile.read(). - Appends specific error messages to the
msgstring if files are not found or separator data is missing.
- Correct spelling:
- Base: Typo
- Return Value:
- Base & Patched: Both return a 3-tuple. Patched version uses explicit parentheses
(primary_audio_out, secondary_audio_out, msg.strip()).
- Base & Patched: Both return a 3-tuple. Patched version uses explicit parentheses
II. User Interface (UI) - define_layout Method
1. Main Application Title
- Base:
gr.HTML("<h1> 🎵 Ultimate Vocal Remover WebUI 🎵 </h1>") - Patched:
gr.HTML('<h1> 🎵 Ultimate Vocal Remover WebUI Local Patch By Germanized🎵 </h1>')(Title changed, single quotes)
2. Arch Choice Dropdown (self.arch_choice)
- Base: Comment indicates
DEMUCS_ARCH_TYPEwas considered butchoices=[VR_ARCH_TYPE, MDX_ARCH_TYPE]is active. - Patched:
choices=[VR_ARCH_TYPE, MDX_ARCH_TYPE]. (Functionally same as base's active choices).
3. Input Filename Textbox (self.input_filename)
- Base:
label="Input filename" - Patched:
label="Input filename (e.g., song.wav)"(More descriptive)
4. Input Audio Component (self.audio_in)
- Base:
gr.Audio(label="Input audio", interactive=True) - Patched:
gr.Audio(label="Input audio", type="numpy", interactive=True)(Specifiestype="numpy")
5. Output Message Textbox (self.out_message)
- Base:
show_progress=Falseexplicitly set. - Patched:
show_progressattribute removed (Gradio's default behavior applies).
6. "Settings" Tab
- "Settings Guide" Tab Name:
- Base:
"Settings Guide" - Patched:
"Settings Guide (Placeholder)"
- Base:
- "Additional Settings" Tab Name & Content:
- Base: Tab name
"Additional Settigns"(typo).wav_typelabel:"Wav Type".mp3_ratelabel:"MP3 Bitrate". - Patched: Tab name
"Additional Settings"(corrected).wav_typelabel:"Wav Type Output".mp3_ratelabel:"MP3 Bitrate Output".
- Base: Tab name
- "Download models" Tab:
md_urlHelper Function:- Base:
return f"[{url}]({url})" - Patched:
return f"[{text}]({url})"(allows different display text for the Markdown link).
- Base:
- Row Variants:
- Base: Uses
gr.Row(variant="panel")for MDX and Demucs model download sections. - Patched:
variant="panel"attribute removed from these rows.
- Base: Uses
- Dropdown Change Lambdas for URL Display:
- Base: e.g.,
lambda model: md_url(vr_models[model]). This would fail ifmodelis not invr_modelsor ifmodelisNone. - Patched: e.g.,
lambda model: md_url(vr_models_for_dl.get(model, "URL not found")) if model else "". More robust: uses.get()for safe dictionary access, provides a default "URL not found", and handles the case wheremodelisNone(e.g., dropdown cleared) by returning an empty string. Similar robustness added for MDX and Demucs.
- Base: e.g.,
- Demucs URL Display:
- Patched: Safely accesses items from
demucs_models_for_dl.get(model, {}).items()to prevent errors if a model has no downloadable files listed.
- Patched: Safely accesses items from
7. Exclusive Checkbox Event Handling (in define_layout)
- Base:
self.set_checkboxes_exclusive( [self.primary_stem_only, self.secondary_stem_only], [lambda value: root.is_primary_stem_only_var.set(value), lambda value: root.is_secondary_stem_only_var.set(value)]) - Patched: (As detailed in Core Functionality section 7)
This is a fundamental change to a more standard and reliable Gradio pattern for exclusive checkboxes.def make_exclusive_primary(is_checked_primary): # ... logic ... def make_exclusive_secondary(is_checked_secondary): # ... logic ... self.primary_stem_only.change(make_exclusive_primary, inputs=self.primary_stem_only, outputs=[self.primary_stem_only, self.secondary_stem_only]) self.secondary_stem_only.change(make_exclusive_secondary, inputs=self.secondary_stem_only, outputs=[self.primary_stem_only, self.secondary_stem_only])
III. Main Script Execution Block (Outside Class)
1. Variable Names
- Base:
uvr,webui. - Patched:
uvr_interface_instance,webui_instance.
2. Model Download Logic
- Complete Overhaul:
- Base:
- Prints
webui.models_url. - Imports
osandwgetlocally within this block. - Iterates using hardcoded category names (
'VR Arc','MDX-Net') and hardcoded paths ('models/VR_Models','models/MDX_Net_Models'). - Does not create these model directories.
- Constructs and executes
aria2ccommand line calls usingos.system()for downloads. - Explicitly ignores other categories (like Demucs) for this download method.
- Prints
- Patched:
- Prints "INFO: Checking and downloading models if necessary...".
- Uses
VR_ARCH_TYPE,MDX_ARCH_TYPE,DEMUCS_ARCH_TYPEconstants and corresponding*_MODELS_DIRconstants. - Creates
target_model_dirif it doesn't exist usingos.makedirs(..., exist_ok=True). - Skips
DEMUCS_ARCH_TYPEin this specific loop (notes it might be handled elsewhere or differently). - Determines expected local filename and path with correct suffix.
- Uses Python's
wget.download(model_full_url, out=target_model_dir)for downloading. - Compares downloaded filename with expected filename and uses
shutil.move()to rename if necessary, ensuring the file is saved with the name expected byget_local_models. - Includes more detailed INFO/ERROR print statements during download.
- Base:
3. WebUI Re-initialization after Downloads
- Base:
webui = UVRWebUI(uvr, online_data_path='models/download_checks.json')(Second instantiation). - Patched:
print("INFO: Re-initializing WebUI to pick up downloaded models for dropdowns...")webui_instance = UVRWebUI(uvr_interface_instance, online_data_path='models/download_checks.json')(Second instantiation ofwebui_instance).- Note on Patched Script's Structure: The patched file has an additional (likely ineffective) attempt to update
webui_instance.model_choice.choicesbefore this final re-initialization, operating on the first instance ofwebui_instance. The crucial part for UI display is this second, final instantiation.
4. Code Style (Throughout the Patched File)
- Consistent use of single quotes (
'...') for string literals. - More explicit parentheses for tuples in return statements.
IV. Summary of Changes by Germanized
The "LocalPatchByGermanized" version introduces substantial improvements over the provided base webUI.py:
- Greatly Enhanced Robustness: Improved error handling in model loading, processing, file operations, and UI updates. UI is less likely to break from unexpected conditions.
- Modernized Model Downloading: Replaced
aria2cCLI calls with a Python-nativewgetandshutilimplementation, including better directory/filename management and error feedback. - Improved User Experience (UI & Feedback):
- More descriptive labels and messages.
- Better handling of Demucs architecture selection in the UI (hiding irrelevant settings).
- Clearer feedback during model downloads and processing.
- Corrected typos in UI text.
- Refined UI Component Behavior: More standard and reliable implementation for exclusive checkboxes. Safer handling of dropdown changes in the "Download models" tab.
- Code Maintainability: More consistent use of constants, better directory management practices.
- Branding: Updated UI title to reflect the "Local Patch By Germanized".
Overall, the patched script is a significant step up in terms of stability, usability, and code quality.
Germanized
changed pull request title from
This (PATCH) replaced your kind of not so the best download logic with better logic and automatic downloading of models thats faster and more visual progress
to UVRWUI Local (PATCH)