diff --git a/data/models/coqui/.placeholder b/data/models/coqui/.placeholder new file mode 100644 index 0000000..ef6e9e2 --- /dev/null +++ b/data/models/coqui/.placeholder @@ -0,0 +1,2 @@ +Put Coqui models folders here. +Must contains both a "model.pth" and "config.json" file. diff --git a/data/models/rvc/.placeholder b/data/models/rvc/.placeholder index 5bbc9a8..b5ff768 100644 --- a/data/models/rvc/.placeholder +++ b/data/models/rvc/.placeholder @@ -1,2 +1,3 @@ -Put RVC models (in .pth format) here. -.index files (should have the same name as .pth files) are optional but could help improve the processing time. +Put RVC models folder here. +Must have ".pth" file in it +.index file is optional but could help improve the processing time/quality. diff --git a/modules/text_to_speech/coqui/coqui_module.py b/modules/text_to_speech/coqui/coqui_module.py index a50e122..a161fec 100644 --- a/modules/text_to_speech/coqui/coqui_module.py +++ b/modules/text_to_speech/coqui/coqui_module.py @@ -24,6 +24,10 @@ from TTS.utils.manage import ModelManager DEBUG_PREFIX = "" +COQUI_MODELS_PATH = "data/models/coqui/" +IGNORED_FILES = [".placeholder"] +COQUI_LOCAL_MODEL_FILE_NAME = "model.pth" +COQUI_LOCAL_CONFIG_FILE_NAME = "config.json" gpu_mode = False is_downloading = False @@ -165,8 +169,50 @@ def coqui_get_local_models(): """ Return user local models list in the following format: [language][dataset][name] = TTS_string_id """ + try: + print(DEBUG_PREFIX, "Received request for list of RVC models") + + folder_names = os.listdir(COQUI_MODELS_PATH) + + print(DEBUG_PREFIX,"Searching model in",COQUI_MODELS_PATH) + + model_list = [] + for folder_name in folder_names: + folder_path = COQUI_MODELS_PATH+folder_name + + if folder_name in IGNORED_FILES: + continue + + # Must be a folder + if not os.path.isdir(folder_path): + print("> WARNING:",folder_name,"is not a folder, it should not be there, ignored") + continue + + print("> Found model folder",folder_name) + + # Check pth + valid_folder = False + for file_name in os.listdir(folder_path): + if file_name.endswith(".pth"): + print(" > pth:",file_name) + valid_folder = True + if file_name.endswith(".config"): + print(" > config:",file_name) + + if valid_folder: + print(" > Valid folder added to list") + model_list.append(folder_name) + else: + print(" > WARNING: Missing pth or config file, ignored folder") + + # Return the list of valid folders + response = json.dumps({"models_list":model_list}) + return response + + except Exception as e: + print(e) + abort(500, DEBUG_PREFIX + " Exception occurs while searching for Coqui models.") - abort(500, DEBUG_PREFIX + " Not implemented yet") def coqui_generate_tts(): @@ -207,6 +253,12 @@ def coqui_generate_tts(): language_id = None speaker_id = None + # Local model + model_type = model_name.split("/")[0] + if model_type == "local": + return generate_tts_local(model_name.split("/")[1], text) + + if request_json["language_id"] != "none": language_id = request_json["language_id"] @@ -241,4 +293,33 @@ def coqui_generate_tts(): except Exception as e: print(e) - abort(500, DEBUG_PREFIX + " Exception occurs while trying to process request "+str(request_json)) \ No newline at end of file + abort(500, DEBUG_PREFIX + " Exception occurs while trying to process request "+str(request_json)) + +def generate_tts_local(model_folder, text): + """ + Generate tts using local coqui model + """ + audio_buffer = io.BytesIO() + + print(DEBUG_PREFIX,"Request for tts from local coqui model",model_folder) + + model_path = os.path.join(COQUI_MODELS_PATH,model_folder,COQUI_LOCAL_MODEL_FILE_NAME) + config_path = os.path.join(COQUI_MODELS_PATH,model_folder,COQUI_LOCAL_CONFIG_FILE_NAME) + + if not os.path.exists(model_path): + raise ValueError("File does not exists:",model_path) + + if not os.path.exists(config_path): + raise ValueError("File does not exists:",config_path) + + print(DEBUG_PREFIX,"Loading local tts model", model_path,"using",("GPU" if gpu_mode else "CPU")) + tts = TTS(model_path=model_path, config_path=config_path, progress_bar=True, gpu=gpu_mode) + tts.tts_to_file(text=text, file_path=audio_buffer) + + print(DEBUG_PREFIX, "Success, saved to",audio_buffer) + + # Return the output_audio_path object as a response + response = send_file(audio_buffer, mimetype="audio/x-wav") + audio_buffer = io.BytesIO() + + return response \ No newline at end of file diff --git a/modules/voice_conversion/rvc_module.py b/modules/voice_conversion/rvc_module.py index 3b43e90..cd7b156 100644 --- a/modules/voice_conversion/rvc_module.py +++ b/modules/voice_conversion/rvc_module.py @@ -63,7 +63,7 @@ def rvc_get_models_list(): else: print(" > WARNING: Missing pth, ignored folder") - # Return the output_audio_path object as a response + # Return the list of valid folders response = json.dumps({"models_list":model_list}) return response diff --git a/server.py b/server.py index 457d894..c0721fc 100644 --- a/server.py +++ b/server.py @@ -392,12 +392,14 @@ if "coqui-tts" in modules: if not coqui_module.install_model(i): raise ValueError("Coqui model loading failed, most likely a wrong model name in --coqui-models argument, check log above to see which one") - + # Coqui-api models app.add_url_rule("/api/text-to-speech/coqui/coqui-api/check-model-state", view_func=coqui_module.coqui_check_model_state, methods=["POST"]) app.add_url_rule("/api/text-to-speech/coqui/coqui-api/install-model", view_func=coqui_module.coqui_install_model, methods=["POST"]) + # Users models app.add_url_rule("/api/text-to-speech/coqui/local/get-models", view_func=coqui_module.coqui_get_local_models, methods=["POST"]) + # Handle both coqui-api/users models app.add_url_rule("/api/text-to-speech/coqui/generate-tts", view_func=coqui_module.coqui_generate_tts, methods=["POST"]) def require_module(name):