diff --git a/script.py b/script.py index 38bac24..94d2df8 100644 --- a/script.py +++ b/script.py @@ -77,6 +77,8 @@ with open(this_dir / "languages.json", encoding="utf8") as f: languages = json.load(f) # Create a global lock process_lock = threading.Lock() +# Base setting for a possible FineTuned model existing and the loader being available +tts_method_xtts_ft = False # Gather the voice files def get_available_voices(): @@ -139,10 +141,23 @@ def check_required_files(): subprocess.run(["python", str(download_script_path)]) print(f"[{params['branding']}Startup] All required files are present.") - # STARTUP Call Check routine check_required_files() +################################################## +#### Check to see if a finetuned model exists #### +################################################## +# Set the path to the directory +trained_model_directory = this_dir / "models" / "trainedmodel" +# Check if the directory "trainedmodel" exists +finetuned_model = trained_model_directory.exists() +# If the directory exists, check for the existence of the required files +# If true, this will add a extra option in the Gradio interface for loading Xttsv2 FT +if finetuned_model: + required_files = ["model.pth", "config.json", "vocab.json"] + finetuned_model = all((trained_model_directory / file).exists() for file in required_files) +if finetuned_model: + print(f"[{params['branding']}Startup] Finetuned model \033[93mDetected\033[0m") #################################################### #### SET GRADIO BUTTONS BASED ON confignew.json #### @@ -272,11 +287,13 @@ else: # Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this alltalk_tts sys.exit(1) + ##################################### #### MODEL LOADING AND UNLOADING #### ##################################### # MODEL - Swap model based on Gradio selection API TTS, API Local, XTTSv2 Local def send_reload_request(tts_method): + global tts_method_xtts_ft try: params["tts_model_loaded"] = False url = f"{base_url}/api/reload" @@ -295,17 +312,26 @@ def send_reload_request(tts_method): params["tts_method_api_tts"] = True params["deepspeed_activate"] = False audio_path = this_dir / "templates" / "apitts.wav" + tts_method_xtts_ft = False elif tts_method == "API Local": params["tts_method_api_tts"] = False params["tts_method_xtts_local"] = False params["tts_method_api_local"] = True params["deepspeed_activate"] = False audio_path = this_dir / "templates" / "apilocal.wav" + tts_method_xtts_ft = False elif tts_method == "XTTSv2 Local": params["tts_method_api_tts"] = False params["tts_method_api_local"] = False params["tts_method_xtts_local"] = True audio_path = this_dir / "templates" / "xttslocal.wav" + tts_method_xtts_ft = False + elif tts_method == "XTTSv2 FT": + params["tts_method_api_tts"] = False + params["tts_method_api_local"] = False + params["tts_method_xtts_local"] = False + audio_path = this_dir / "templates" / "xttsfinetuned.wav" + tts_method_xtts_ft = True return f'' except requests.exceptions.RequestException as e: # Handle the HTTP request error @@ -494,7 +520,6 @@ def output_modifier(string, state): if not params["activate"]: return string original_string = string - #print("ORGINAL STRING: ", original_string) cleaned_string = before_audio_generation(string, params) if cleaned_string is None: return @@ -505,7 +530,6 @@ def output_modifier(string, state): if process_lock.acquire(blocking=False): try: if params["narrator_enabled"]: - #print(original_string) # Do Some basic stripping and remove any double CR's processed_string = ( original_string @@ -786,8 +810,11 @@ def ui(): deepspeed_checkbox_play = gr.HTML(visible=False) with gr.Row(): + model_loader_choices=["API TTS", "API Local", "XTTSv2 Local"] + if finetuned_model: + model_loader_choices.append("XTTSv2 FT") tts_radio_buttons = gr.Radio( - choices=["API TTS", "API Local", "XTTSv2 Local"], + choices=model_loader_choices, label="Select TTS Generation Method (Read NOTE)", value=gr_modelchoice, # Set the default value ) diff --git a/templates/xttsfinetuned.wav b/templates/xttsfinetuned.wav new file mode 100644 index 0000000..6bddcfd Binary files /dev/null and b/templates/xttsfinetuned.wav differ diff --git a/tts_server.py b/tts_server.py index 57ac453..e9a6e5a 100644 --- a/tts_server.py +++ b/tts_server.py @@ -33,7 +33,8 @@ device = "cuda" if torch.cuda.is_available() else "cpu" # STARTUP VARIABLE - Import languges file for Gradio to be able to display them in the interface with open(this_dir / "languages.json", encoding="utf8") as f: languages = json.load(f) - +# Base setting for a possible FineTuned model existing and the loader being available +tts_method_xtts_ft = False ################################################################# #### LOAD PARAMS FROM confignew.json - REQUIRED FOR BRANDING #### @@ -123,7 +124,7 @@ app = FastAPI(lifespan=startup_shutdown) ##################################### #### MODEL LOADING AND UNLOADING #### ##################################### -# MODEL LOADERS Picker For API TTS, API Local, XTTSv2 Local +# MODEL LOADERS Picker For API TTS, API Local, XTTSv2 Local, XTTSv2 FT async def setup(): global device # Set a timer to calculate load times @@ -150,6 +151,13 @@ async def setup(): "\033[0m", ) model = await xtts_manual_load_model() + elif tts_method_xtts_ft: + print( + f"[{params['branding']}Model] \033[94mXTTSv2 FT Loading\033[0m /models/fintuned/model.pth \033[94minto\033[93m", + device, + "\033[0m", + ) + model = await xtts_ft_manual_load_model() # Create an end timer for calculating load times generate_end_time = time.time() # Calculate start time minus end time @@ -222,6 +230,23 @@ async def xtts_manual_load_model(): model.to(device) return model +# MODEL LOADER For "XTTSv2 FT" +async def xtts_ft_manual_load_model(): + global model + config = XttsConfig() + config_path = this_dir / "models" / "trainedmodel" / "config.json" + vocab_path_dir = this_dir / "models" / "trainedmodel" / "vocab.json" + checkpoint_dir = this_dir / "models" / "trainedmodel" + config.load_json(str(config_path)) + model = Xtts.init_from_config(config) + model.load_checkpoint( + config, + checkpoint_dir=str(checkpoint_dir), + vocab_path=str(vocab_path_dir), + use_deepspeed=params["deepspeed_activate"], + ) + model.to(device) + return model # MODEL UNLOADER async def unload_model(model): @@ -236,6 +261,7 @@ async def unload_model(model): # MODEL - Swap model based on Gradio selection API TTS, API Local, XTTSv2 Local async def handle_tts_method_change(tts_method): global model + global tts_method_xtts_ft # Update the params dictionary based on the selected radio button print( f"[{params['branding']}Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m" @@ -246,15 +272,23 @@ async def handle_tts_method_change(tts_method): params["tts_method_xtts_local"] = False params["tts_method_api_tts"] = True params["deepspeed_activate"] = False + tts_method_xtts_ft = False elif tts_method == "API Local": params["tts_method_api_tts"] = False params["tts_method_xtts_local"] = False params["tts_method_api_local"] = True params["deepspeed_activate"] = False + tts_method_xtts_ft = False elif tts_method == "XTTSv2 Local": params["tts_method_api_tts"] = False params["tts_method_api_local"] = False params["tts_method_xtts_local"] = True + tts_method_xtts_ft = False + elif tts_method == "XTTSv2 FT": + tts_method_xtts_ft = True + params["tts_method_api_tts"] = False + params["tts_method_api_local"] = False + params["tts_method_xtts_local"] = False # Unload the current model model = await unload_model(model) @@ -267,7 +301,7 @@ async def handle_tts_method_change(tts_method): @app.route("/api/reload", methods=["POST"]) async def reload(request: Request): tts_method = request.query_params.get("tts_method") - if tts_method not in ["API TTS", "API Local", "XTTSv2 Local"]: + if tts_method not in ["API TTS", "API Local", "XTTSv2 Local", "XTTSv2 FT"]: return {"status": "error", "message": "Invalid TTS method specified"} await handle_tts_method_change(tts_method) return Response( @@ -424,8 +458,8 @@ async def generate_audio(text, voice, language, output_file): if params["low_vram"] and device == "cpu": await switch_device() generate_start_time = time.time() # Record the start time of generating TTS - # XTTSv2 LOCAL Method - if params["tts_method_xtts_local"]: + # XTTSv2 LOCAL & Xttsv2 FT Method + if params["tts_method_xtts_local"] or tts_method_xtts_ft: print(f"[{params['branding']}TTSGen] {text}") gpt_cond_latent, speaker_embedding = model.get_conditioning_latents( audio_path=[f"{this_dir}/voices/{voice}"], @@ -805,10 +839,6 @@ async def tts_generate( autoplay_volume: float = Form(...), ): try: - #print(f"text_filtering: {text_filtering}") - #print(f"narrator_enabled: {narrator_enabled}") - #print(f"text_not_inside: {text_not_inside}") - #print(f"output_file_timestamp: {output_file_timestamp}") json_input_data = { "text_input": text_input, "text_filtering": text_filtering, @@ -828,46 +858,38 @@ async def tts_generate( else: return JSONResponse(content={"error": JSONresult}, status_code=400) if narrator_enabled: - print("ORIGINAL UNTOUCHED STRING IS:", text_input,"\n") + #print("ORIGINAL UNTOUCHED STRING IS:", text_input,"\n") if text_filtering in ["standard", "none"]: cleaned_string = ( text_input .replace('"', '"<') .replace('*', '<*') ) - print("STANDARD FILTERING IS NOW:", cleaned_string,"\n") - #parts = re.split(r'\.(?