mirror of
https://github.com/Anjok07/ultimatevocalremovergui.git
synced 2024-11-24 15:30:11 +01:00
1703 lines
90 KiB
Python
1703 lines
90 KiB
Python
# GUI modules
|
|
import os
|
|
import pyperclip
|
|
from gc import freeze
|
|
import tkinter as tk
|
|
from tkinter import *
|
|
from tkinter.tix import *
|
|
import webbrowser
|
|
from tracemalloc import stop
|
|
import lib_v5.sv_ttk
|
|
import tkinter.ttk as ttk
|
|
import tkinter.messagebox
|
|
import tkinter.filedialog
|
|
import tkinter.font
|
|
from tkinterdnd2 import TkinterDnD, DND_FILES # Enable Drag & Drop
|
|
import pyglet,tkinter
|
|
from datetime import datetime
|
|
# Images
|
|
from PIL import Image
|
|
from PIL import ImageTk
|
|
import pickle # Save Data
|
|
# Other Modules
|
|
|
|
# Pathfinding
|
|
import pathlib
|
|
import sys
|
|
import subprocess
|
|
from collections import defaultdict
|
|
# Used for live text displaying
|
|
import queue
|
|
import threading # Run the algorithm inside a thread
|
|
from subprocess import call
|
|
from pathlib import Path
|
|
import ctypes as ct
|
|
import subprocess # Run python file
|
|
import inference_MDX
|
|
import inference_v5
|
|
import inference_v5_ensemble
|
|
|
|
try:
|
|
with open(os.path.join(os.getcwd(), 'tmp', 'splash.txt'), 'w') as f:
|
|
f.write('1')
|
|
except:
|
|
pass
|
|
|
|
# Change the current working directory to the directory
|
|
# this file sits in
|
|
if getattr(sys, 'frozen', False):
|
|
# If the application is run as a bundle, the PyInstaller bootloader
|
|
# extends the sys module by a flag frozen=True and sets the app
|
|
# path into variable _MEIPASS'.
|
|
base_path = sys._MEIPASS
|
|
else:
|
|
base_path = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
os.chdir(base_path) # Change the current working directory to the base path
|
|
|
|
#Images
|
|
instrumentalModels_dir = os.path.join(base_path, 'models')
|
|
banner_path = os.path.join(base_path, 'img', 'UVR-banner.png')
|
|
efile_path = os.path.join(base_path, 'img', 'file.png')
|
|
stop_path = os.path.join(base_path, 'img', 'stop.png')
|
|
help_path = os.path.join(base_path, 'img', 'help.png')
|
|
gen_opt_path = os.path.join(base_path, 'img', 'gen_opt.png')
|
|
mdx_opt_path = os.path.join(base_path, 'img', 'mdx_opt.png')
|
|
vr_opt_path = os.path.join(base_path, 'img', 'vr_opt.png')
|
|
ense_opt_path = os.path.join(base_path, 'img', 'ense_opt.png')
|
|
user_ens_opt_path = os.path.join(base_path, 'img', 'user_ens_opt.png')
|
|
more_info_path = os.path.join(base_path, 'img', 'more_info.png')
|
|
credits_path = os.path.join(base_path, 'img', 'credits.png')
|
|
|
|
DEFAULT_DATA = {
|
|
'exportPath': '',
|
|
'inputPaths': [],
|
|
'saveFormat': 'Wav',
|
|
'gpu': False,
|
|
'postprocess': False,
|
|
'tta': False,
|
|
'save': True,
|
|
'output_image': False,
|
|
'window_size': '512',
|
|
'agg': 10,
|
|
'modelFolder': False,
|
|
'modelInstrumentalLabel': '',
|
|
'aiModel': 'MDX-Net',
|
|
'algo': 'Instrumentals (Min Spec)',
|
|
'ensChoose': 'MDX-Net/VR Ensemble',
|
|
'useModel': 'instrumental',
|
|
'lastDir': None,
|
|
'break': False,
|
|
#MDX-Net
|
|
'demucsmodel': True,
|
|
'non_red': False,
|
|
'noise_reduc': True,
|
|
'voc_only': False,
|
|
'inst_only': False,
|
|
'chunks': 'Auto',
|
|
'noisereduc_s': '3',
|
|
'mixing': 'default',
|
|
'mdxnetModel': 'UVR-MDX-NET 1',
|
|
}
|
|
|
|
def open_image(path: str, size: tuple = None, keep_aspect: bool = True, rotate: int = 0) -> ImageTk.PhotoImage:
|
|
"""
|
|
Open the image on the path and apply given settings\n
|
|
Paramaters:
|
|
path(str):
|
|
Absolute path of the image
|
|
size(tuple):
|
|
first value - width
|
|
second value - height
|
|
keep_aspect(bool):
|
|
keep aspect ratio of image and resize
|
|
to maximum possible width and height
|
|
(maxima are given by size)
|
|
rotate(int):
|
|
clockwise rotation of image
|
|
Returns(ImageTk.PhotoImage):
|
|
Image of path
|
|
"""
|
|
img = Image.open(path).convert(mode='RGBA')
|
|
ratio = img.height/img.width
|
|
img = img.rotate(angle=-rotate)
|
|
if size is not None:
|
|
size = (int(size[0]), int(size[1]))
|
|
if keep_aspect:
|
|
img = img.resize((size[0], int(size[0] * ratio)), Image.ANTIALIAS)
|
|
else:
|
|
img = img.resize(size, Image.ANTIALIAS)
|
|
return ImageTk.PhotoImage(img)
|
|
|
|
def save_data(data):
|
|
"""
|
|
Saves given data as a .pkl (pickle) file
|
|
|
|
Paramters:
|
|
data(dict):
|
|
Dictionary containing all the necessary data to save
|
|
"""
|
|
# Open data file, create it if it does not exist
|
|
with open('data.pkl', 'wb') as data_file:
|
|
pickle.dump(data, data_file)
|
|
|
|
def load_data() -> dict:
|
|
"""
|
|
Loads saved pkl file and returns the stored data
|
|
|
|
Returns(dict):
|
|
Dictionary containing all the saved data
|
|
"""
|
|
try:
|
|
with open('data.pkl', 'rb') as data_file: # Open data file
|
|
data = pickle.load(data_file)
|
|
|
|
return data
|
|
except (ValueError, FileNotFoundError):
|
|
# Data File is corrupted or not found so recreate it
|
|
save_data(data=DEFAULT_DATA)
|
|
|
|
return load_data()
|
|
|
|
def drop(event, accept_mode: str = 'files'):
|
|
"""
|
|
Drag & Drop verification process
|
|
"""
|
|
path = event.data
|
|
|
|
if accept_mode == 'folder':
|
|
path = path.replace('{', '').replace('}', '')
|
|
if not os.path.isdir(path):
|
|
tk.messagebox.showerror(title='Invalid Folder',
|
|
message='Your given export path is not a valid folder!')
|
|
return
|
|
# Set Variables
|
|
root.exportPath_var.set(path)
|
|
elif accept_mode == 'files':
|
|
# Clean path text and set path to the list of paths
|
|
path = path.replace('{', '')
|
|
path = path.split('} ')
|
|
path[-1] = path[-1].replace('}', '')
|
|
# Set Variables
|
|
root.inputPaths = path
|
|
root.update_inputPaths()
|
|
else:
|
|
# Invalid accept mode
|
|
return
|
|
|
|
class ThreadSafeConsole(tk.Text):
|
|
"""
|
|
Text Widget which is thread safe for tkinter
|
|
"""
|
|
def __init__(self, master, **options):
|
|
tk.Text.__init__(self, master, **options)
|
|
self.queue = queue.Queue()
|
|
self.update_me()
|
|
|
|
def write(self, line):
|
|
self.queue.put(line)
|
|
|
|
def clear(self):
|
|
self.queue.put(None)
|
|
|
|
def update_me(self):
|
|
self.configure(state=tk.NORMAL)
|
|
try:
|
|
while 1:
|
|
line = self.queue.get_nowait()
|
|
if line is None:
|
|
self.delete(1.0, tk.END)
|
|
else:
|
|
self.insert(tk.END, str(line))
|
|
self.see(tk.END)
|
|
self.update_idletasks()
|
|
except queue.Empty:
|
|
pass
|
|
self.configure(state=tk.DISABLED)
|
|
self.after(100, self.update_me)
|
|
|
|
class MainWindow(TkinterDnD.Tk):
|
|
# --Constants--
|
|
# Layout
|
|
IMAGE_HEIGHT = 140
|
|
FILEPATHS_HEIGHT = 85
|
|
OPTIONS_HEIGHT = 275
|
|
CONVERSIONBUTTON_HEIGHT = 35
|
|
COMMAND_HEIGHT = 200
|
|
PROGRESS_HEIGHT = 30
|
|
PADDING = 10
|
|
|
|
COL1_ROWS = 11
|
|
COL2_ROWS = 11
|
|
|
|
def __init__(self):
|
|
# Run the __init__ method on the tk.Tk class
|
|
super().__init__()
|
|
|
|
# Calculate window height
|
|
height = self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT
|
|
height += self.CONVERSIONBUTTON_HEIGHT + self.COMMAND_HEIGHT + self.PROGRESS_HEIGHT
|
|
height += self.PADDING * 5 # Padding
|
|
|
|
# --Window Settings--
|
|
self.title('Ultimate Vocal Remover')
|
|
# Set Geometry and Center Window
|
|
self.geometry('{width}x{height}+{xpad}+{ypad}'.format(
|
|
width=620,
|
|
height=height,
|
|
xpad=int(self.winfo_screenwidth()/2 - 635/2),
|
|
ypad=int(self.winfo_screenheight()/2 - height/2 - 30)))
|
|
self.configure(bg='#0e0e0f') # Set background color to #0c0c0d
|
|
self.protocol("WM_DELETE_WINDOW", self.save_values)
|
|
self.resizable(False, False)
|
|
self.update()
|
|
|
|
# --Variables--
|
|
self.logo_img = open_image(path=banner_path,
|
|
size=(self.winfo_width(), 9999))
|
|
self.efile_img = open_image(path=efile_path,
|
|
size=(20, 20))
|
|
self.stop_img = open_image(path=stop_path,
|
|
size=(20, 20))
|
|
self.help_img = open_image(path=help_path,
|
|
size=(20, 20))
|
|
self.gen_opt_img = open_image(path=gen_opt_path,
|
|
size=(1016, 826))
|
|
self.mdx_opt_img = open_image(path=mdx_opt_path,
|
|
size=(1016, 826))
|
|
self.vr_opt_img = open_image(path=vr_opt_path,
|
|
size=(1016, 826))
|
|
self.ense_opt_img = open_image(path=ense_opt_path,
|
|
size=(1016, 826))
|
|
self.user_ens_opt_img = open_image(path=user_ens_opt_path,
|
|
size=(1016, 826))
|
|
self.more_info_img = open_image(path=more_info_path,
|
|
size=(1016, 826))
|
|
self.credits_img = open_image(path=credits_path,
|
|
size=(100, 100))
|
|
|
|
self.instrumentalLabel_to_path = defaultdict(lambda: '')
|
|
self.lastInstrumentalModels = []
|
|
|
|
# -Tkinter Value Holders-
|
|
data = load_data()
|
|
# Paths
|
|
self.inputPaths = data['inputPaths']
|
|
self.inputPathop_var = tk.StringVar(value=data['inputPaths'])
|
|
self.exportPath_var = tk.StringVar(value=data['exportPath'])
|
|
self.saveFormat_var = tk.StringVar(value=data['saveFormat'])
|
|
|
|
# Processing Options
|
|
self.gpuConversion_var = tk.BooleanVar(value=data['gpu'])
|
|
self.postprocessing_var = tk.BooleanVar(value=data['postprocess'])
|
|
self.tta_var = tk.BooleanVar(value=data['tta'])
|
|
self.save_var = tk.BooleanVar(value=data['save'])
|
|
self.outputImage_var = tk.BooleanVar(value=data['output_image'])
|
|
# MDX-NET Specific Processing Options
|
|
self.demucsmodel_var = tk.BooleanVar(value=data['demucsmodel'])
|
|
self.non_red_var = tk.BooleanVar(value=data['non_red'])
|
|
self.noisereduc_var = tk.BooleanVar(value=data['noise_reduc'])
|
|
self.chunks_var = tk.StringVar(value=data['chunks'])
|
|
self.noisereduc_s_var = tk.StringVar(value=data['noisereduc_s'])
|
|
self.mixing_var = tk.StringVar(value=data['mixing']) #dropdown
|
|
# Models
|
|
self.instrumentalModel_var = tk.StringVar(value=data['modelInstrumentalLabel'])
|
|
# Model Test Mode
|
|
self.modelFolder_var = tk.BooleanVar(value=data['modelFolder'])
|
|
# Constants
|
|
self.winSize_var = tk.StringVar(value=data['window_size'])
|
|
self.agg_var = tk.StringVar(value=data['agg'])
|
|
# Instrumental or Vocal Only
|
|
self.voc_only_var = tk.BooleanVar(value=data['voc_only'])
|
|
self.inst_only_var = tk.BooleanVar(value=data['inst_only'])
|
|
# Choose Conversion Method
|
|
self.aiModel_var = tk.StringVar(value=data['aiModel'])
|
|
self.last_aiModel = self.aiModel_var.get()
|
|
# Choose Conversion Method
|
|
self.algo_var = tk.StringVar(value=data['algo'])
|
|
self.last_algo = self.aiModel_var.get()
|
|
# Choose Ensemble
|
|
self.ensChoose_var = tk.StringVar(value=data['ensChoose'])
|
|
self.last_ensChoose = self.ensChoose_var.get()
|
|
# Choose MDX-NET Model
|
|
self.mdxnetModel_var = tk.StringVar(value=data['mdxnetModel'])
|
|
self.last_mdxnetModel = self.mdxnetModel_var.get()
|
|
# Other
|
|
self.inputPathsEntry_var = tk.StringVar(value='')
|
|
self.lastDir = data['lastDir'] # nopep8
|
|
self.progress_var = tk.IntVar(value=0)
|
|
# Font
|
|
pyglet.font.add_file('lib_v5/fonts/centurygothic/GOTHIC.TTF')
|
|
pyglet.font.add_file('lib_v5/fonts/unispace/unispace.ttf')
|
|
#Font(file="lib_v5/fonts/centurygothic/GOTHIC.TTF", family="Century Gothic")
|
|
#Font(file="lib_v5/fonts/unispace/unispace.ttf", family="Unispace")
|
|
self.font = tk.font.Font(family='Century Gothic', size=10)
|
|
self.fontRadio = tk.font.Font(family='Century Gothic', size=8)
|
|
# --Widgets--
|
|
self.create_widgets()
|
|
self.configure_widgets()
|
|
self.bind_widgets()
|
|
self.place_widgets()
|
|
|
|
self.update_available_models()
|
|
self.update_states()
|
|
self.update_loop()
|
|
|
|
|
|
|
|
|
|
# -Widget Methods-
|
|
def create_widgets(self):
|
|
"""Create window widgets"""
|
|
self.title_Label = tk.Label(master=self, bg='#0e0e0f',
|
|
image=self.logo_img, compound=tk.TOP)
|
|
self.filePaths_Frame = ttk.Frame(master=self)
|
|
self.fill_filePaths_Frame()
|
|
|
|
self.options_Frame = ttk.Frame(master=self)
|
|
self.fill_options_Frame()
|
|
|
|
self.conversion_Button = ttk.Button(master=self,
|
|
text='Start Processing',
|
|
command=self.start_conversion)
|
|
self.stop_Button = ttk.Button(master=self,
|
|
image=self.stop_img,
|
|
command=self.restart)
|
|
self.help_Button = ttk.Button(master=self,
|
|
image=self.help_img,
|
|
command=self.help)
|
|
|
|
#ttk.Button(win, text= "Open", command= open_popup).pack()
|
|
|
|
self.efile_e_Button = ttk.Button(master=self,
|
|
image=self.efile_img,
|
|
command=self.open_exportPath_filedialog)
|
|
|
|
self.efile_i_Button = ttk.Button(master=self,
|
|
image=self.efile_img,
|
|
command=self.open_inputPath_filedialog)
|
|
|
|
self.progressbar = ttk.Progressbar(master=self, variable=self.progress_var)
|
|
|
|
self.command_Text = ThreadSafeConsole(master=self,
|
|
background='#0e0e0f',fg='#898b8e', font=('Century Gothic', 11),
|
|
borderwidth=0,)
|
|
|
|
self.command_Text.write(f'Ultimate Vocal Remover [{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}]\n')
|
|
|
|
|
|
def configure_widgets(self):
|
|
"""Change widget styling and appearance"""
|
|
|
|
#ttk.Style().configure('TCheckbutton', background='#0e0e0f',
|
|
# font=self.font, foreground='#d4d4d4')
|
|
#ttk.Style().configure('TRadiobutton', background='#0e0e0f',
|
|
# font=("Century Gothic", "8", "bold"), foreground='#d4d4d4')
|
|
#ttk.Style().configure('T', font=self.font, foreground='#d4d4d4')
|
|
|
|
#s = ttk.Style()
|
|
#s.configure('TButton', background='blue', foreground='black', font=('Century Gothic', '9', 'bold'), relief="groove")
|
|
|
|
|
|
def bind_widgets(self):
|
|
"""Bind widgets to the drag & drop mechanic"""
|
|
self.filePaths_musicFile_Button.drop_target_register(DND_FILES)
|
|
self.filePaths_musicFile_Entry.drop_target_register(DND_FILES)
|
|
self.filePaths_saveTo_Button.drop_target_register(DND_FILES)
|
|
self.filePaths_saveTo_Entry.drop_target_register(DND_FILES)
|
|
self.filePaths_musicFile_Button.dnd_bind('<<Drop>>',
|
|
lambda e: drop(e, accept_mode='files'))
|
|
self.filePaths_musicFile_Entry.dnd_bind('<<Drop>>',
|
|
lambda e: drop(e, accept_mode='files'))
|
|
self.filePaths_saveTo_Button.dnd_bind('<<Drop>>',
|
|
lambda e: drop(e, accept_mode='folder'))
|
|
self.filePaths_saveTo_Entry.dnd_bind('<<Drop>>',
|
|
lambda e: drop(e, accept_mode='folder'))
|
|
|
|
def place_widgets(self):
|
|
"""Place main widgets"""
|
|
self.title_Label.place(x=-2, y=-2)
|
|
self.filePaths_Frame.place(x=10, y=155, width=-20, height=self.FILEPATHS_HEIGHT,
|
|
relx=0, rely=0, relwidth=1, relheight=0)
|
|
self.options_Frame.place(x=10, y=250, width=-50, height=self.OPTIONS_HEIGHT,
|
|
relx=0, rely=0, relwidth=1, relheight=0)
|
|
self.conversion_Button.place(x=50, y=self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT + self.PADDING*2, width=-60 - 40, height=self.CONVERSIONBUTTON_HEIGHT,
|
|
relx=0, rely=0, relwidth=1, relheight=0)
|
|
self.efile_e_Button.place(x=-45, y=200, width=35, height=30,
|
|
relx=1, rely=0, relwidth=0, relheight=0)
|
|
self.efile_i_Button.place(x=-45, y=160, width=35, height=30,
|
|
relx=1, rely=0, relwidth=0, relheight=0)
|
|
|
|
self.stop_Button.place(x=-10 - 35, y=self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT + self.PADDING*2, width=35, height=self.CONVERSIONBUTTON_HEIGHT,
|
|
relx=1, rely=0, relwidth=0, relheight=0)
|
|
self.help_Button.place(x=-10 - 600, y=self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT + self.PADDING*2, width=35, height=self.CONVERSIONBUTTON_HEIGHT,
|
|
relx=1, rely=0, relwidth=0, relheight=0)
|
|
self.command_Text.place(x=25, y=self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT + self.CONVERSIONBUTTON_HEIGHT + self.PADDING*3, width=-30, height=self.COMMAND_HEIGHT,
|
|
relx=0, rely=0, relwidth=1, relheight=0)
|
|
self.progressbar.place(x=25, y=self.IMAGE_HEIGHT + self.FILEPATHS_HEIGHT + self.OPTIONS_HEIGHT + self.CONVERSIONBUTTON_HEIGHT + self.COMMAND_HEIGHT + self.PADDING*4, width=-50, height=self.PROGRESS_HEIGHT,
|
|
relx=0, rely=0, relwidth=1, relheight=0)
|
|
|
|
def fill_filePaths_Frame(self):
|
|
"""Fill Frame with neccessary widgets"""
|
|
# -Create Widgets-
|
|
# Save To Option
|
|
# Select Music Files Option
|
|
|
|
# Save To Option
|
|
self.filePaths_saveTo_Button = ttk.Button(master=self.filePaths_Frame,
|
|
text='Select output',
|
|
command=self.open_export_filedialog)
|
|
self.filePaths_saveTo_Entry = ttk.Entry(master=self.filePaths_Frame,
|
|
|
|
textvariable=self.exportPath_var,
|
|
state=tk.DISABLED
|
|
)
|
|
# Select Music Files Option
|
|
self.filePaths_musicFile_Button = ttk.Button(master=self.filePaths_Frame,
|
|
text='Select input',
|
|
command=self.open_file_filedialog)
|
|
self.filePaths_musicFile_Entry = ttk.Entry(master=self.filePaths_Frame,
|
|
textvariable=self.inputPathsEntry_var,
|
|
state=tk.DISABLED
|
|
)
|
|
|
|
|
|
# -Place Widgets-
|
|
|
|
# Select Music Files Option
|
|
self.filePaths_musicFile_Button.place(x=0, y=5, width=0, height=-10,
|
|
relx=0, rely=0, relwidth=0.3, relheight=0.5)
|
|
self.filePaths_musicFile_Entry.place(x=10, y=2.5, width=-50, height=-5,
|
|
relx=0.3, rely=0, relwidth=0.7, relheight=0.5)
|
|
|
|
# Save To Option
|
|
self.filePaths_saveTo_Button.place(x=0, y=5, width=0, height=-10,
|
|
relx=0, rely=0.5, relwidth=0.3, relheight=0.5)
|
|
self.filePaths_saveTo_Entry.place(x=10, y=2.5, width=-50, height=-5,
|
|
relx=0.3, rely=0.5, relwidth=0.7, relheight=0.5)
|
|
|
|
|
|
def fill_options_Frame(self):
|
|
"""Fill Frame with neccessary widgets"""
|
|
# -Create Widgets-
|
|
|
|
|
|
# Save as wav
|
|
self.options_wav_Radiobutton = ttk.Radiobutton(master=self.options_Frame,
|
|
text='WAV',
|
|
variable=self.saveFormat_var,
|
|
value='Wav'
|
|
)
|
|
|
|
# Save as flac
|
|
self.options_flac_Radiobutton = ttk.Radiobutton(master=self.options_Frame,
|
|
text='FLAC',
|
|
variable=self.saveFormat_var,
|
|
value='Flac'
|
|
)
|
|
|
|
# Save as mp3
|
|
self.options_mpThree_Radiobutton = ttk.Radiobutton(master=self.options_Frame,
|
|
text='MP3',
|
|
variable=self.saveFormat_var,
|
|
value='Mp3',
|
|
)
|
|
|
|
# -Column 1-
|
|
|
|
# Choose Conversion Method
|
|
self.options_aiModel_Label = tk.Label(master=self.options_Frame,
|
|
text='Choose Process Method', anchor=tk.CENTER,
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_aiModel_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.aiModel_var,
|
|
None, 'VR Architecture', 'MDX-Net', 'Ensemble Mode')
|
|
# Choose Instrumental Model
|
|
self.options_instrumentalModel_Label = tk.Label(master=self.options_Frame,
|
|
text='Choose Main Model',
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_instrumentalModel_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.instrumentalModel_var)
|
|
# Choose MDX-Net Model
|
|
self.options_mdxnetModel_Label = tk.Label(master=self.options_Frame,
|
|
text='Choose MDX-Net Model', anchor=tk.CENTER,
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
|
|
self.options_mdxnetModel_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.mdxnetModel_var,
|
|
None, 'UVR-MDX-NET 1', 'UVR-MDX-NET 2', 'UVR-MDX-NET 3', 'UVR-MDX-NET Karaoke')
|
|
# Ensemble Mode
|
|
self.options_ensChoose_Label = tk.Label(master=self.options_Frame,
|
|
text='Choose Ensemble', anchor=tk.CENTER,
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_ensChoose_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.ensChoose_var,
|
|
None, 'MDX-Net/VR Ensemble', 'HP Models', 'Vocal Models', 'HP2 Models', 'All HP/HP2 Models', 'User Ensemble')
|
|
|
|
# Choose Agorithim
|
|
self.options_algo_Label = tk.Label(master=self.options_Frame,
|
|
text='Choose Algorithm', anchor=tk.CENTER,
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_algo_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.algo_var,
|
|
None, 'Vocals (Max Spec)', 'Instrumentals (Min Spec)')#, 'Invert (Normal)', 'Invert (Spectral)')
|
|
|
|
|
|
# -Column 2-
|
|
|
|
# WINDOW SIZE
|
|
self.options_winSize_Label = tk.Label(master=self.options_Frame,
|
|
text='Window Size', anchor=tk.CENTER,
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_winSize_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.winSize_var,
|
|
None, '320', '512','1024')
|
|
# MDX-chunks
|
|
self.options_chunks_Label = tk.Label(master=self.options_Frame,
|
|
text='Chunks',
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_chunks_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.chunks_var,
|
|
None, 'Auto', '1', '5', '10', '15', '20',
|
|
'25', '30', '35', '40', '45', '50',
|
|
'55', '60', '65', '70', '75', '80',
|
|
'85', '90', '95', 'Full')
|
|
|
|
#Checkboxes
|
|
# GPU Selection
|
|
self.options_gpu_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='GPU Conversion',
|
|
variable=self.gpuConversion_var,
|
|
)
|
|
|
|
# Vocal Only
|
|
self.options_voc_only_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Save Vocals Only',
|
|
variable=self.voc_only_var,
|
|
)
|
|
# Instrumental Only
|
|
self.options_inst_only_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Save Instrumental Only',
|
|
variable=self.inst_only_var,
|
|
)
|
|
# TTA
|
|
self.options_tta_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='TTA',
|
|
variable=self.tta_var,
|
|
)
|
|
|
|
# MDX-Auto-Chunk
|
|
self.options_non_red_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Save Noisey Vocal',
|
|
variable=self.non_red_var,
|
|
)
|
|
|
|
# Postprocessing
|
|
self.options_post_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Post-Process',
|
|
variable=self.postprocessing_var,
|
|
)
|
|
|
|
# -Column 3-
|
|
|
|
# AGG
|
|
self.options_agg_Label = tk.Label(master=self.options_Frame,
|
|
text='Aggression Setting',
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_agg_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.agg_var,
|
|
None, '1', '2', '3', '4', '5',
|
|
'6', '7', '8', '9', '10', '11',
|
|
'12', '13', '14', '15', '16', '17',
|
|
'18', '19', '20')
|
|
|
|
# MDX-noisereduc_s
|
|
self.options_noisereduc_s_Label = tk.Label(master=self.options_Frame,
|
|
text='Noise Reduction',
|
|
background='#0e0e0f', font=self.font, foreground='#13a4c9')
|
|
self.options_noisereduc_s_Optionmenu = ttk.OptionMenu(self.options_Frame,
|
|
self.noisereduc_s_var,
|
|
None, 'None', '0', '1', '2', '3', '4', '5',
|
|
'6', '7', '8', '9', '10', '11',
|
|
'12', '13', '14', '15', '16', '17',
|
|
'18', '19', '20')
|
|
|
|
|
|
# Save Image
|
|
self.options_image_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Output Image',
|
|
variable=self.outputImage_var,
|
|
)
|
|
|
|
# MDX-Enable Demucs Model
|
|
self.options_demucsmodel_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Demucs Model',
|
|
variable=self.demucsmodel_var,
|
|
)
|
|
|
|
# MDX-Noise Reduction
|
|
self.options_noisereduc_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Noise Reduction',
|
|
variable=self.noisereduc_var,
|
|
)
|
|
|
|
# Ensemble Save Ensemble Outputs
|
|
self.options_save_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Save All Outputs',
|
|
variable=self.save_var,
|
|
)
|
|
|
|
# Model Test Mode
|
|
self.options_modelFolder_Checkbutton = ttk.Checkbutton(master=self.options_Frame,
|
|
text='Model Test Mode',
|
|
variable=self.modelFolder_var,
|
|
)
|
|
|
|
# -Place Widgets-
|
|
|
|
# -Column 0-
|
|
|
|
# Save as
|
|
self.options_wav_Radiobutton.place(x=400, y=-5, width=0, height=6,
|
|
relx=0, rely=0/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_flac_Radiobutton.place(x=271, y=-5, width=0, height=6,
|
|
relx=1/3, rely=0/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_mpThree_Radiobutton.place(x=143, y=-5, width=0, height=6,
|
|
relx=2/3, rely=0/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# -Column 1-
|
|
|
|
# Choose Conversion Method
|
|
self.options_aiModel_Label.place(x=0, y=0, width=0, height=-10,
|
|
relx=0, rely=2/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_aiModel_Optionmenu.place(x=0, y=-2, width=0, height=7,
|
|
relx=0, rely=3/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# Choose Main Model
|
|
self.options_instrumentalModel_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_instrumentalModel_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# Choose MDX-Net Model
|
|
self.options_mdxnetModel_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_mdxnetModel_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# Choose Ensemble
|
|
self.options_ensChoose_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_ensChoose_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
|
|
# Choose Algorithm
|
|
self.options_algo_Label.place(x=20, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_algo_Optionmenu.place(x=12, y=-2, width=0, height=7,
|
|
relx=1/3, rely=3/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
|
|
# -Column 2-
|
|
|
|
# WINDOW
|
|
self.options_winSize_Label.place(x=13, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_winSize_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#---MDX-Net Specific---
|
|
# MDX-chunks
|
|
self.options_chunks_Label.place(x=12, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_chunks_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Checkboxes
|
|
|
|
#GPU Conversion
|
|
self.options_gpu_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Vocals Only
|
|
self.options_voc_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Instrumental Only
|
|
self.options_inst_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# TTA
|
|
self.options_tta_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-Keep Non_Reduced Vocal
|
|
self.options_non_red_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# -Column 3-
|
|
|
|
# AGG
|
|
self.options_agg_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_agg_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-noisereduc_s
|
|
self.options_noisereduc_s_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_noisereduc_s_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Checkboxes
|
|
#---MDX-Net Specific---
|
|
# MDX-demucs Model
|
|
self.options_demucsmodel_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
#---VR Architecture Specific---
|
|
#Post-Process
|
|
self.options_post_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Save Image
|
|
# self.options_image_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
# relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#---Ensemble Specific---
|
|
#Ensemble Save Outputs
|
|
self.options_save_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#---MDX-Net & VR Architecture Specific---
|
|
#Model Test Mode
|
|
self.options_modelFolder_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# Change States
|
|
self.aiModel_var.trace_add('write',
|
|
lambda *args: self.deselect_models())
|
|
self.ensChoose_var.trace_add('write',
|
|
lambda *args: self.update_states())
|
|
|
|
self.inst_only_var.trace_add('write',
|
|
lambda *args: self.update_states())
|
|
|
|
self.voc_only_var.trace_add('write',
|
|
lambda *args: self.update_states())
|
|
self.noisereduc_s_var.trace_add('write',
|
|
lambda *args: self.update_states())
|
|
self.non_red_var.trace_add('write',
|
|
lambda *args: self.update_states())
|
|
|
|
# Opening filedialogs
|
|
def open_file_filedialog(self):
|
|
"""Make user select music files"""
|
|
if self.lastDir is not None:
|
|
if not os.path.isdir(self.lastDir):
|
|
self.lastDir = None
|
|
|
|
paths = tk.filedialog.askopenfilenames(
|
|
parent=self,
|
|
title=f'Select Music Files',
|
|
initialfile='',
|
|
initialdir=self.lastDir,
|
|
)
|
|
if paths: # Path selected
|
|
self.inputPaths = paths
|
|
self.update_inputPaths()
|
|
self.lastDir = os.path.dirname(paths[0])
|
|
|
|
def open_export_filedialog(self):
|
|
"""Make user select a folder to export the converted files in"""
|
|
path = tk.filedialog.askdirectory(
|
|
parent=self,
|
|
title=f'Select Folder',)
|
|
if path: # Path selected
|
|
self.exportPath_var.set(path)
|
|
|
|
def open_exportPath_filedialog(self):
|
|
filename = self.exportPath_var.get()
|
|
|
|
if sys.platform == "win32":
|
|
os.startfile(filename)
|
|
else:
|
|
opener = "open" if sys.platform == "darwin" else "xdg-open"
|
|
subprocess.call([opener, filename])
|
|
|
|
def open_inputPath_filedialog(self):
|
|
"""Open Input Directory"""
|
|
|
|
filename = self.lastDir
|
|
|
|
if sys.platform == "win32":
|
|
os.startfile(filename)
|
|
|
|
def start_conversion(self):
|
|
"""
|
|
Start the conversion for all the given mp3 and wav files
|
|
"""
|
|
|
|
# -Get all variables-
|
|
export_path = self.exportPath_var.get()
|
|
input_paths = self.inputPaths
|
|
instrumentalModel_path = self.instrumentalLabel_to_path[self.instrumentalModel_var.get()] # nopep8
|
|
# mdxnetModel_path = self.mdxnetLabel_to_path[self.mdxnetModel_var.get()]
|
|
# Get constants
|
|
instrumental = self.instrumentalModel_var.get()
|
|
try:
|
|
if [bool(instrumental)].count(True) == 2: #CHECKTHIS
|
|
window_size = DEFAULT_DATA['window_size']
|
|
agg = DEFAULT_DATA['agg']
|
|
chunks = DEFAULT_DATA['chunks']
|
|
noisereduc_s = DEFAULT_DATA['noisereduc_s']
|
|
mixing = DEFAULT_DATA['mixing']
|
|
else:
|
|
window_size = int(self.winSize_var.get())
|
|
agg = int(self.agg_var.get())
|
|
chunks = str(self.chunks_var.get())
|
|
noisereduc_s = str(self.noisereduc_s_var.get())
|
|
mixing = str(self.mixing_var.get())
|
|
ensChoose = str(self.ensChoose_var.get())
|
|
mdxnetModel = str(self.mdxnetModel_var.get())
|
|
|
|
except SyntaxError: # Non integer was put in entry box
|
|
tk.messagebox.showwarning(master=self,
|
|
title='Invalid Music File',
|
|
message='You have selected an invalid music file!\nPlease make sure that your files still exist and ends with either ".mp3", ".mp4", ".m4a", ".flac", ".wav"')
|
|
return
|
|
|
|
# -Check for invalid inputs-
|
|
for path in input_paths:
|
|
if not os.path.isfile(path):
|
|
tk.messagebox.showwarning(master=self,
|
|
title='Invalid Music File',
|
|
message='You have selected an invalid music file! Please make sure that the file still exists!',
|
|
detail=f'File path: {path}')
|
|
return
|
|
if self.aiModel_var.get() == 'VR Architecture':
|
|
if not os.path.isfile(instrumentalModel_path):
|
|
tk.messagebox.showwarning(master=self,
|
|
title='Invalid Main Model File',
|
|
message='You have selected an invalid main model file!\nPlease make sure that your model file still exists!')
|
|
return
|
|
|
|
if not os.path.isdir(export_path):
|
|
tk.messagebox.showwarning(master=self,
|
|
title='Invalid Export Directory',
|
|
message='You have selected an invalid export directory!\nPlease make sure that your directory still exists!')
|
|
return
|
|
|
|
if self.aiModel_var.get() == 'VR Architecture':
|
|
inference = inference_v5
|
|
elif self.aiModel_var.get() == 'Ensemble Mode':
|
|
inference = inference_v5_ensemble
|
|
elif self.aiModel_var.get() == 'MDX-Net':
|
|
inference = inference_MDX
|
|
else:
|
|
raise TypeError('This error should not occur.')
|
|
|
|
# -Run the algorithm-
|
|
threading.Thread(target=inference.main,
|
|
kwargs={
|
|
# Paths
|
|
'input_paths': input_paths,
|
|
'export_path': export_path,
|
|
'saveFormat': self.saveFormat_var.get(),
|
|
# Processing Options
|
|
'gpu': 0 if self.gpuConversion_var.get() else -1,
|
|
'postprocess': self.postprocessing_var.get(),
|
|
'tta': self.tta_var.get(),
|
|
'save': self.save_var.get(),
|
|
'output_image': self.outputImage_var.get(),
|
|
'algo': self.algo_var.get(),
|
|
# Models
|
|
'instrumentalModel': instrumentalModel_path,
|
|
'vocalModel': '', # Always not needed
|
|
'useModel': 'instrumental', # Always instrumental
|
|
# Model Folder
|
|
'modelFolder': self.modelFolder_var.get(),
|
|
# Constants
|
|
'window_size': window_size,
|
|
'agg': agg,
|
|
'break': False,
|
|
'ensChoose': ensChoose,
|
|
'mdxnetModel': mdxnetModel,
|
|
# Other Variables (Tkinter)
|
|
'window': self,
|
|
'text_widget': self.command_Text,
|
|
'button_widget': self.conversion_Button,
|
|
'inst_menu': self.options_instrumentalModel_Optionmenu,
|
|
'progress_var': self.progress_var,
|
|
# MDX-Net Specific
|
|
'demucsmodel': self.demucsmodel_var.get(),
|
|
'non_red': self.non_red_var.get(),
|
|
'noise_reduc': self.noisereduc_var.get(),
|
|
'voc_only': self.voc_only_var.get(),
|
|
'inst_only': self.inst_only_var.get(),
|
|
'chunks': chunks,
|
|
'noisereduc_s': noisereduc_s,
|
|
'mixing': mixing,
|
|
},
|
|
daemon=True
|
|
).start()
|
|
|
|
# Models
|
|
def update_inputPaths(self):
|
|
"""Update the music file entry"""
|
|
if self.inputPaths:
|
|
# Non-empty Selection
|
|
text = '; '.join(self.inputPaths)
|
|
else:
|
|
# Empty Selection
|
|
text = ''
|
|
self.inputPathsEntry_var.set(text)
|
|
|
|
def update_loop(self):
|
|
"""Update the dropdown menu"""
|
|
self.update_available_models()
|
|
|
|
self.after(3000, self.update_loop)
|
|
|
|
def update_available_models(self):
|
|
"""
|
|
Loop through every model (.pth) in the models directory
|
|
and add to the select your model list
|
|
"""
|
|
temp_instrumentalModels_dir = os.path.join(instrumentalModels_dir, 'Main_Models') # nopep8
|
|
|
|
# Main models
|
|
new_InstrumentalModels = os.listdir(temp_instrumentalModels_dir)
|
|
if new_InstrumentalModels != self.lastInstrumentalModels:
|
|
self.instrumentalLabel_to_path.clear()
|
|
self.options_instrumentalModel_Optionmenu['menu'].delete(0, 'end')
|
|
for file_name in new_InstrumentalModels:
|
|
if file_name.endswith('.pth'):
|
|
# Add Radiobutton to the Options Menu
|
|
self.options_instrumentalModel_Optionmenu['menu'].add_radiobutton(label=file_name,
|
|
command=tk._setit(self.instrumentalModel_var, file_name))
|
|
# Link the files name to its absolute path
|
|
self.instrumentalLabel_to_path[file_name] = os.path.join(temp_instrumentalModels_dir, file_name) # nopep8
|
|
self.lastInstrumentalModels = new_InstrumentalModels
|
|
|
|
def update_states(self):
|
|
"""
|
|
Vary the states for all widgets based
|
|
on certain selections
|
|
"""
|
|
|
|
if self.aiModel_var.get() == 'MDX-Net':
|
|
# Place Widgets
|
|
|
|
# Choose MDX-Net Model
|
|
self.options_mdxnetModel_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_mdxnetModel_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# MDX-chunks
|
|
self.options_chunks_Label.place(x=12, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_chunks_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-noisereduc_s
|
|
self.options_noisereduc_s_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_noisereduc_s_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#GPU Conversion
|
|
self.options_gpu_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_gpu_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Vocals Only
|
|
self.options_voc_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_voc_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Instrumental Only
|
|
self.options_inst_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_inst_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-demucs Model
|
|
self.options_demucsmodel_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_demucsmodel_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# MDX-Keep Non_Reduced Vocal
|
|
self.options_non_red_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_non_red_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Model Test Mode
|
|
self.options_modelFolder_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_modelFolder_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
|
|
# Forget widgets
|
|
self.options_ensChoose_Label.place_forget()
|
|
self.options_ensChoose_Optionmenu.place_forget()
|
|
self.options_instrumentalModel_Label.place_forget()
|
|
self.options_instrumentalModel_Optionmenu.place_forget()
|
|
self.options_save_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_save_Checkbutton.place_forget()
|
|
self.options_post_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_post_Checkbutton.place_forget()
|
|
self.options_tta_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_tta_Checkbutton.place_forget()
|
|
# self.options_image_Checkbutton.configure(state=tk.DISABLED)
|
|
# self.options_image_Checkbutton.place_forget()
|
|
self.options_winSize_Label.place_forget()
|
|
self.options_winSize_Optionmenu.place_forget()
|
|
self.options_agg_Label.place_forget()
|
|
self.options_agg_Optionmenu.place_forget()
|
|
self.options_algo_Label.place_forget()
|
|
self.options_algo_Optionmenu.place_forget()
|
|
|
|
|
|
elif self.aiModel_var.get() == 'VR Architecture':
|
|
#Keep for Ensemble & VR Architecture Mode
|
|
# Choose Main Model
|
|
self.options_instrumentalModel_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_instrumentalModel_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# WINDOW
|
|
self.options_winSize_Label.place(x=13, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_winSize_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# AGG
|
|
self.options_agg_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_agg_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#GPU Conversion
|
|
self.options_gpu_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_gpu_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Vocals Only
|
|
self.options_voc_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_voc_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Instrumental Only
|
|
self.options_inst_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_inst_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# TTA
|
|
self.options_tta_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_tta_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Post-Process
|
|
self.options_post_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_post_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Save Image
|
|
# self.options_image_Checkbutton.configure(state=tk.NORMAL)
|
|
# self.options_image_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
# relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Model Test Mode
|
|
self.options_modelFolder_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_modelFolder_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Forget Widgets
|
|
self.options_ensChoose_Label.place_forget()
|
|
self.options_ensChoose_Optionmenu.place_forget()
|
|
self.options_chunks_Label.place_forget()
|
|
self.options_chunks_Optionmenu.place_forget()
|
|
self.options_noisereduc_s_Label.place_forget()
|
|
self.options_noisereduc_s_Optionmenu.place_forget()
|
|
self.options_mdxnetModel_Label.place_forget()
|
|
self.options_mdxnetModel_Optionmenu.place_forget()
|
|
self.options_algo_Label.place_forget()
|
|
self.options_algo_Optionmenu.place_forget()
|
|
self.options_save_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_save_Checkbutton.place_forget()
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_non_red_Checkbutton.place_forget()
|
|
self.options_noisereduc_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_noisereduc_Checkbutton.place_forget()
|
|
self.options_demucsmodel_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_demucsmodel_Checkbutton.place_forget()
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_non_red_Checkbutton.place_forget()
|
|
|
|
elif self.aiModel_var.get() == 'Ensemble Mode':
|
|
if self.ensChoose_var.get() == 'User Ensemble':
|
|
# Choose Algorithm
|
|
self.options_algo_Label.place(x=20, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_algo_Optionmenu.place(x=12, y=-2, width=0, height=7,
|
|
relx=1/3, rely=3/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# Choose Ensemble
|
|
self.options_ensChoose_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_ensChoose_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# Forget Widgets
|
|
self.options_save_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_save_Checkbutton.place_forget()
|
|
self.options_post_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_post_Checkbutton.place_forget()
|
|
self.options_tta_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_tta_Checkbutton.place_forget()
|
|
self.options_modelFolder_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_modelFolder_Checkbutton.place_forget()
|
|
# self.options_image_Checkbutton.configure(state=tk.DISABLED)
|
|
# self.options_image_Checkbutton.place_forget()
|
|
self.options_gpu_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_gpu_Checkbutton.place_forget()
|
|
self.options_voc_only_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_voc_only_Checkbutton.place_forget()
|
|
self.options_inst_only_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_inst_only_Checkbutton.place_forget()
|
|
self.options_demucsmodel_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_demucsmodel_Checkbutton.place_forget()
|
|
self.options_noisereduc_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_noisereduc_Checkbutton.place_forget()
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_non_red_Checkbutton.place_forget()
|
|
self.options_chunks_Label.place_forget()
|
|
self.options_chunks_Optionmenu.place_forget()
|
|
self.options_noisereduc_s_Label.place_forget()
|
|
self.options_noisereduc_s_Optionmenu.place_forget()
|
|
self.options_mdxnetModel_Label.place_forget()
|
|
self.options_mdxnetModel_Optionmenu.place_forget()
|
|
self.options_winSize_Label.place_forget()
|
|
self.options_winSize_Optionmenu.place_forget()
|
|
self.options_agg_Label.place_forget()
|
|
self.options_agg_Optionmenu.place_forget()
|
|
|
|
elif self.ensChoose_var.get() == 'MDX-Net/VR Ensemble':
|
|
# Choose Ensemble
|
|
self.options_ensChoose_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_ensChoose_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# MDX-chunks
|
|
self.options_chunks_Label.place(x=12, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_chunks_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-noisereduc_s
|
|
self.options_noisereduc_s_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_noisereduc_s_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# WINDOW
|
|
self.options_winSize_Label.place(x=13, y=-7, width=0, height=-10,
|
|
relx=1/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_winSize_Optionmenu.place(x=71, y=-5, width=-118, height=7,
|
|
relx=1/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# AGG
|
|
self.options_agg_Label.place(x=15, y=-7, width=0, height=-10,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_agg_Optionmenu.place(x=71, y=-5, width=-118, height=7,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#GPU Conversion
|
|
self.options_gpu_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_gpu_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=1/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Vocals Only
|
|
self.options_voc_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_voc_only_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=1/3, rely=8/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Instrumental Only
|
|
self.options_inst_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_inst_only_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=1/3, rely=9/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# MDX-demucs Model
|
|
self.options_demucsmodel_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_demucsmodel_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# TTA
|
|
self.options_tta_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_tta_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=2/3, rely=8/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Ensemble Save Outputs
|
|
self.options_save_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_save_Checkbutton.place(x=35, y=3, width=0, height=5,
|
|
relx=2/3, rely=9/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# Forget Widgets
|
|
self.options_post_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_post_Checkbutton.place_forget()
|
|
self.options_modelFolder_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_modelFolder_Checkbutton.place_forget()
|
|
# self.options_image_Checkbutton.configure(state=tk.DISABLED)
|
|
# self.options_image_Checkbutton.place_forget()
|
|
self.options_noisereduc_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_noisereduc_Checkbutton.place_forget()
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_non_red_Checkbutton.place_forget()
|
|
self.options_algo_Label.place_forget()
|
|
self.options_algo_Optionmenu.place_forget()
|
|
else:
|
|
# Choose Ensemble
|
|
self.options_ensChoose_Label.place(x=0, y=19, width=0, height=-10,
|
|
relx=0, rely=6/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
self.options_ensChoose_Optionmenu.place(x=0, y=19, width=0, height=7,
|
|
relx=0, rely=7/self.COL1_ROWS, relwidth=1/3, relheight=1/self.COL1_ROWS)
|
|
# WINDOW
|
|
self.options_winSize_Label.place(x=13, y=0, width=0, height=-10,
|
|
relx=1/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_winSize_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=1/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# AGG
|
|
self.options_agg_Label.place(x=15, y=0, width=0, height=-10,
|
|
relx=2/3, rely=2/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
self.options_agg_Optionmenu.place(x=71, y=-2, width=-118, height=7,
|
|
relx=2/3, rely=3/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#GPU Conversion
|
|
self.options_gpu_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_gpu_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Vocals Only
|
|
self.options_voc_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_voc_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Instrumental Only
|
|
self.options_inst_only_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_inst_only_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=1/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
# TTA
|
|
self.options_tta_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_tta_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Post-Process
|
|
self.options_post_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_post_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=6/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Save Image
|
|
# self.options_image_Checkbutton.configure(state=tk.NORMAL)
|
|
# self.options_image_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
# relx=2/3, rely=5/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Ensemble Save Outputs
|
|
self.options_save_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_save_Checkbutton.place(x=35, y=21, width=0, height=5,
|
|
relx=2/3, rely=7/self.COL2_ROWS, relwidth=1/3, relheight=1/self.COL2_ROWS)
|
|
#Forget Widgets
|
|
self.options_algo_Label.place_forget()
|
|
self.options_algo_Optionmenu.place_forget()
|
|
self.options_instrumentalModel_Label.place_forget()
|
|
self.options_instrumentalModel_Optionmenu.place_forget()
|
|
self.options_chunks_Label.place_forget()
|
|
self.options_chunks_Optionmenu.place_forget()
|
|
self.options_noisereduc_s_Label.place_forget()
|
|
self.options_noisereduc_s_Optionmenu.place_forget()
|
|
self.options_mdxnetModel_Label.place_forget()
|
|
self.options_mdxnetModel_Optionmenu.place_forget()
|
|
self.options_modelFolder_Checkbutton.place_forget()
|
|
self.options_modelFolder_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_noisereduc_Checkbutton.place_forget()
|
|
self.options_noisereduc_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_demucsmodel_Checkbutton.place_forget()
|
|
self.options_demucsmodel_Checkbutton.configure(state=tk.DISABLED)
|
|
self.options_non_red_Checkbutton.place_forget()
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
|
|
|
|
if self.inst_only_var.get() == True:
|
|
self.options_voc_only_Checkbutton.configure(state=tk.DISABLED)
|
|
self.voc_only_var.set(False)
|
|
self.non_red_var.set(False)
|
|
elif self.inst_only_var.get() == False:
|
|
self.options_non_red_Checkbutton.configure(state=tk.NORMAL)
|
|
self.options_voc_only_Checkbutton.configure(state=tk.NORMAL)
|
|
|
|
if self.voc_only_var.get() == True:
|
|
self.options_inst_only_Checkbutton.configure(state=tk.DISABLED)
|
|
self.inst_only_var.set(False)
|
|
elif self.voc_only_var.get() == False:
|
|
self.options_inst_only_Checkbutton.configure(state=tk.NORMAL)
|
|
|
|
if self.noisereduc_s_var.get() == 'None':
|
|
self.options_non_red_Checkbutton.configure(state=tk.DISABLED)
|
|
self.non_red_var.set(False)
|
|
if not self.noisereduc_s_var.get() == 'None':
|
|
self.options_non_red_Checkbutton.configure(state=tk.NORMAL)
|
|
|
|
|
|
self.update_inputPaths()
|
|
|
|
def deselect_models(self):
|
|
"""
|
|
Run this method on version change
|
|
"""
|
|
if self.aiModel_var.get() == self.last_aiModel:
|
|
return
|
|
else:
|
|
self.last_aiModel = self.aiModel_var.get()
|
|
|
|
self.instrumentalModel_var.set('')
|
|
self.ensChoose_var.set('MDX-Net/VR Ensemble')
|
|
self.mdxnetModel_var.set('UVR-MDX-NET 1')
|
|
|
|
self.winSize_var.set(DEFAULT_DATA['window_size'])
|
|
self.agg_var.set(DEFAULT_DATA['agg'])
|
|
self.modelFolder_var.set(DEFAULT_DATA['modelFolder'])
|
|
|
|
|
|
self.update_available_models()
|
|
self.update_states()
|
|
|
|
def restart(self):
|
|
"""
|
|
Restart the application after asking for confirmation
|
|
"""
|
|
confirm = tk.messagebox.askyesno(title='Restart Confirmation',
|
|
message='This will restart the application and halt any running processes. Your current settings will be saved. \n\n Are you sure you wish to continue?')
|
|
|
|
if confirm:
|
|
self.save_values()
|
|
|
|
subprocess.Popen(f'UVR_Launcher.exe')
|
|
exit()
|
|
else:
|
|
pass
|
|
|
|
def help(self):
|
|
"""
|
|
Open Help Guide
|
|
"""
|
|
top= Toplevel(self)
|
|
top.geometry("1080x920")
|
|
top.title("UVR Help Guide")
|
|
|
|
top.resizable(False, False) # This code helps to disable windows from resizing
|
|
|
|
window_height = 920
|
|
window_width = 1080
|
|
|
|
screen_width = top.winfo_screenwidth()
|
|
screen_height = top.winfo_screenheight()
|
|
|
|
x_cordinate = int((screen_width/2) - (window_width/2))
|
|
y_cordinate = int((screen_height/2) - (window_height/2))
|
|
|
|
top.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))
|
|
|
|
# change title bar icon
|
|
top.iconbitmap('img\\UVR-Icon-v2.ico')
|
|
|
|
tabControl = ttk.Notebook(top)
|
|
|
|
tab1 = ttk.Frame(tabControl)
|
|
tab2 = ttk.Frame(tabControl)
|
|
tab3 = ttk.Frame(tabControl)
|
|
tab4 = ttk.Frame(tabControl)
|
|
tab5 = ttk.Frame(tabControl)
|
|
tab6 = ttk.Frame(tabControl)
|
|
tab7 = ttk.Frame(tabControl)
|
|
tab8 = ttk.Frame(tabControl)
|
|
tab9 = ttk.Frame(tabControl)
|
|
|
|
tabControl.add(tab1, text ='General Options')
|
|
tabControl.add(tab2, text ='VR Architecture Options')
|
|
tabControl.add(tab3, text ='MDX-Net Options')
|
|
tabControl.add(tab4, text ='Ensemble Mode')
|
|
tabControl.add(tab5, text ='User Ensemble')
|
|
tabControl.add(tab6, text ='More Info')
|
|
tabControl.add(tab7, text ='Credits')
|
|
tabControl.add(tab8, text ='Updates')
|
|
tabControl.add(tab9, text ='Error Log')
|
|
|
|
tabControl.pack(expand = 1, fill ="both")
|
|
|
|
#Configure the row/col of our frame and root window to be resizable and fill all available space
|
|
tab6.grid_rowconfigure(0, weight=1)
|
|
tab6.grid_columnconfigure(0, weight=1)
|
|
|
|
tab7.grid_rowconfigure(0, weight=1)
|
|
tab7.grid_columnconfigure(0, weight=1)
|
|
|
|
tab8.grid_rowconfigure(0, weight=1)
|
|
tab8.grid_columnconfigure(0, weight=1)
|
|
|
|
tab9.grid_rowconfigure(0, weight=1)
|
|
tab9.grid_columnconfigure(0, weight=1)
|
|
|
|
ttk.Label(tab1, image=self.gen_opt_img).grid(column = 0,
|
|
row = 0,
|
|
padx = 30,
|
|
pady = 30)
|
|
|
|
ttk.Label(tab2, image=self.vr_opt_img).grid(column = 0,
|
|
row = 0,
|
|
padx = 30,
|
|
pady = 30)
|
|
|
|
ttk.Label(tab3, image=self.mdx_opt_img).grid(column = 0,
|
|
row = 0,
|
|
padx = 30,
|
|
pady = 30)
|
|
|
|
ttk.Label(tab4, image=self.ense_opt_img).grid(column = 0,
|
|
row = 0,
|
|
padx = 30,
|
|
pady = 30)
|
|
|
|
ttk.Label(tab5, image=self.user_ens_opt_img).grid(column = 0,
|
|
row = 0,
|
|
padx = 30,
|
|
pady = 30)
|
|
|
|
#frame0
|
|
frame0=Frame(tab6,highlightbackground='red',highlightthicknes=0)
|
|
frame0.grid(row=0,column=0,padx=0,pady=30)
|
|
|
|
l0=Label(frame0,text="Notes",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=1,column=0,padx=20,pady=15)
|
|
|
|
l0=Label(frame0,text="UVR is 100% free and open-source but MIT licensed.\nAll the models provided as part of UVR were trained by its core developers.\nPlease credit the core UVR developers if you choose to use any of our models or code for projects unrelated to UVR.",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=2,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Resources",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=3,column=0,padx=20,pady=15, sticky=N)
|
|
|
|
link = Label(frame0, text="Ultimate Vocal Remover (Official GitHub)",font=("Century Gothic", "14", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=4,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/Anjok07/ultimatevocalremovergui"))
|
|
|
|
l0=Label(frame0,text="You can find updates, report issues, and give us a shout via our official GitHub.",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=5,column=0,padx=10,pady=10)
|
|
|
|
link = Label(frame0, text="SoX - Sound eXchange",font=("Century Gothic", "14", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=6,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://sourceforge.net/projects/sox/files/sox/14.4.2/sox-14.4.2-win32.zip/download"))
|
|
|
|
l0=Label(frame0,text="UVR relies on SoX for Noise Reduction. It's automatically included via the UVR installer but not the developer build.\nIf you are missing SoX, please download it via the link and extract the SoX archive to the following directory - lib_v5/sox",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=7,column=0,padx=10,pady=10)
|
|
|
|
link = Label(frame0, text="FFmpeg",font=("Century Gothic", "14", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=8,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://www.wikihow.com/Install-FFmpeg-on-Windows"))
|
|
|
|
l0=Label(frame0,text="UVR relies on FFmpeg for processing non-wav audio files.\nIt's automatically included via the UVR installer but not the developer build.\nIf you are missing FFmpeg, please see the installation guide via the link provided.",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=9,column=0,padx=10,pady=10)
|
|
|
|
link = Label(frame0, text="X-Minus AI",font=("Century Gothic", "14", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=10,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://x-minus.pro/ai"))
|
|
|
|
l0=Label(frame0,text="Many of the models provided are also on X-Minus.\nThis resource primarily benefits users without the computing resources to run the GUI or models locally.",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=11,column=0,padx=10,pady=10)
|
|
|
|
link = Label(frame0, text="Official UVR Patreon",font=("Century Gothic", "14", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=12,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://www.patreon.com/uvr"))
|
|
|
|
l0=Label(frame0,text="If you wish to support and donate to this project, click the link above and become a Patreon!",font=("Century Gothic", "13"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=13,column=0,padx=10,pady=10)
|
|
|
|
frame0=Frame(tab7,highlightbackground='red',highlightthicknes=0)
|
|
frame0.grid(row=0,column=0,padx=0,pady=30)
|
|
|
|
#inside frame0
|
|
|
|
l0=Label(frame0,text="Core UVR Developers",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=0,column=0,padx=20,pady=10, sticky=N)
|
|
|
|
l0=Label(frame0,image=self.credits_img,font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=1,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Anjok07\nAufr33",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=2,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Special Thanks",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=4,column=0,padx=20,pady=15)
|
|
|
|
l0=Label(frame0,text="DilanBoskan",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=5,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Your contributions at the start of this project were essential to the success of UVR. Thank you!",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=6,column=0,padx=0,pady=0)
|
|
|
|
link = Label(frame0, text="Tsurumeso",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=7,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/tsurumeso/vocal-remover"))
|
|
|
|
l0=Label(frame0,text="Developed the original VR Architecture AI code.",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=8,column=0,padx=0,pady=0)
|
|
|
|
link = Label(frame0, text="Kuielab & Woosung Choi",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=9,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/kuielab"))
|
|
|
|
l0=Label(frame0,text="Developed the original MDX-Net AI code.",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=10,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="Bas Curtiz",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=11,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Designed the official UVR logo, icon, banner, splash screen, and interface.",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=12,column=0,padx=0,pady=0)
|
|
|
|
link = Label(frame0, text="Adefossez & Demucs",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=13,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/facebookresearch/demucs"))
|
|
|
|
l0=Label(frame0,text="Core developer of Facebook's Demucs Music Source Separation.",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=14,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="Audio Separation Discord Community",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=15,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Thank you for the support!",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=16,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="CC Karokee & Friends Discord Community",font=("Century Gothic", "13", "bold"), justify="center", fg="#13a4c9")
|
|
l0.grid(row=17,column=0,padx=10,pady=10)
|
|
|
|
l0=Label(frame0,text="Thank you for the support!",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=18,column=0,padx=0,pady=0)
|
|
|
|
frame0=Frame(tab8,highlightbackground='red',highlightthicknes=0)
|
|
frame0.grid(row=0,column=0,padx=0,pady=30)
|
|
|
|
l0=Label(frame0,text="Update Details",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=1,column=0,padx=20,pady=10)
|
|
|
|
l0=Label(frame0,text="Installing Model Expansion Pack",font=("Century Gothic", "13", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=2,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="1. Download the model expansion pack via the provided link below.\n2. Once the download has completed, click the \"Open Models Directory\" button below.\n3. Extract the \'Main Models\' folder within the downloaded archive to the opened \"models\" directory.\n4. Without restarting the application, you will now see the new models appear under the VR Architecture model selection list.",font=("Century Gothic", "11"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=3,column=0,padx=0,pady=0)
|
|
|
|
link = Label(frame0, text="Model Expansion Pack",font=("Century Gothic", "11", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=4,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/Anjok07/ultimatevocalremovergui/releases/tag/v5.2.0"))
|
|
|
|
l0=Button(frame0,text='Open Models Directory',font=("Century Gothic", "11"), command=self.open_Modelfolder_filedialog, justify="left", wraplength=1000, bg="black", relief="ridge")
|
|
l0.grid(row=5,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="\n\n\nBackward Compatibility",font=("Century Gothic", "13", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=6,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="The v4 Models are fully compatible with this GUI. \n1. If you already have them on your system, click the \"Open Models Directory\" button below. \n2. Place the files with extension \".pth\" into the \"Main Models\" directory. \n3. Now they will automatically appear in the VR Architecture model selection list.\n Note: The v2 models are not compatible with this GUI.\n",font=("Century Gothic", "11"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=7,column=0,padx=0,pady=0)
|
|
|
|
l0=Button(frame0,text='Open Models Directory',font=("Century Gothic", "11"), command=self.open_Modelfolder_filedialog, justify="left", wraplength=1000, bg="black", relief="ridge")
|
|
l0.grid(row=8,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="\n\n\nInstalling Future Updates",font=("Century Gothic", "13", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=9,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="New updates and patches for this application can be found on the official UVR Releases GitHub page (link below).\nAny new update instructions will likely require the use of the \"Open Application Directory\" button below.",font=("Century Gothic", "11"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=10,column=0,padx=0,pady=0)
|
|
|
|
link = Label(frame0, text="UVR Releases GitHub Page",font=("Century Gothic", "11", "underline"), justify="center", fg="#13a4c9", cursor="hand2")
|
|
link.grid(row=11,column=0,padx=10,pady=10)
|
|
link.bind("<Button-1>", lambda e:
|
|
callback("https://github.com/Anjok07/ultimatevocalremovergui/releases"))
|
|
|
|
l0=Button(frame0,text='Open Application Directory',font=("Century Gothic", "11"), command=self.open_appdir_filedialog, justify="left", wraplength=1000, bg="black", relief="ridge")
|
|
l0.grid(row=12,column=0,padx=0,pady=0)
|
|
|
|
frame0=Frame(tab9,highlightbackground='red',highlightthicknes=0)
|
|
frame0.grid(row=0,column=0,padx=0,pady=30)
|
|
|
|
l0=Label(frame0,text="Error Details",font=("Century Gothic", "16", "bold"), justify="center", fg="#f4f4f4")
|
|
l0.grid(row=1,column=0,padx=20,pady=10)
|
|
|
|
l0=Label(frame0,text="This tab will show the raw details of the last error received.",font=("Century Gothic", "12"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=2,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="(Click the error console below to copy the error)\n",font=("Century Gothic", "10"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=3,column=0,padx=0,pady=0)
|
|
|
|
with open("errorlog.txt", "r") as f:
|
|
l0=Button(frame0,text=f.read(),font=("Century Gothic", "11"), command=self.copy_clip, justify="left", wraplength=1000, fg="#FF0000", bg="black", relief="sunken")
|
|
l0.grid(row=4,column=0,padx=0,pady=0)
|
|
|
|
l0=Label(frame0,text="",font=("Century Gothic", "10"), justify="center", fg="#F6F6F7")
|
|
l0.grid(row=5,column=0,padx=0,pady=0)
|
|
|
|
def copy_clip(self):
|
|
copy_t = open("errorlog.txt", "r").read()
|
|
pyperclip.copy(copy_t)
|
|
|
|
def open_Modelfolder_filedialog(self):
|
|
"""Let user paste a ".pth" model to use for the vocal seperation"""
|
|
filename = 'models'
|
|
|
|
if sys.platform == "win32":
|
|
os.startfile(filename)
|
|
else:
|
|
opener = "open" if sys.platform == "darwin" else "xdg-open"
|
|
subprocess.call([opener, filename])
|
|
|
|
def open_appdir_filedialog(self):
|
|
|
|
pathname = '.'
|
|
|
|
print(pathname)
|
|
|
|
if sys.platform == "win32":
|
|
os.startfile(pathname)
|
|
else:
|
|
opener = "open" if sys.platform == "darwin" else "xdg-open"
|
|
subprocess.call([opener, filename])
|
|
|
|
def save_values(self):
|
|
"""
|
|
Save the data of the application
|
|
"""
|
|
# Get constants
|
|
instrumental = self.instrumentalModel_var.get()
|
|
if [bool(instrumental)].count(True) == 2: #Checkthis
|
|
window_size = DEFAULT_DATA['window_size']
|
|
agg = DEFAULT_DATA['agg']
|
|
chunks = DEFAULT_DATA['chunks']
|
|
noisereduc_s = DEFAULT_DATA['noisereduc_s']
|
|
mixing = DEFAULT_DATA['mixing']
|
|
else:
|
|
window_size = self.winSize_var.get()
|
|
agg = self.agg_var.get()
|
|
chunks = self.chunks_var.get()
|
|
noisereduc_s = self.noisereduc_s_var.get()
|
|
mixing = self.mixing_var.get()
|
|
|
|
# -Save Data-
|
|
save_data(data={
|
|
'exportPath': self.exportPath_var.get(),
|
|
'inputPaths': self.inputPaths,
|
|
'saveFormat': self.saveFormat_var.get(),
|
|
'gpu': self.gpuConversion_var.get(),
|
|
'postprocess': self.postprocessing_var.get(),
|
|
'tta': self.tta_var.get(),
|
|
'save': self.save_var.get(),
|
|
'output_image': self.outputImage_var.get(),
|
|
'window_size': window_size,
|
|
'agg': agg,
|
|
'useModel': 'instrumental',
|
|
'lastDir': self.lastDir,
|
|
'modelFolder': self.modelFolder_var.get(),
|
|
'modelInstrumentalLabel': self.instrumentalModel_var.get(),
|
|
'aiModel': self.aiModel_var.get(),
|
|
'algo': self.algo_var.get(),
|
|
'ensChoose': self.ensChoose_var.get(),
|
|
'mdxnetModel': self.mdxnetModel_var.get(),
|
|
#MDX-Net
|
|
'demucsmodel': self.demucsmodel_var.get(),
|
|
'non_red': self.non_red_var.get(),
|
|
'noise_reduc': self.noisereduc_var.get(),
|
|
'voc_only': self.voc_only_var.get(),
|
|
'inst_only': self.inst_only_var.get(),
|
|
'chunks': chunks,
|
|
'noisereduc_s': noisereduc_s,
|
|
'mixing': mixing,
|
|
})
|
|
|
|
self.destroy()
|
|
|
|
if __name__ == "__main__":
|
|
|
|
root = MainWindow()
|
|
|
|
root.tk.call(
|
|
'wm',
|
|
'iconphoto',
|
|
root._w,
|
|
tk.PhotoImage(file='img\\GUI-icon.png')
|
|
)
|
|
|
|
lib_v5.sv_ttk.set_theme("dark")
|
|
lib_v5.sv_ttk.use_dark_theme() # Set dark theme
|
|
|
|
#Define a callback function
|
|
def callback(url):
|
|
webbrowser.open_new_tab(url)
|
|
|
|
root.mainloop()
|