Branding Change
This commit is contained in:
1 parent
3d1316bd07
commit
ce11e4846e
4 files changed
+683
-330
No files matched your search
+1
-1
@@ -1 +1 @@
|
||||
{"activate": true, "autoplay": true, "deepspeed_activate": false, "delete_output_wavs": "Disabled", "ip_address": "127.0.0.1", "language": "English", "low_vram": false, "model_loaded": true, "model_name": "tts_models/multilingual/multi-dataset/xtts_v2", "output_folder_wav": "extensions/coqui_tts/outputs/", "port_number": "7851", "remove_trailing_dots": false, "show_text": true, "tts_method_api_local": false, "tts_method_api_tts": false, "tts_method_xtts_local": true, "voice": "female_01.wav"}
|
||||
{"activate": true, "autoplay": true, "branding": "AllTalk ", "deepspeed_activate": false, "delete_output_wavs": "Disabled", "ip_address": "127.0.0.1", "language": "English", "low_vram": false, "model_loaded": true, "model_name": "tts_models/multilingual/multi-dataset/xtts_v2", "output_folder_wav": "extensions/coqui_tts/outputs/", "port_number": "7851", "remove_trailing_dots": false, "show_text": true, "tts_method_api_local": false, "tts_method_api_tts": false, "tts_method_xtts_local": true, "voice": "female_01.wav"}
|
||||
+76
-26
@@ -6,15 +6,29 @@ import importlib.metadata as metadata
|
||||
import json
|
||||
from packaging import version
|
||||
|
||||
# Use this_dir in the downloader script
|
||||
##############################################################
|
||||
#### LOAD PARAMS FROM CONFIG.JSON - REQUIRED FOR BRANDING ####
|
||||
##############################################################
|
||||
# STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
|
||||
# Define the path to the JSON file
|
||||
config_file_path = this_dir / 'modeldownload.json'
|
||||
|
||||
# load standard config file in and get settings
|
||||
def load_config(file_path):
|
||||
with open(file_path, "r") as config_file:
|
||||
config = json.load(config_file)
|
||||
return config
|
||||
|
||||
|
||||
config_file_path = this_dir / "config.json"
|
||||
params = load_config(config_file_path)
|
||||
|
||||
# Define the path to the modeldownload config file file
|
||||
modeldownload_config_file_path = this_dir / "modeldownload.json"
|
||||
|
||||
# Check if the JSON file exists
|
||||
if config_file_path.exists():
|
||||
with open(config_file_path, 'r') as config_file:
|
||||
if modeldownload_config_file_path.exists():
|
||||
with open(modeldownload_config_file_path, "r") as config_file:
|
||||
settings = json.load(config_file)
|
||||
|
||||
# Extract settings from the loaded JSON
|
||||
@@ -23,65 +37,101 @@ if config_file_path.exists():
|
||||
files_to_download = settings.get("files_to_download", {})
|
||||
else:
|
||||
# Default settings if the JSON file doesn't exist or is empty
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m modeldownload.json is missing so please re-download it and save it in the coquii_tts main folder.")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m API Local and XTTSv2 Local will error unless this is corrected.")
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m modeldownload.json is missing so please re-download it and save it in the coquii_tts main folder."
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m API Local and XTTSv2 Local will error unless this is corrected."
|
||||
)
|
||||
|
||||
# Read the version specifier from requirements.txt
|
||||
with open(this_dir / 'requirements.txt', 'r') as req_file:
|
||||
with open(this_dir / "requirements.txt", "r") as req_file:
|
||||
requirements = req_file.readlines()
|
||||
|
||||
tts_version_required = None
|
||||
for req in requirements:
|
||||
if req.startswith('TTS=='):
|
||||
tts_version_required = req.strip().split('==')[1]
|
||||
if req.startswith("TTS=="):
|
||||
tts_version_required = req.strip().split("==")[1]
|
||||
break
|
||||
|
||||
if tts_version_required is None:
|
||||
raise ValueError("[CoquiTTS Startup] \033[91mWarning\033[0m Could not find TTS version specifier in requirements.txt")
|
||||
raise ValueError(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Could not find TTS version specifier in requirements.txt"
|
||||
)
|
||||
|
||||
|
||||
def create_directory_if_not_exists(directory):
|
||||
if not directory.exists():
|
||||
directory.mkdir(parents=True)
|
||||
|
||||
|
||||
def download_file(url, destination):
|
||||
response = requests.get(url, stream=True)
|
||||
total_size_in_bytes = int(response.headers.get('content-length', 0))
|
||||
total_size_in_bytes = int(response.headers.get("content-length", 0))
|
||||
block_size = 1024 # 1 Kibibyte
|
||||
|
||||
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)
|
||||
|
||||
with open(destination, 'wb') as file:
|
||||
progress_bar = tqdm(total=total_size_in_bytes, unit="iB", unit_scale=True)
|
||||
|
||||
with open(destination, "wb") as file:
|
||||
for data in response.iter_content(block_size):
|
||||
progress_bar.update(len(data))
|
||||
file.write(data)
|
||||
|
||||
progress_bar.close()
|
||||
|
||||
|
||||
def check_tts_version():
|
||||
try:
|
||||
tts_version = metadata.version("tts")
|
||||
print(f"[CoquiTTS Startup] TTS version installed: \033[93m{tts_version}\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Startup] TTS version installed: \033[93m"
|
||||
+ tts_version
|
||||
+ "\033[0m"
|
||||
)
|
||||
|
||||
if version.parse(tts_version) < version.parse(tts_version_required):
|
||||
print(f"[CoquiTTS Startup] \033[91mWarning\033[0m TTS version is too old. Please upgrade to version \033[93m{tts_version_required}\033[0m or later.\033[0m")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m At your terminal/command prompt \033[94mpip install --upgrade tts\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS version is too old. Please upgrade to version \033[93m"
|
||||
+ tts_version_required
|
||||
+ "\033[0m or later.\033[0m"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m At your terminal/command prompt \033[94mpip install --upgrade tts\033[0m"
|
||||
)
|
||||
else:
|
||||
print("[CoquiTTS Startup] TTS version is up to date.")
|
||||
print(f"[{params['branding']}Startup] TTS version is up to date.")
|
||||
except metadata.PackageNotFoundError:
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m TTS is not installed.")
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS is not installed."
|
||||
)
|
||||
|
||||
|
||||
# Check and create directories
|
||||
if str(base_path) == "models":
|
||||
create_directory_if_not_exists(this_dir / base_path / model_path)
|
||||
else:
|
||||
create_directory_if_not_exists(base_path / model_path)
|
||||
print("[CoquiTTS Startup] \033[94mInfo\033[0m Custom path set in \033[93mmodeldownload.json\033[0m. Using the following settings:")
|
||||
print("[CoquiTTS Startup] \033[94mInfo\033[0m Base folder Path:\033[93m", base_path , "\033[0m")
|
||||
print("[CoquiTTS Startup] \033[94mInfo\033[0m Model folder Path:\033[93m", model_path , "\033[0m")
|
||||
print("[CoquiTTS Startup] \033[94mInfo\033[0m Full Path:\033[93m", base_path / model_path , "\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Custom path set in \033[93mmodeldownload.json\033[0m. Using the following settings:"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Base folder Path:\033[93m",
|
||||
base_path,
|
||||
"\033[0m",
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Model folder Path:\033[93m",
|
||||
model_path,
|
||||
"\033[0m",
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[94mInfo\033[0m Full Path:\033[93m",
|
||||
base_path / model_path,
|
||||
"\033[0m",
|
||||
)
|
||||
|
||||
# Download files if they don't exist
|
||||
print("[CoquiTTS Startup] Checking Model is Downloaded.")
|
||||
print("[" + params["branding"] + "Startup] Checking Model is Downloaded.")
|
||||
for filename, url in files_to_download.items():
|
||||
if str(base_path) == "models":
|
||||
destination = this_dir / base_path / model_path / filename
|
||||
@@ -89,7 +139,7 @@ for filename, url in files_to_download.items():
|
||||
destination = Path(base_path) / model_path / filename
|
||||
|
||||
if not destination.exists():
|
||||
print(f"[CoquiTTS Startup] Downloading {filename}...")
|
||||
print(f"[{params['branding']}Startup] Downloading " + filename + "...")
|
||||
download_file(url, destination)
|
||||
|
||||
check_tts_version()
|
||||
@@ -19,22 +19,43 @@ from modules.logging_colors import logger
|
||||
from modules.ui import create_refresh_button
|
||||
from modules.utils import gradio
|
||||
|
||||
#Required for sentence splitting
|
||||
##############################################################
|
||||
#### LOAD PARAMS FROM CONFIG.JSON - REQUIRED FOR BRANDING ####
|
||||
##############################################################
|
||||
# STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
# load config file in and get settings
|
||||
def load_config(file_path):
|
||||
with open(file_path, "r") as config_file:
|
||||
config = json.load(config_file)
|
||||
return config
|
||||
|
||||
|
||||
config_file_path = this_dir / "config.json"
|
||||
params = load_config(config_file_path)
|
||||
|
||||
|
||||
# Required for sentence splitting
|
||||
try:
|
||||
from TTS.api import TTS
|
||||
from TTS.utils.synthesizer import Synthesizer
|
||||
except ModuleNotFoundError:
|
||||
logger.error(
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Could not find the TTS module. Make sure to install the requirements for the coqui_tts extension."
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Linux / Mac:\npip install -r extensions/coqui_tts/requirements.txt\n"
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Windows:\npip install -r extensions\\coqui_tts\\requirements.txt\n"
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m If you used the one-click installer, paste the command above in the terminal window launched after running the \"cmd_\" script. On Windows, that's \"cmd_windows.bat\"."
|
||||
"[params['branding']]\033[91mWarning\033[0m Could not find the TTS module. Make sure to install the requirements for the "
|
||||
+ params["branding"]
|
||||
+ " extension."
|
||||
"[params['branding']]\033[91mWarning\033[0m Linux / Mac:\npip install -r extensions/alltalk_tts/requirements.txt\n"
|
||||
"[params['branding']]\033[91mWarning\033[0m Windows:\npip install -r extensions\\alltalk_tts\\requirements.txt\n"
|
||||
"[params['branding']]\033[91mWarning\033[0m If you used the one-click installer, paste the command above in the terminal window launched after running the cmd_ script. On Windows, that's cmd_windows.bat."
|
||||
)
|
||||
raise
|
||||
|
||||
#IMPORT - Attempt Importing DeepSpeed
|
||||
# IMPORT - Attempt Importing DeepSpeed
|
||||
try:
|
||||
import deepspeed
|
||||
|
||||
deepspeed_installed = True
|
||||
except ImportError:
|
||||
deepspeed_installed = False
|
||||
@@ -42,41 +63,36 @@ except ImportError:
|
||||
###########################
|
||||
#### STARTUP VARIABLES ####
|
||||
###########################
|
||||
#STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
#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:
|
||||
# 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)
|
||||
# Create a global lock
|
||||
process_lock = threading.Lock()
|
||||
|
||||
#######################################
|
||||
#### LOAD PARAMS FROM CONFIG.JSON ####
|
||||
#######################################
|
||||
def load_config(file_path):
|
||||
with open(file_path, 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
return config
|
||||
|
||||
config_file_path = (this_dir / 'config.json')
|
||||
params = load_config(config_file_path)
|
||||
|
||||
def get_available_voices():
|
||||
return sorted([voice.name for voice in Path(f"{this_dir}/voices").glob("*.wav")])
|
||||
|
||||
|
||||
#########################
|
||||
#### LICENSE DISPLAY ####
|
||||
#########################
|
||||
#STARTUP Display Licence Information
|
||||
print("[CoquiTTS Startup] \033[94mCoqui Public Model License\033[0m")
|
||||
print("[CoquiTTS Startup] \033[94mhttps://coqui.ai/cpml.txt\033[0m")
|
||||
# STARTUP Display Licence Information
|
||||
print("[" + params["branding"] + "Startup] \033[94mCoqui Public Model License\033[0m")
|
||||
print("[" + params["branding"] + "Startup] \033[94mhttps://coqui.ai/cpml.txt\033[0m")
|
||||
|
||||
|
||||
############################################
|
||||
#### DELETE OLD OUTPUT WAV FILES IF SET ####
|
||||
############################################
|
||||
def delete_old_files(folder_path, days_to_keep):
|
||||
current_time = datetime.now()
|
||||
print("[CoquiTTS Startup] Deletion of old output folder WAV files is currently enabled and set at", delete_output_wavs_setting)
|
||||
print(
|
||||
"["
|
||||
+ params["branding"]
|
||||
+ "Startup] Deletion of old output folder WAV files is currently enabled and set at",
|
||||
delete_output_wavs_setting,
|
||||
)
|
||||
for file_name in os.listdir(folder_path):
|
||||
file_path = os.path.join(folder_path, file_name)
|
||||
if os.path.isfile(file_path):
|
||||
@@ -85,6 +101,7 @@ def delete_old_files(folder_path, days_to_keep):
|
||||
if age > timedelta(days=days_to_keep):
|
||||
os.remove(file_path)
|
||||
|
||||
|
||||
# Extract settings using params dictionary
|
||||
delete_output_wavs_setting = params["delete_output_wavs"]
|
||||
output_folder_wav = params["output_folder_wav"]
|
||||
@@ -92,25 +109,33 @@ output_folder_wav = os.path.normpath(output_folder_wav)
|
||||
|
||||
# Check and perform file deletion
|
||||
if delete_output_wavs_setting.lower() == "disabled":
|
||||
print("[CoquiTTS Startup] Old output wav file deletion is set to disabled.")
|
||||
print(
|
||||
"["
|
||||
+ params["branding"]
|
||||
+ "Startup] Old output wav file deletion is set to disabled."
|
||||
)
|
||||
else:
|
||||
try:
|
||||
days_to_keep = int(delete_output_wavs_setting.split()[0])
|
||||
delete_old_files(output_folder_wav, days_to_keep)
|
||||
except ValueError:
|
||||
print("[CoquiTTS Startup] Invalid setting for deleting old wav files. Please use 'Disabled' or 'X Days' format.")
|
||||
print(
|
||||
f"[{params['branding']}Startup] Invalid setting for deleting old wav files. Please use 'Disabled' or 'X Days' format."
|
||||
)
|
||||
|
||||
|
||||
########################
|
||||
#### STARTUP CHECKS ####
|
||||
########################
|
||||
#STARTUP Checks routine
|
||||
# STARTUP Checks routine
|
||||
def check_required_files():
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
download_script_path = this_dir / 'modeldownload.py'
|
||||
subprocess.run(['python', str(download_script_path)])
|
||||
print("[CoquiTTS Startup] All required files are present.")
|
||||
download_script_path = this_dir / "modeldownload.py"
|
||||
subprocess.run(["python", str(download_script_path)])
|
||||
print(f"[{params['branding']}Startup] All required files are present.")
|
||||
|
||||
#STARTUP Call Check routine
|
||||
|
||||
# STARTUP Call Check routine
|
||||
check_required_files()
|
||||
|
||||
#################################################
|
||||
@@ -124,72 +149,102 @@ elif params["tts_method_api_local"] == True:
|
||||
elif params["tts_method_xtts_local"] == True:
|
||||
gr_modelchoice = "XTTSv2 Local"
|
||||
|
||||
|
||||
######################
|
||||
#### GRADIO STUFF ####
|
||||
######################
|
||||
def remove_tts_from_history(history):
|
||||
for i, entry in enumerate(history['internal']):
|
||||
history['visible'][i] = [history['visible'][i][0], entry[1]]
|
||||
for i, entry in enumerate(history["internal"]):
|
||||
history["visible"][i] = [history["visible"][i][0], entry[1]]
|
||||
return history
|
||||
|
||||
|
||||
def toggle_text_in_history(history):
|
||||
for i, entry in enumerate(history['visible']):
|
||||
for i, entry in enumerate(history["visible"]):
|
||||
visible_reply = entry[1]
|
||||
if visible_reply.startswith('<audio'):
|
||||
if params['show_text']:
|
||||
reply = history['internal'][i][1]
|
||||
history['visible'][i] = [history['visible'][i][0], f"{visible_reply.split('</audio>')[0]}</audio>\n\n{reply}"]
|
||||
if visible_reply.startswith("<audio"):
|
||||
if params["show_text"]:
|
||||
reply = history["internal"][i][1]
|
||||
history["visible"][i] = [
|
||||
history["visible"][i][0],
|
||||
f"{visible_reply.split('</audio>')[0]}</audio>\n\n{reply}",
|
||||
]
|
||||
else:
|
||||
history['visible'][i] = [history['visible'][i][0], f"{visible_reply.split('</audio>')[0]}</audio>"]
|
||||
history["visible"][i] = [
|
||||
history["visible"][i][0],
|
||||
f"{visible_reply.split('</audio>')[0]}</audio>",
|
||||
]
|
||||
return history
|
||||
|
||||
|
||||
def history_modifier(history):
|
||||
# Remove autoplay from the last reply
|
||||
if len(history['internal']) > 0:
|
||||
history['visible'][-1] = [
|
||||
history['visible'][-1][0],
|
||||
history['visible'][-1][1].replace('controls autoplay>', 'controls>')
|
||||
if len(history["internal"]) > 0:
|
||||
history["visible"][-1] = [
|
||||
history["visible"][-1][0],
|
||||
history["visible"][-1][1].replace("controls autoplay>", "controls>"),
|
||||
]
|
||||
|
||||
return history
|
||||
|
||||
|
||||
######################################
|
||||
#### SUBPROCESS/WEBSERVER STARTUP ####
|
||||
######################################
|
||||
base_url = f"http://{params['ip_address']}:{params['port_number']}"
|
||||
script_path = this_dir / 'tts_server.py'
|
||||
script_path = this_dir / "tts_server.py"
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
print("[CoquiTTS Shutdown] \033[94mReceived Ctrl+C, terminating subprocess\033[92m")
|
||||
print(
|
||||
f"[{params['branding']}Shutdown] \033[94mReceived Ctrl+C, terminating subprocess\033[92m"
|
||||
)
|
||||
if process.poll() is None:
|
||||
process.terminate()
|
||||
process.wait() # Wait for the subprocess to finish
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# Attach the signal handler to the SIGINT signal (Ctrl+C)
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
# Start the subprocess
|
||||
process = subprocess.Popen(['python', script_path])
|
||||
process = subprocess.Popen(["python", script_path])
|
||||
|
||||
# Check if the subprocess has started successfully
|
||||
if process.poll() is None:
|
||||
print("[CoquiTTS Startup] TTS Subprocess starting")
|
||||
print("[CoquiTTS Startup] Readme available here:", f"http://{params['ip_address']}:{params['port_number']}")
|
||||
print(f"[{params['branding']}Startup] TTS Subprocess starting")
|
||||
print(
|
||||
f"[{params['branding']}Startup] Readme available here:",
|
||||
f"http://{params['ip_address']}:{params['port_number']}",
|
||||
)
|
||||
else:
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m TTS Subprocess Webserver failing to start process")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m It could be that you have something on port:", params['port_number'])
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m Or you have not started in a Python environement with all the necesssary bits installed")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m Check you are starting Text-generation-webui with either the start_xxxxx file or the Python environment with cmd_xxxxx file.")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m xxxxx is the type of OS you are on e.g. windows, linux or mac.")
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m Alternatively, you could check no other Python processes are running that shouldnt be e.g. Restart your computer is the simple way.")
|
||||
#Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this coquii_tts
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS Subprocess Webserver failing to start process"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m It could be that you have something on port:",
|
||||
params["port_number"],
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Or you have not started in a Python environement with all the necesssary bits installed"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Check you are starting Text-generation-webui with either the start_xxxxx file or the Python environment with cmd_xxxxx file."
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m xxxxx is the type of OS you are on e.g. windows, linux or mac."
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Alternatively, you could check no other Python processes are running that shouldnt be e.g. Restart your computer is the simple way."
|
||||
)
|
||||
# Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this alltalk_tts
|
||||
sys.exit(1)
|
||||
|
||||
timeout = 60 # Adjust the timeout as needed
|
||||
|
||||
# Introduce a delay before starting the check loop
|
||||
time.sleep(25) #Wait 25 secs before checking if the tts_server.py has started up.
|
||||
time.sleep(25) # Wait 25 secs before checking if the tts_server.py has started up.
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < timeout:
|
||||
try:
|
||||
@@ -198,17 +253,22 @@ while time.time() - start_time < timeout:
|
||||
break
|
||||
except requests.RequestException as e:
|
||||
# Print the exception for debugging purposes
|
||||
print(f"[CoquiTTS Startup] \033[91mWarning\033[0m TTS Subprocess has NOT started up yet, Will keep trying for 60 seconds maximum")
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m TTS Subprocess has NOT started up yet, Will keep trying for 60 seconds maximum"
|
||||
)
|
||||
time.sleep(1)
|
||||
else:
|
||||
print("[CoquiTTS Startup] Startup timed out. Check the server logs for more information.")
|
||||
#Cleanly kill off this script, but allow text-generation-webui to keep running, albeit without this coquii_tts
|
||||
print(
|
||||
f"[{params['branding']}Startup] Startup timed out. Check the server logs for more information."
|
||||
)
|
||||
# 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
|
||||
# MODEL - Swap model based on Gradio selection API TTS, API Local, XTTSv2 Local
|
||||
def send_reload_request(tts_method):
|
||||
try:
|
||||
params["model_loaded"] = False
|
||||
@@ -224,13 +284,16 @@ def send_reload_request(tts_method):
|
||||
return json_response
|
||||
except requests.exceptions.RequestException as e:
|
||||
# Handle the HTTP request error
|
||||
print(f"[CoquiTTS Server] \033[91mWarning\033[0m Error during request to webserver process: {e}")
|
||||
print(
|
||||
f"[{params['branding']}Server] \033[91mWarning\033[0m Error during request to webserver process: {e}"
|
||||
)
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
##################
|
||||
#### LOW VRAM ####
|
||||
##################
|
||||
#LOW VRAM - Gradio Checkbox handling
|
||||
# LOW VRAM - Gradio Checkbox handling
|
||||
def send_lowvram_request(low_vram):
|
||||
try:
|
||||
params["model_loaded"] = False
|
||||
@@ -246,13 +309,16 @@ def send_lowvram_request(low_vram):
|
||||
return json_response
|
||||
except requests.exceptions.RequestException as e:
|
||||
# Handle the HTTP request error
|
||||
print(f"[CoquiTTS Server] \033[91mWarning\033[0m Error during request to webserver process: {e}")
|
||||
print(
|
||||
f"[{params['branding']}Server] \033[91mWarning\033[0m Error during request to webserver process: {e}"
|
||||
)
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
###################
|
||||
#### DeepSpeed ####
|
||||
###################
|
||||
#DEEPSPEED - Reload the model when DeepSpeed checkbox is enabled/disabled
|
||||
# DEEPSPEED - Reload the model when DeepSpeed checkbox is enabled/disabled
|
||||
def send_deepspeed_request(deepspeed_param):
|
||||
try:
|
||||
params["model_loaded"] = False
|
||||
@@ -268,54 +334,63 @@ def send_deepspeed_request(deepspeed_param):
|
||||
return json_response
|
||||
except requests.exceptions.RequestException as e:
|
||||
# Handle the HTTP request error
|
||||
print(f"[CoquiTTS Server] \033[91mWarning\033[0m Error during request to webserver process: {e}")
|
||||
print(
|
||||
f"[{params['branding']}Server] \033[91mWarning\033[0m Error during request to webserver process: {e}"
|
||||
)
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
# DEEPSPEED - Display DeepSpeed Checkbox Yes or No
|
||||
deepspeed_condition = params["tts_method_xtts_local"] == "True" and deepspeed_installed
|
||||
|
||||
|
||||
########################
|
||||
#### TTS GENERATION ####
|
||||
########################
|
||||
#PREVIEW VOICE - Generate Random Sentence if Voice Preview box is empty
|
||||
# PREVIEW VOICE - Generate Random Sentence if Voice Preview box is empty
|
||||
def random_sentence():
|
||||
with open(Path("extensions/coqui_tts/harvard_sentences.txt")) as f:
|
||||
with open(Path("extensions/alltalk_tts/harvard_sentences.txt")) as f:
|
||||
return random.choice(list(f))
|
||||
|
||||
#PREVIEW VOICE- Generate TTS Function
|
||||
|
||||
# PREVIEW VOICE- Generate TTS Function
|
||||
def voice_preview(string):
|
||||
if not params['activate']:
|
||||
return string
|
||||
if not params["activate"]:
|
||||
return string
|
||||
# Clean the string, capture model not loaded, and move model to cuda if needed
|
||||
cleaned_string = before_audio_generation(string, params)
|
||||
cleaned_string = before_audio_generation(string, params)
|
||||
if cleaned_string is None:
|
||||
return
|
||||
string = cleaned_string
|
||||
return
|
||||
string = cleaned_string
|
||||
# Setup the output file
|
||||
output_file = Path(params["output_folder_wav"]) / "voice_preview.wav"
|
||||
# Generate the audio
|
||||
language_code = languages.get(params["language"])
|
||||
language_code = languages.get(params["language"])
|
||||
# Convert the WindowsPath object to a string before using it in JSON payload
|
||||
output_file_str = output_file.as_posix()
|
||||
output_file_str = output_file.as_posix()
|
||||
# Lock before making the generate request
|
||||
with process_lock:
|
||||
generate_response = send_generate_request(string, params["voice"], language_code, output_file_str)
|
||||
generate_response = send_generate_request(
|
||||
string, params["voice"], language_code, output_file_str
|
||||
)
|
||||
# Check if lock is already acquired
|
||||
if process_lock.locked():
|
||||
print("[CoquiTTS Model] \033[91mWarning\033[0m Audio generation is already in progress. Please wait.")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mWarning\033[0m Audio generation is already in progress. Please wait."
|
||||
)
|
||||
return
|
||||
if generate_response.get("status") == "generate-success":
|
||||
# Handle Gradio and playback
|
||||
autoplay = 'autoplay' if params['autoplay'] else ''
|
||||
autoplay = "autoplay" if params["autoplay"] else ""
|
||||
return f'<audio src="file/{output_file_str}?{int(time.time())}" controls {autoplay}></audio>'
|
||||
else:
|
||||
# Handle the case where audio generation was not successful
|
||||
return f"Audio generation failed. Status: {generate_response.get('status')}"
|
||||
return f"[{params['branding']}Server] Audio generation failed. Status: {generate_response.get('status')}"
|
||||
|
||||
#STANDARD VOICE - Generate TTS Function
|
||||
|
||||
# STANDARD VOICE - Generate TTS Function
|
||||
def output_modifier(string, state):
|
||||
if not params['activate']:
|
||||
if not params["activate"]:
|
||||
return string
|
||||
original_string = string
|
||||
cleaned_string = before_audio_generation(string, params)
|
||||
@@ -323,50 +398,63 @@ def output_modifier(string, state):
|
||||
return
|
||||
string = cleaned_string
|
||||
# Setup the output file
|
||||
output_file = Path(f'{params["output_folder_wav"]}/{state["character_menu"]}_{int(time.time())}.wav')
|
||||
output_file = Path(
|
||||
f'{params["output_folder_wav"]}/{state["character_menu"]}_{int(time.time())}.wav'
|
||||
)
|
||||
# Generate the audio and handle the response
|
||||
language_code = languages.get(params["language"])
|
||||
# Convert the WindowsPath object to a string before using it in JSON payload
|
||||
output_file_str = output_file.as_posix()
|
||||
|
||||
# Lock before making the generate request
|
||||
# Lock before making the generate request
|
||||
with process_lock:
|
||||
generate_response = send_generate_request(string, params["voice"], language_code, output_file_str)
|
||||
|
||||
generate_response = send_generate_request(
|
||||
string, params["voice"], language_code, output_file_str
|
||||
)
|
||||
|
||||
# Check if lock is already acquired
|
||||
if process_lock.locked():
|
||||
print("[CoquiTTS Model] \033[91mWarning\033[0m Audio generation is already in progress. Please wait.")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mWarning\033[0m Audio generation is already in progress. Please wait."
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
if generate_response.get("status") == "generate-success":
|
||||
audio_path = generate_response.get("data", {}).get("audio_path")
|
||||
if audio_path:
|
||||
# Handle Gradio and playback
|
||||
autoplay = 'autoplay' if params['autoplay'] else ''
|
||||
autoplay = "autoplay" if params["autoplay"] else ""
|
||||
string = f'<audio src="file/{audio_path}" controls {autoplay}></audio>'
|
||||
|
||||
if params['show_text']:
|
||||
string += f'\n\n{original_string}'
|
||||
|
||||
if params["show_text"]:
|
||||
string += f"\n\n{original_string}"
|
||||
shared.processing_message = "*Is typing...*"
|
||||
|
||||
|
||||
return string
|
||||
else:
|
||||
print("No audio path in the response.")
|
||||
print(
|
||||
f"[{params['branding']}Server] \033[91mWarning\033[0m No audio path in the response."
|
||||
)
|
||||
else:
|
||||
print("[CoquiTTS Server] \033[91mWarning\033[0m Audio generation failed. Status:", generate_response.get("message"))
|
||||
|
||||
print(
|
||||
f"[{params['branding']}Server] \033[91mWarning\033[0m Audio generation failed. Status:",
|
||||
generate_response.get("message"),
|
||||
)
|
||||
|
||||
|
||||
def send_generate_request(text, voice, language, output_file):
|
||||
url = f"{base_url}/api/generate"
|
||||
payload = {
|
||||
"text": text,
|
||||
"voice": voice,
|
||||
"language": language,
|
||||
"output_file": output_file
|
||||
"output_file": output_file,
|
||||
}
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url, json=payload, headers=headers)
|
||||
return response.json()
|
||||
|
||||
|
||||
#############################################################
|
||||
#### TTS STRING CLEANING & PROCESSING PRE SENDING TO TTS ####
|
||||
#############################################################
|
||||
@@ -375,12 +463,13 @@ def preprocess(raw_input):
|
||||
# raw_input = raw_input.strip("\"")
|
||||
return raw_input
|
||||
|
||||
|
||||
def new_split_into_sentences(self, text):
|
||||
sentences = self.seg.segment(text)
|
||||
if params['remove_trailing_dots']:
|
||||
if params["remove_trailing_dots"]:
|
||||
sentences_without_dots = []
|
||||
for sentence in sentences:
|
||||
if sentence.endswith('.') and not sentence.endswith('...'):
|
||||
if sentence.endswith(".") and not sentence.endswith("..."):
|
||||
sentence = sentence[:-1]
|
||||
|
||||
sentences_without_dots.append(sentence)
|
||||
@@ -389,104 +478,182 @@ def new_split_into_sentences(self, text):
|
||||
else:
|
||||
return sentences
|
||||
|
||||
|
||||
Synthesizer.split_into_sentences = new_split_into_sentences
|
||||
|
||||
#TTS STRING CLEANING - Clean String before TTS generation (Called from voice_preview and output_modifer)
|
||||
|
||||
# TTS STRING CLEANING - Clean String before TTS generation (Called from voice_preview and output_modifer)
|
||||
def before_audio_generation(string, params):
|
||||
#Check Model is loaded into cuda or cpu and error if not
|
||||
# Check Model is loaded into cuda or cpu and error if not
|
||||
if not params["model_loaded"]:
|
||||
print("[CoquiTTS Model] \033[91mWarning\033[0m Model is still loading, please wait before trying to generate TTS")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mWarning\033[0m Model is still loading, please wait before trying to generate TTS"
|
||||
)
|
||||
return
|
||||
string = html.unescape(string) or random_sentence()
|
||||
# Replace double quotes with single, asterisks, carriage returns, and line feeds
|
||||
string = string.replace('"', "'").replace(".'", "'.").replace('*', '').replace('\r', '').replace('\n', '')
|
||||
if string == '':
|
||||
return '*Empty string*'
|
||||
string = (
|
||||
string.replace('"', "'")
|
||||
.replace(".'", "'.")
|
||||
.replace("*", "")
|
||||
.replace("\r", "")
|
||||
.replace("\n", "")
|
||||
)
|
||||
if string == "":
|
||||
return "*Empty string*"
|
||||
return string
|
||||
|
||||
|
||||
################################
|
||||
#### SUBPORCESS TERMINATION ####
|
||||
################################
|
||||
#Register the termination code to be executed at exit
|
||||
# Register the termination code to be executed at exit
|
||||
atexit.register(lambda: process.terminate() if process.poll() is None else None)
|
||||
|
||||
|
||||
######################
|
||||
#### GRADIO STUFF ####
|
||||
######################
|
||||
def state_modifier(state):
|
||||
if not params['activate']:
|
||||
if not params["activate"]:
|
||||
return state
|
||||
|
||||
state['stream'] = False
|
||||
state["stream"] = False
|
||||
return state
|
||||
|
||||
|
||||
def input_modifier(string, state):
|
||||
if not params['activate']:
|
||||
if not params["activate"]:
|
||||
return string
|
||||
|
||||
shared.processing_message = "*Is recording a voice message...*"
|
||||
return string
|
||||
|
||||
|
||||
def custom_css():
|
||||
path_to_css = Path(f"{this_dir}/style.css")
|
||||
return open(path_to_css, 'r').read()
|
||||
return open(path_to_css, "r").read()
|
||||
|
||||
|
||||
def ui():
|
||||
with gr.Accordion("Coqui TTS (XTTSv2)"):
|
||||
with gr.Accordion(params["branding"] + " TTS (XTTSv2)"):
|
||||
with gr.Row():
|
||||
activate = gr.Checkbox(value=params['activate'], label='Activate TTS')
|
||||
autoplay = gr.Checkbox(value=params['autoplay'], label='Play TTS automatically')
|
||||
activate = gr.Checkbox(value=params["activate"], label="Activate TTS")
|
||||
autoplay = gr.Checkbox(
|
||||
value=params["autoplay"], label="Play TTS automatically"
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
show_text = gr.Checkbox(value=params['show_text'], label='Show message text under audio player')
|
||||
remove_trailing_dots = gr.Checkbox(value=params['remove_trailing_dots'], label='Remove trailing "." from text segments before generation')
|
||||
|
||||
show_text = gr.Checkbox(
|
||||
value=params["show_text"], label="Show message text under audio player"
|
||||
)
|
||||
remove_trailing_dots = gr.Checkbox(
|
||||
value=params["remove_trailing_dots"],
|
||||
label='Remove trailing "." from text segments before generation',
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
low_vram = gr.Checkbox(value=params['low_vram'], label='Low VRAM mode (Read NOTE)')
|
||||
deepspeed_checkbox = gr.Checkbox(value=params['deepspeed_activate'], label='Activate DeepSpeed (Read NOTE)', visible=deepspeed_installed)
|
||||
|
||||
low_vram = gr.Checkbox(
|
||||
value=params["low_vram"], label="Low VRAM mode (Read NOTE)"
|
||||
)
|
||||
deepspeed_checkbox = gr.Checkbox(
|
||||
value=params["deepspeed_activate"],
|
||||
label="Activate DeepSpeed (Read NOTE)",
|
||||
visible=deepspeed_installed,
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
tts_radio_buttons = gr.Radio(
|
||||
choices=["API TTS", "API Local", "XTTSv2 Local"],
|
||||
label="Select TTS Generation Method (Read NOTE)",
|
||||
value=gr_modelchoice # Set the default value
|
||||
choices=["API TTS", "API Local", "XTTSv2 Local"],
|
||||
label="Select TTS Generation Method (Read NOTE)",
|
||||
value=gr_modelchoice, # Set the default value
|
||||
)
|
||||
explanation_text = gr.HTML(f"<p>NOTE: Switching Model Type, Low VRAM & DeepSpeed takes 15 seconds. Each TTS generation method has a slightly different sound. DeepSpeed checkbox is only visible if DeepSpeed is present. Readme & Settings: <a href='http://{params['ip_address']}:{params['port_number']}'>http://{params['ip_address']}:{params['port_number']}</a>")
|
||||
|
||||
explanation_text = gr.HTML(
|
||||
f"<p>NOTE: Switching Model Type, Low VRAM & DeepSpeed takes 15 seconds. Each TTS generation method has a slightly different sound. DeepSpeed checkbox is only visible if DeepSpeed is present. Readme & Settings: <a href='http://{params['ip_address']}:{params['port_number']}'>http://{params['ip_address']}:{params['port_number']}</a>"
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
with gr.Row():
|
||||
voice = gr.Dropdown(get_available_voices(), label="Voice wav", value=params["voice"])
|
||||
create_refresh_button(voice, lambda: None, lambda: {'choices': get_available_voices(), 'value': params["voice"]}, 'refresh-button')
|
||||
voice = gr.Dropdown(
|
||||
get_available_voices(), label="Voice wav", value=params["voice"]
|
||||
)
|
||||
create_refresh_button(
|
||||
voice,
|
||||
lambda: None,
|
||||
lambda: {
|
||||
"choices": get_available_voices(),
|
||||
"value": params["voice"],
|
||||
},
|
||||
"refresh-button",
|
||||
)
|
||||
|
||||
language = gr.Dropdown(languages.keys(), label="Language", value=params["language"])
|
||||
language = gr.Dropdown(
|
||||
languages.keys(), label="Language", value=params["language"]
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
preview_text = gr.Text(show_label=False, placeholder="Preview text", elem_id="silero_preview_text")
|
||||
preview_text = gr.Text(
|
||||
show_label=False,
|
||||
placeholder="Preview text",
|
||||
elem_id="silero_preview_text",
|
||||
)
|
||||
preview_play = gr.Button("Preview")
|
||||
preview_audio = gr.HTML(visible=False)
|
||||
|
||||
with gr.Row():
|
||||
convert = gr.Button('Permanently replace audios with the message texts')
|
||||
convert_cancel = gr.Button('Cancel', visible=False)
|
||||
convert_confirm = gr.Button('Confirm (cannot be undone)', variant="stop", visible=False)
|
||||
convert = gr.Button("Permanently replace audios with the message texts")
|
||||
convert_cancel = gr.Button("Cancel", visible=False)
|
||||
convert_confirm = gr.Button(
|
||||
"Confirm (cannot be undone)", variant="stop", visible=False
|
||||
)
|
||||
|
||||
# Convert history with confirmation
|
||||
convert_arr = [convert_confirm, convert, convert_cancel]
|
||||
convert.click(lambda: [gr.update(visible=True), gr.update(visible=False), gr.update(visible=True)], None, convert_arr)
|
||||
convert.click(
|
||||
lambda: [
|
||||
gr.update(visible=True),
|
||||
gr.update(visible=False),
|
||||
gr.update(visible=True),
|
||||
],
|
||||
None,
|
||||
convert_arr,
|
||||
)
|
||||
convert_confirm.click(
|
||||
lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)], None, convert_arr).then(
|
||||
remove_tts_from_history, gradio('history'), gradio('history')).then(
|
||||
chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
|
||||
chat.redraw_html, gradio(ui_chat.reload_arr), gradio('display'))
|
||||
lambda: [
|
||||
gr.update(visible=False),
|
||||
gr.update(visible=True),
|
||||
gr.update(visible=False),
|
||||
],
|
||||
None,
|
||||
convert_arr,
|
||||
).then(remove_tts_from_history, gradio("history"), gradio("history")).then(
|
||||
chat.save_history,
|
||||
gradio("history", "unique_id", "character_menu", "mode"),
|
||||
None,
|
||||
).then(
|
||||
chat.redraw_html, gradio(ui_chat.reload_arr), gradio("display")
|
||||
)
|
||||
|
||||
convert_cancel.click(lambda: [gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)], None, convert_arr)
|
||||
convert_cancel.click(
|
||||
lambda: [
|
||||
gr.update(visible=False),
|
||||
gr.update(visible=True),
|
||||
gr.update(visible=False),
|
||||
],
|
||||
None,
|
||||
convert_arr,
|
||||
)
|
||||
|
||||
# Toggle message text in history
|
||||
show_text.change(
|
||||
lambda x: params.update({"show_text": x}), show_text, None).then(
|
||||
toggle_text_in_history, gradio('history'), gradio('history')).then(
|
||||
chat.save_history, gradio('history', 'unique_id', 'character_menu', 'mode'), None).then(
|
||||
chat.redraw_html, gradio(ui_chat.reload_arr), gradio('display'))
|
||||
show_text.change(lambda x: params.update({"show_text": x}), show_text, None).then(
|
||||
toggle_text_in_history, gradio("history"), gradio("history")
|
||||
).then(
|
||||
chat.save_history,
|
||||
gradio("history", "unique_id", "character_menu", "mode"),
|
||||
None,
|
||||
).then(
|
||||
chat.redraw_html, gradio(ui_chat.reload_arr), gradio("display")
|
||||
)
|
||||
|
||||
# Event functions to update the parameters in the backend
|
||||
activate.change(lambda x: params.update({"activate": x}), activate, None)
|
||||
@@ -495,7 +662,9 @@ def ui():
|
||||
low_vram.change(lambda x: send_lowvram_request(x), low_vram, None)
|
||||
tts_radio_buttons.change(send_reload_request, tts_radio_buttons, None)
|
||||
deepspeed_checkbox.change(send_deepspeed_request, deepspeed_checkbox, None)
|
||||
remove_trailing_dots.change(lambda x: params.update({"remove_trailing_dots": x}), remove_trailing_dots, None)
|
||||
remove_trailing_dots.change(
|
||||
lambda x: params.update({"remove_trailing_dots": x}), remove_trailing_dots, None
|
||||
)
|
||||
voice.change(lambda x: params.update({"voice": x}), voice, None)
|
||||
language.change(lambda x: params.update({"language": x}), language, None)
|
||||
|
||||
|
||||
+295
-161
@@ -11,11 +11,75 @@ from TTS.tts.models.xtts import Xtts
|
||||
##########################
|
||||
#### Webserver Imports####
|
||||
##########################
|
||||
from fastapi import FastAPI, Form, Request, HTTPException, BackgroundTasks, Response, Depends
|
||||
from fastapi import (
|
||||
FastAPI,
|
||||
Form,
|
||||
Request,
|
||||
HTTPException,
|
||||
BackgroundTasks,
|
||||
Response,
|
||||
Depends,
|
||||
)
|
||||
from fastapi.responses import JSONResponse, HTMLResponse, RedirectResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
|
||||
###########################
|
||||
#### STARTUP VARIABLES ####
|
||||
###########################
|
||||
# STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
# STARTUP VARIABLE - Set "device" to cuda if exists, otherwise cpu
|
||||
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)
|
||||
|
||||
|
||||
##############################################################
|
||||
#### LOAD PARAMS FROM CONFIG.JSON - REQUIRED FOR BRANDING ####
|
||||
##############################################################
|
||||
|
||||
|
||||
# Load config file and get settings
|
||||
def load_config(file_path):
|
||||
with open(file_path, "r") as configfile_path:
|
||||
configfile_data = json.load(configfile_path)
|
||||
return configfile_data
|
||||
|
||||
|
||||
# Define the path to the config.json file
|
||||
configfile_path = this_dir / "config.json"
|
||||
|
||||
# Load config.json and assign it to a different variable (config_data)
|
||||
params = load_config(configfile_path)
|
||||
|
||||
# Define the path to the JSON file
|
||||
config_file_path = this_dir / "modeldownload.json"
|
||||
|
||||
#############################################
|
||||
#### LOAD PARAMS FROM MODELDOWNLOAD.JSON ####
|
||||
############################################
|
||||
# This is used only in the instance that someone has changed their model path
|
||||
# Define the path to the JSON file
|
||||
modeldownload_config_file_path = this_dir / "modeldownload.json"
|
||||
|
||||
# Check if the JSON file exists
|
||||
if modeldownload_config_file_path.exists():
|
||||
with open(modeldownload_config_file_path, "r") as modeldownload_config_file:
|
||||
modeldownload_settings = json.load(modeldownload_config_file)
|
||||
|
||||
# Extract settings from the loaded JSON
|
||||
modeldownload_base_path = Path(modeldownload_settings.get("base_path", ""))
|
||||
modeldownload_model_path = Path(modeldownload_settings.get("model_path", ""))
|
||||
else:
|
||||
# Default settings if the JSON file doesn't exist or is empty
|
||||
print(
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m modeldownload.config is missing so please re-download it and save it in the coquii_tts main folder."
|
||||
)
|
||||
|
||||
|
||||
########################
|
||||
#### STARTUP CHECKS ####
|
||||
########################
|
||||
@@ -24,151 +88,160 @@ try:
|
||||
from TTS.utils.synthesizer import Synthesizer
|
||||
except ModuleNotFoundError:
|
||||
logger.error(
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Could not find the TTS module. Make sure to install the requirements for the coqui_tts extension."
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Linux / Mac:\npip install -r extensions/coqui_tts/requirements.txt\n"
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m Windows:\npip install -r extensions\\coqui_tts\\requirements.txt\n"
|
||||
"[CoquiTTS Startup] \033[91mWarning\033[0m If you used the one-click installer, paste the command above in the terminal window launched after running the \"cmd_\" script. On Windows, that's \"cmd_windows.bat\"."
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Could not find the TTS module. Make sure to install the requirements for the alltalk_tts extension."
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Linux / Mac:\npip install -r extensions/alltalk_tts/requirements.txt\n"
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m Windows:\npip install -r extensions\\alltalk_tts\\requirements.txt\n"
|
||||
f"[{params['branding']}Startup] \033[91mWarning\033[0m If you used the one-click installer, paste the command above in the terminal window launched after running the cmd_ script. On Windows, that's cmd_windows.bat."
|
||||
)
|
||||
raise
|
||||
|
||||
#DEEPSPEED Import - Check for DeepSpeed and import it if it exists
|
||||
# DEEPSPEED Import - Check for DeepSpeed and import it if it exists
|
||||
try:
|
||||
import deepspeed
|
||||
|
||||
deepspeed_installed = True
|
||||
print("[CoquiTTS Startup] DeepSpeed \033[93mDetected\033[0m")
|
||||
print("[CoquiTTS Startup] Activate DeepSpeed in Coqui settings")
|
||||
print(f"[{params['branding']}Startup] DeepSpeed \033[93mDetected\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Startup] Activate DeepSpeed in "
|
||||
+ params["branding"]
|
||||
+ " settings"
|
||||
)
|
||||
except ImportError:
|
||||
deepspeed_installed = False
|
||||
print("[CoquiTTS Startup] DeepSpeed \033[93mNot Detected\033[0m. See https://github.com/microsoft/DeepSpeed")
|
||||
print(
|
||||
f"[{params['branding']}Startup] DeepSpeed \033[93mNot Detected\033[0m. See https://github.com/microsoft/DeepSpeed"
|
||||
)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def startup_shutdown(no_actual_value_it_demanded_something_be_here):
|
||||
await setup()
|
||||
yield
|
||||
yield
|
||||
# Shutdown logic
|
||||
|
||||
###########################
|
||||
#### STARTUP VARIABLES ####
|
||||
###########################
|
||||
#STARTUP VARIABLE - Set "device" to cuda if exists, otherwise cpu
|
||||
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||
#STARTUP VARIABLE - Create "this_dir" variable as the current script directory
|
||||
this_dir = Path(__file__).parent.resolve()
|
||||
#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)
|
||||
|
||||
# Create FastAPI app with lifespan
|
||||
app = FastAPI(lifespan=startup_shutdown)
|
||||
|
||||
######################################
|
||||
#### LOAD PARAMS FROM CONFIG.JSON ####
|
||||
######################################
|
||||
def load_config(file_path):
|
||||
with open(file_path, 'r') as config_file:
|
||||
config = json.load(config_file)
|
||||
return config
|
||||
|
||||
config_file_path = (this_dir / 'config.json')
|
||||
params = load_config(config_file_path)
|
||||
|
||||
#############################################
|
||||
#### LOAD PARAMS FROM MODELDOWNLOAD.JSON ####
|
||||
############################################
|
||||
#This is used only in the instance that someone has changed their model path
|
||||
# Define the path to the JSON file
|
||||
modeldownload_config_file_path = this_dir / 'modeldownload.json'
|
||||
|
||||
#Check if the JSON file exists
|
||||
if modeldownload_config_file_path.exists():
|
||||
with open(modeldownload_config_file_path, 'r') as modeldownload_config_file:
|
||||
modeldownload_settings = json.load(modeldownload_config_file)
|
||||
|
||||
#Extract settings from the loaded JSON
|
||||
modeldownload_base_path = Path(modeldownload_settings.get("base_path", ""))
|
||||
modeldownload_model_path = Path(modeldownload_settings.get("model_path", ""))
|
||||
else:
|
||||
#Default settings if the JSON file doesn't exist or is empty
|
||||
print("[CoquiTTS Startup] \033[91mWarning\033[0m modeldownload.config is missing so please re-download it and save it in the coquii_tts main folder.")
|
||||
|
||||
#####################################
|
||||
#### MODEL LOADING AND UNLOADING ####
|
||||
#####################################
|
||||
#MODEL LOADERS Picker For API TTS, API Local, XTTSv2 Local
|
||||
# MODEL LOADERS Picker For API TTS, API Local, XTTSv2 Local
|
||||
async def setup():
|
||||
global device
|
||||
#Set a timer to calculate load times
|
||||
# Set a timer to calculate load times
|
||||
generate_start_time = time.time() # Record the start time of loading the model
|
||||
#Start loading the correct model as set by "tts_method_api_tts", "tts_method_api_local" or "tts_method_xtts_local" being True/False
|
||||
# Start loading the correct model as set by "tts_method_api_tts", "tts_method_api_local" or "tts_method_xtts_local" being True/False
|
||||
if params["tts_method_api_tts"]:
|
||||
print(f"[CoquiTTS Model] \033[94mAPI TTS Loading\033[0m {params['model_name']} \033[94minto\033[93m", device, "\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mAPI TTS Loading\033[0m {params['model_name']} \033[94minto\033[93m",
|
||||
device,
|
||||
"\033[0m",
|
||||
)
|
||||
model = await api_load_model()
|
||||
elif params["tts_method_api_local"]:
|
||||
print(f"[CoquiTTS Model] \033[94mAPI Local Loading\033[0m {modeldownload_model_path} \033[94minto\033[93m", device, "\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mAPI Local Loading\033[0m {modeldownload_model_path} \033[94minto\033[93m",
|
||||
device,
|
||||
"\033[0m",
|
||||
)
|
||||
model = await api_manual_load_model()
|
||||
elif params["tts_method_xtts_local"]:
|
||||
print(f"[CoquiTTS Model] \033[94mXTTSv2 Local Loading\033[0m {modeldownload_model_path} \033[94minto\033[93m", device, "\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mXTTSv2 Local Loading\033[0m {modeldownload_model_path} \033[94minto\033[93m",
|
||||
device,
|
||||
"\033[0m",
|
||||
)
|
||||
model = await xtts_manual_load_model()
|
||||
#Create an end timer for calculating load times
|
||||
# Create an end timer for calculating load times
|
||||
generate_end_time = time.time()
|
||||
#Calculate start time minus end time
|
||||
# Calculate start time minus end time
|
||||
generate_elapsed_time = generate_end_time - generate_start_time
|
||||
#Print out the result of the load time
|
||||
print(f"[CoquiTTS Model] \033[94mModel Loaded in \033[93m{generate_elapsed_time:.2f} seconds.\033[0m")
|
||||
#Set "model_loaded" to true
|
||||
# Print out the result of the load time
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mModel Loaded in \033[93m{generate_elapsed_time:.2f} seconds.\033[0m"
|
||||
)
|
||||
# Set "model_loaded" to true
|
||||
params["model_loaded"] = True
|
||||
#Set the output path for wav files
|
||||
# Set the output path for wav files
|
||||
Path(f'{params["output_folder_wav"]}outputs/').mkdir(parents=True, exist_ok=True)
|
||||
|
||||
#MODEL LOADER For "API TTS"
|
||||
|
||||
# MODEL LOADER For "API TTS"
|
||||
async def api_load_model():
|
||||
global model
|
||||
model = TTS(params["model_name"]).to(device)
|
||||
return model
|
||||
|
||||
#MODEL LOADER For "API Local"
|
||||
|
||||
# MODEL LOADER For "API Local"
|
||||
async def api_manual_load_model():
|
||||
global model
|
||||
#check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
||||
# check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
||||
if str(modeldownload_base_path) == "models":
|
||||
model = TTS(model_path=this_dir / 'models' / modeldownload_model_path,config_path=this_dir / 'models' / modeldownload_model_path / 'config.json').to(device)
|
||||
model = TTS(
|
||||
model_path=this_dir / "models" / modeldownload_model_path,
|
||||
config_path=this_dir / "models" / modeldownload_model_path / "config.json",
|
||||
).to(device)
|
||||
else:
|
||||
print("[CoquiTTS Model] \033[94mInfo\033[0m Loading your custom model set in \033[93mmodeldownload.json\033[0m:", modeldownload_base_path / modeldownload_model_path)
|
||||
model = TTS(model_path=modeldownload_base_path / modeldownload_model_path,config_path=modeldownload_base_path / modeldownload_model_path / 'config.json').to(device)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mInfo\033[0m Loading your custom model set in \033[93mmodeldownload.json\033[0m:",
|
||||
modeldownload_base_path / modeldownload_model_path,
|
||||
)
|
||||
model = TTS(
|
||||
model_path=modeldownload_base_path / modeldownload_model_path,
|
||||
config_path=modeldownload_base_path
|
||||
/ modeldownload_model_path
|
||||
/ "config.json",
|
||||
).to(device)
|
||||
return model
|
||||
|
||||
#MODEL LOADER For "XTTSv2 Local"
|
||||
|
||||
# MODEL LOADER For "XTTSv2 Local"
|
||||
async def xtts_manual_load_model():
|
||||
global model
|
||||
config = XttsConfig()
|
||||
#check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
||||
# check to see if a custom path has been set in modeldownload.json and use that path to load the model if so
|
||||
if str(modeldownload_base_path) == "models":
|
||||
config_path = this_dir / 'models' / modeldownload_model_path / 'config.json'
|
||||
checkpoint_dir = this_dir / 'models' / modeldownload_model_path
|
||||
config_path = this_dir / "models" / modeldownload_model_path / "config.json"
|
||||
checkpoint_dir = this_dir / "models" / modeldownload_model_path
|
||||
else:
|
||||
print("[CoquiTTS Model] \033[94mInfo\033[0m Loading your custom model set in \033[93mmodeldownload.json\033[0m:", modeldownload_base_path / modeldownload_model_path)
|
||||
config_path = modeldownload_base_path / modeldownload_model_path / 'config.json'
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mInfo\033[0m Loading your custom model set in \033[93mmodeldownload.json\033[0m:",
|
||||
modeldownload_base_path / modeldownload_model_path,
|
||||
)
|
||||
config_path = modeldownload_base_path / modeldownload_model_path / "config.json"
|
||||
checkpoint_dir = modeldownload_base_path / modeldownload_model_path
|
||||
config.load_json(str(config_path))
|
||||
model = Xtts.init_from_config(config)
|
||||
model.load_checkpoint(config, checkpoint_dir=str(checkpoint_dir), use_deepspeed=params['deepspeed_activate'])
|
||||
model.load_checkpoint(
|
||||
config,
|
||||
checkpoint_dir=str(checkpoint_dir),
|
||||
use_deepspeed=params["deepspeed_activate"],
|
||||
)
|
||||
model.cuda()
|
||||
model.to(device)
|
||||
return model
|
||||
|
||||
#MODEL UNLOADER
|
||||
|
||||
# MODEL UNLOADER
|
||||
async def unload_model(model):
|
||||
print("[CoquiTTS Model] \033[94mUnloading model \033[0m")
|
||||
print(f"[{params['branding']}Model] \033[94mUnloading model \033[0m")
|
||||
del model
|
||||
torch.cuda.empty_cache()
|
||||
params["model_loaded"] = False
|
||||
return None
|
||||
|
||||
#MODEL - Swap model based on Gradio selection API TTS, API Local, XTTSv2 Local
|
||||
|
||||
# MODEL - Swap model based on Gradio selection API TTS, API Local, XTTSv2 Local
|
||||
async def handle_tts_method_change(tts_method):
|
||||
global model
|
||||
#Update the params dictionary based on the selected radio button
|
||||
print("[CoquiTTS Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m")
|
||||
#Set other parameters to False
|
||||
# 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"
|
||||
)
|
||||
# Set other parameters to False
|
||||
if tts_method == "API TTS":
|
||||
params["tts_method_api_local"] = False
|
||||
params["tts_method_xtts_local"] = False
|
||||
@@ -184,39 +257,41 @@ async def handle_tts_method_change(tts_method):
|
||||
params["tts_method_api_local"] = False
|
||||
params["tts_method_xtts_local"] = True
|
||||
|
||||
#Unload the current model
|
||||
# Unload the current model
|
||||
model = await unload_model(model)
|
||||
|
||||
#Load the correct model based on the updated params
|
||||
# Load the correct model based on the updated params
|
||||
await setup()
|
||||
|
||||
#MODEL WEBSERVER- API Swap Between Models
|
||||
|
||||
# MODEL WEBSERVER- API Swap Between Models
|
||||
@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"]:
|
||||
return {"status": "error", "message": "Invalid TTS method specified"}
|
||||
return {"status": "error", "message": "Invalid TTS method specified"}
|
||||
await handle_tts_method_change(tts_method)
|
||||
return Response(
|
||||
content=json.dumps({"status": "model-success"}),
|
||||
media_type="application/json"
|
||||
content=json.dumps({"status": "model-success"}), media_type="application/json"
|
||||
)
|
||||
|
||||
|
||||
##################
|
||||
#### LOW VRAM ####
|
||||
##################
|
||||
#LOW VRAM - MODEL MOVER VRAM(cuda)<>System RAM(cpu) for Low VRAM setting
|
||||
# LOW VRAM - MODEL MOVER VRAM(cuda)<>System RAM(cpu) for Low VRAM setting
|
||||
async def switch_device():
|
||||
global model, device
|
||||
if device == "cuda":
|
||||
device = "cpu"
|
||||
model.to(device)
|
||||
model.to(device)
|
||||
torch.cuda.empty_cache()
|
||||
else:
|
||||
else:
|
||||
device == "cpu"
|
||||
device = "cuda"
|
||||
model.to(device)
|
||||
|
||||
|
||||
@app.post("/api/lowvramsetting")
|
||||
async def set_low_vram(request: Request, new_low_vram_value: bool):
|
||||
global device
|
||||
@@ -225,38 +300,64 @@ async def set_low_vram(request: Request, new_low_vram_value: bool):
|
||||
raise ValueError("Missing 'low_vram' parameter")
|
||||
if params["low_vram"] == new_low_vram_value:
|
||||
return Response(
|
||||
content=json.dumps({"status": "success", "message": f"[CoquiTTS Model] LowVRAM is already {'enabled' if new_low_vram_value else 'disabled'}."}))
|
||||
content=json.dumps(
|
||||
{
|
||||
"status": "success",
|
||||
"message": f"[{params['branding']}Model] LowVRAM is already {'enabled' if new_low_vram_value else 'disabled'}.",
|
||||
}
|
||||
)
|
||||
)
|
||||
params["low_vram"] = new_low_vram_value
|
||||
if params["low_vram"]:
|
||||
await unload_model(model)
|
||||
device = "cpu"
|
||||
print("[CoquiTTS Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m")
|
||||
print("[CoquiTTS Model] \033[94mLowVRAM Enabled.\033[0m Model will move between \033[93mVRAM(cuda) <> System RAM(cpu)\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mLowVRAM Enabled.\033[0m Model will move between \033[93mVRAM(cuda) <> System RAM(cpu)\033[0m"
|
||||
)
|
||||
await setup()
|
||||
else:
|
||||
await unload_model(model)
|
||||
device = "cuda"
|
||||
print("[CoquiTTS Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m")
|
||||
print("[CoquiTTS Model] \033[94mLowVRAM Disabled.\033[0m Model will stay in \033[93mVRAM(cuda)\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mLowVRAM Disabled.\033[0m Model will stay in \033[93mVRAM(cuda)\033[0m"
|
||||
)
|
||||
await setup()
|
||||
return Response(content=json.dumps({"status": "lowvram-success"}))
|
||||
except Exception as e:
|
||||
return Response(content=json.dumps({"status": "error", "message": str(e)}))
|
||||
|
||||
|
||||
###################
|
||||
#### DeepSpeed ####
|
||||
###################
|
||||
#DEEPSPEED - Reload the model when DeepSpeed checkbox is enabled/disabled
|
||||
# DEEPSPEED - Reload the model when DeepSpeed checkbox is enabled/disabled
|
||||
async def handle_deepspeed_change(value):
|
||||
global model
|
||||
if value:
|
||||
# DeepSpeed enabled
|
||||
print("[CoquiTTS Model] \033[93mDeepSpeed Activating\033[0m")
|
||||
print("[CoquiTTS Model] \033[94mChanging model \033[92m(DeepSpeed can take 30 seconds to activate)\033[0m")
|
||||
print("[CoquiTTS Model] \033[91mInformation\033[0m If you have not set CUDA_HOME path, DeepSpeed may fail to load/activate")
|
||||
print("[CoquiTTS Model] \033[91mInformation\033[0m DeepSpeed needs to find nvcc from the CUDA Toolkit. Please check your CUDA_HOME path is")
|
||||
print("[CoquiTTS Model] \033[91mInformation\033[0m pointing to the correct location and use 'set CUDA_HOME=putyoutpathhere' (Windows) or")
|
||||
print("[CoquiTTS Model] \033[91mInformation\033[0m 'export CUDA_HOME=putyoutpathhere' (Linux) within your Python Environment")
|
||||
print(f"[{params['branding']}Model] \033[93mDeepSpeed Activating\033[0m")
|
||||
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mChanging model \033[92m(DeepSpeed can take 30 seconds to activate)\033[0m"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mInformation\033[0m If you have not set CUDA_HOME path, DeepSpeed may fail to load/activate"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mInformation\033[0m DeepSpeed needs to find nvcc from the CUDA Toolkit. Please check your CUDA_HOME path is"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mInformation\033[0m pointing to the correct location and use 'set CUDA_HOME=putyoutpathhere' (Windows) or"
|
||||
)
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[91mInformation\033[0m 'export CUDA_HOME=putyoutpathhere' (Linux) within your Python Environment"
|
||||
)
|
||||
model = await unload_model(model)
|
||||
params["tts_method_api_tts"] = False
|
||||
params["tts_method_api_local"] = False
|
||||
@@ -265,15 +366,18 @@ async def handle_deepspeed_change(value):
|
||||
await setup()
|
||||
else:
|
||||
# DeepSpeed disabled
|
||||
print("[CoquiTTS Model] \033[93mDeepSpeed De-Activating\033[0m")
|
||||
print("[CoquiTTS Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m")
|
||||
params["deepspeed_activate"] = False
|
||||
print(f"[{params['branding']}Model] \033[93mDeepSpeed De-Activating\033[0m")
|
||||
print(
|
||||
f"[{params['branding']}Model] \033[94mChanging model \033[92m(Please wait 15 seconds)\033[0m"
|
||||
)
|
||||
params["deepspeed_activate"] = False
|
||||
model = await unload_model(model)
|
||||
await setup()
|
||||
|
||||
return value # Return new checkbox value
|
||||
return value # Return new checkbox value
|
||||
|
||||
#DEEPSPEED WEBSERVER- API Enable/Disable DeepSpeed
|
||||
|
||||
# DEEPSPEED WEBSERVER- API Enable/Disable DeepSpeed
|
||||
@app.post("/api/deepspeed")
|
||||
async def deepspeed(request: Request, new_deepspeed_value: bool):
|
||||
try:
|
||||
@@ -281,55 +385,67 @@ async def deepspeed(request: Request, new_deepspeed_value: bool):
|
||||
raise ValueError("Missing 'deepspeed' parameter")
|
||||
if params["deepspeed_activate"] == new_deepspeed_value:
|
||||
return Response(
|
||||
content=json.dumps({"status": "success", "message": f"DeepSpeed is already {'enabled' if new_deepspeed_value else 'disabled'}."}))
|
||||
content=json.dumps(
|
||||
{
|
||||
"status": "success",
|
||||
"message": f"DeepSpeed is already {'enabled' if new_deepspeed_value else 'disabled'}.",
|
||||
}
|
||||
)
|
||||
)
|
||||
params["deepspeed_activate"] = new_deepspeed_value
|
||||
await handle_deepspeed_change(params["deepspeed_activate"])
|
||||
return Response(content=json.dumps({"status": "deepspeed-success"}))
|
||||
except Exception as e:
|
||||
return Response(content=json.dumps({"status": "error", "message": str(e)}))
|
||||
|
||||
|
||||
########################
|
||||
#### TTS GENERATION ####
|
||||
########################
|
||||
#TTS VOICE GENERATION METHODS (called from voice_preview and output_modifer)
|
||||
# TTS VOICE GENERATION METHODS (called from voice_preview and output_modifer)
|
||||
async def generate_audio(text, voice, language, output_file):
|
||||
global model
|
||||
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"]:
|
||||
print("[CoquiTTS TTSGen] {}".format(text))
|
||||
gpt_cond_latent, speaker_embedding = model.get_conditioning_latents(audio_path=[f"{this_dir}/voices/{voice}"])
|
||||
# XTTSv2 LOCAL Method
|
||||
if params["tts_method_xtts_local"]:
|
||||
print("[" + params["branding"] + "TTSGen] {}".format(text))
|
||||
gpt_cond_latent, speaker_embedding = model.get_conditioning_latents(
|
||||
audio_path=[f"{this_dir}/voices/{voice}"]
|
||||
)
|
||||
out = model.inference(
|
||||
text,
|
||||
language,
|
||||
gpt_cond_latent=gpt_cond_latent,
|
||||
speaker_embedding=speaker_embedding,
|
||||
temperature=0.7,
|
||||
enable_text_splitting=True
|
||||
text,
|
||||
language,
|
||||
gpt_cond_latent=gpt_cond_latent,
|
||||
speaker_embedding=speaker_embedding,
|
||||
temperature=0.7,
|
||||
enable_text_splitting=True,
|
||||
)
|
||||
torchaudio.save(output_file, torch.tensor(out["wav"]).unsqueeze(0), 24000)
|
||||
#API TTS and API LOCAL Methods
|
||||
# API TTS and API LOCAL Methods
|
||||
elif params["tts_method_api_tts"] or params["tts_method_api_local"]:
|
||||
#Set the correct output path (different from the if statement)
|
||||
print("[CoquiTTS TTSGen] Using API TTS/Local Method")
|
||||
# Set the correct output path (different from the if statement)
|
||||
print("[" + params["branding"] + "TTSGen] Using API TTS/Local Method")
|
||||
model.tts_to_file(
|
||||
text=text,
|
||||
file_path=output_file,
|
||||
speaker_wav=[f"{this_dir}/voices/{voice}"],
|
||||
language=language,
|
||||
)
|
||||
#Print Generation time and settings
|
||||
# Print Generation time and settings
|
||||
generate_end_time = time.time() # Record the end time to generate TTS
|
||||
generate_elapsed_time = generate_end_time - generate_start_time
|
||||
print(f"[CoquiTTS TTSGen] \033[93m{generate_elapsed_time:.2f} seconds. \033[94mLowVRAM: \033[33m{params['low_vram']} \033[94mDeepSpeed: \033[33m{params['deepspeed_activate']}\033[0m")
|
||||
#Move model back to cpu system ram if needed.
|
||||
print(
|
||||
f"[{params['branding']}TTSGen] \033[93m{generate_elapsed_time:.2f} seconds. \033[94mLowVRAM: \033[33m{params['low_vram']} \033[94mDeepSpeed: \033[33m{params['deepspeed_activate']}\033[0m"
|
||||
)
|
||||
# Move model back to cpu system ram if needed.
|
||||
if params["low_vram"] and device == "cuda":
|
||||
await switch_device()
|
||||
return
|
||||
|
||||
#TTS VOICE GENERATION METHODS - generate TTS API
|
||||
|
||||
# TTS VOICE GENERATION METHODS - generate TTS API
|
||||
@app.route("/api/generate", methods=["POST"])
|
||||
async def generate(request: Request):
|
||||
try:
|
||||
@@ -338,35 +454,48 @@ async def generate(request: Request):
|
||||
text = data["text"]
|
||||
voice = data["voice"]
|
||||
language = data["language"]
|
||||
output_file = data["output_file"]
|
||||
output_file = data["output_file"]
|
||||
# Generation logic
|
||||
await generate_audio(text, voice, language, output_file)
|
||||
return JSONResponse(content={"status": "generate-success", "data": {"audio_path": output_file}})
|
||||
await generate_audio(text, voice, language, output_file)
|
||||
return JSONResponse(
|
||||
content={"status": "generate-success", "data": {"audio_path": output_file}}
|
||||
)
|
||||
except Exception as e:
|
||||
return JSONResponse(content={"status": "error", "message": str(e)})
|
||||
|
||||
|
||||
#############################
|
||||
#### JSON CONFIG UPDATER ####
|
||||
#############################
|
||||
|
||||
#Create an instance of Jinja2Templates for rendering HTML templates
|
||||
# Create an instance of Jinja2Templates for rendering HTML templates
|
||||
templates = Jinja2Templates(directory=this_dir / "templates")
|
||||
|
||||
#Create a dependency to get the current JSON data
|
||||
|
||||
# Create a dependency to get the current JSON data
|
||||
def get_json_data():
|
||||
with open(this_dir / 'config.json', "r") as json_file:
|
||||
with open(this_dir / "config.json", "r") as json_file:
|
||||
data = json.load(json_file)
|
||||
return data
|
||||
|
||||
#Define an endpoint function
|
||||
|
||||
# Define an endpoint function
|
||||
@app.get("/settings")
|
||||
async def get_settings(request: Request):
|
||||
# Render the template with the current JSON data
|
||||
return templates.TemplateResponse("generate_form.html", {"request": request, "data": get_json_data(), "modeldownload_model_path": modeldownload_model_path})
|
||||
return templates.TemplateResponse(
|
||||
"generate_form.html",
|
||||
{
|
||||
"request": request,
|
||||
"data": get_json_data(),
|
||||
"modeldownload_model_path": modeldownload_model_path,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@app.post("/update-settings")
|
||||
async def update_settings(
|
||||
request: Request,
|
||||
request: Request,
|
||||
activate: bool = Form(...),
|
||||
autoplay: bool = Form(...),
|
||||
deepspeed_activate: bool = Form(...),
|
||||
@@ -403,13 +532,14 @@ async def update_settings(
|
||||
data["tts_method_xtts_local"] = tts_method == "xtts_local"
|
||||
data["voice"] = voice
|
||||
|
||||
#Save the updated settings back to the JSON file
|
||||
with open(this_dir / 'config.json', "w") as json_file:
|
||||
# Save the updated settings back to the JSON file
|
||||
with open(this_dir / "config.json", "w") as json_file:
|
||||
json.dump(data, json_file)
|
||||
|
||||
#Redirect to the settings page to display the updated settings
|
||||
# Redirect to the settings page to display the updated settings
|
||||
return RedirectResponse(url="/settings", status_code=303)
|
||||
|
||||
|
||||
#############################################################
|
||||
#### DOCUMENTATION - README ETC - PRESENTED AS A WEBPAGE ####
|
||||
#############################################################
|
||||
@@ -421,7 +551,7 @@ simple_webpage = """
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CoquiTTS for Text-generation-WebUI</title>
|
||||
<title>AllTalk TTS for Text-generation-WebUI</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
@@ -517,7 +647,7 @@ simple_webpage = """
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 id="toc">CoquiTTS for Text-generation-WebUI</h1>
|
||||
<h1 id="toc">AllTalk TTS for Text-generation-WebUI</h1>
|
||||
<p>If you are looking for your <b>Text-generation-WebUI</b> webpage, try visiting <a href="http://127.0.0.1:7860" target="_blank">http://127.0.0.1:7860</a>.</p>
|
||||
<p><b>Text-generation-WebUI</b> documentation and wiki <a href="https://github.com/oobabooga/text-generation-webui/wiki" target="_blank">https://github.com/oobabooga/text-generation-webui/wiki</a>.</p>
|
||||
|
||||
@@ -525,14 +655,14 @@ simple_webpage = """
|
||||
|
||||
<h3>Table of Contents</h3>
|
||||
<ul>
|
||||
<li><a href="#getting-started">Getting Started with CoquiTTS</a></li>
|
||||
<li><a href="#getting-started">Getting Started with AllTalk TTS</a></li>
|
||||
<li><a href="#server-information">Server Information</a></li>
|
||||
<li><a href="#using-voice-samples">Using Voice Samples</a></li>
|
||||
<li><a href="#where-are-the-outputs-stored">Automatic output wav file deletion</a></li>
|
||||
<li><a href="#low-vram-option-overview">Low VRAM Overview</a></li>
|
||||
<li><a href="#deepspeed-simplified">DeepSpeed Simplified</a></li>
|
||||
<li><a href="#setup_deepspeed">Setup DeepSpeed</a></li>
|
||||
<li><a href="#other-features">Other Features of Coqui_TTS Extension for Text-generation-webui</a></li>
|
||||
<li><a href="#other-features">Other Features of AllTalk_TTS Extension for Text-generation-webui</a></li>
|
||||
<li><a href="#TTSmodels">TTS Models/Methods</a></li>
|
||||
<li><a href="#customTTSmodels">Custom TTS Models and Model path</a></li>
|
||||
<li><a href="#curl-commands">CURL Commands</a></li>
|
||||
@@ -542,7 +672,7 @@ simple_webpage = """
|
||||
</ul>
|
||||
|
||||
<h2 id="getting-started">Getting Started</h2>
|
||||
<p>To generate TTS, you can use the provided interface or interact with the server using CURL commands. Below are some details and examples:</p>
|
||||
<p>AllTalk is a web interface, based around the Coqui TTS speech generation system. To generate TTS, you can use the provided interface or interact with the server using CURL commands. Below are some details and examples:</p>
|
||||
|
||||
<h3 id="server-information">Server Information</h3>
|
||||
<ul>
|
||||
@@ -553,12 +683,12 @@ simple_webpage = """
|
||||
|
||||
<h3 id="using-voice-samples"><strong>Using Voice Samples</strong></h3>
|
||||
<h4 id="where-are-the-sample-voices-stored">Where are the sample voices stored?</h4>
|
||||
<p>Voice samples are stored in <b>/extensions/coqui_tts/voices/</b> and should be named using the following format <b>name.wav</b></p>
|
||||
<p>Voice samples are stored in <b>/extensions/alltalk_tts/voices/</b> and should be named using the following format <b>name.wav</b></p>
|
||||
<h4 id="where-are-the-outputs-stored">Where are the outputs stored & Automatic output wav file deletion.</h4>
|
||||
<p>Voice samples are stored in <b>/extensions/coqui_tts/outputs/</b></p>
|
||||
<p>Voice samples are stored in <b>/extensions/alltalk_tts/outputs/</b></p>
|
||||
<p>You can configure automatic maintenence deletion of old wav files by setting <b>"Del WAV's older than"</b> in the settings above. When <b>"Disabled"</b> your output wav files will be left untouched. When set to a setting <b>"1 Day"</b> or greater, your output wav files older than that time period will be automatically deleted on startup.</p>
|
||||
<h4>Where are the models stored?</h4>
|
||||
<p>This extension will download the 2.0.2 model to <b>/extensions/coqui_tts/models/</b></p>
|
||||
<p>This extension will download the 2.0.2 model to <b>/extensions/alltalk_tts/models/</b></p>
|
||||
<p>This TTS engine will also download the latest available model and store it wherever it normally stores it for your OS (Windows/Linux/Mac).</p>
|
||||
<h4>How do I create a new voice sample?</h4>
|
||||
<p>To create a new voice sample you need to make a <b>wav</b> file that is <b>22050Hz</b>, <b>Mono</b>, <b>16 bit</b> and between <b>6 to 12 seconds long</b>, though 7 to 9 seconds is usually good.</p>
|
||||
@@ -567,7 +697,7 @@ simple_webpage = """
|
||||
<h4>Generating the sample!</h4>
|
||||
<p>So youve downloaded your favoutie celebrity interview off Youtube or wherever. From here you need to chop it down to 6 to 12 seconds in length and resample it. If you need to clean it up, do audio processing, volume level changes etc, do it before the steps I am about to describe.</p>
|
||||
<p>Using the latest version of <b>Audacity</b>, select your clip and <b>Tracks > Resample to 22050Hz</b>, then <b>Tracks > Mix > Stereo to Mono</b>. and then <b>File > Export Audio</b>, saving it as a WAV of 22050Hz.</p>
|
||||
<p>Save your generated wav file in <b>/extensions/coqui_tts/voices/</b></p>
|
||||
<p>Save your generated wav file in <b>/extensions/alltalk_tts/voices/</b></p>
|
||||
<p><b>Note:</b> Using AI generated audio clips <b>may</b> introduce unwanted sounds as its already a copy/simulation of a voice.</p>
|
||||
<h4>Why doesnt it sound like XXX Person?</h4>
|
||||
<p>The reasons can be that you:</p>
|
||||
@@ -611,7 +741,7 @@ simple_webpage = """
|
||||
<p><strong>Note:</strong> Requires Nvidia Cuda Toolkit installation and correct CUDA_HOME path configuration.</p>
|
||||
|
||||
<h4>How to Use It:</h4>
|
||||
<p>In CoquiTTS, the DeepSpeed checkbox will only be available if DeepSpeed is detected on your system. Check the checkbox, wait 10 to 30 seconds and off you go!</p>
|
||||
<p>In AllTalkTTS, the DeepSpeed checkbox will only be available if DeepSpeed is detected on your system. Check the checkbox, wait 10 to 30 seconds and off you go!</p>
|
||||
<p><a href="#toc">Back to top of page</a></p>
|
||||
|
||||
<h3 id="setup_deepspeed">Setup DeepSpeed</h3>
|
||||
@@ -692,7 +822,7 @@ simple_webpage = """
|
||||
|
||||
<p><a href="#toc">Back to top of page</a></p>
|
||||
|
||||
<h2 id="other-features"><strong>Other Features of Coqui_TTS Extension for Text-generation-webui</strong></h2>
|
||||
<h2 id="other-features"><strong>Other Features of AllTalk_TTS Extension for Text-generation-webui</strong></h2>
|
||||
|
||||
<h3>Start-up Checks</h3>
|
||||
<p>Ensures a minimum TTS version (0.21.3) is installed and provides an error/instructions if not.</p>
|
||||
@@ -701,21 +831,21 @@ simple_webpage = """
|
||||
<p><a href="#toc">Back to top of page</a></p>
|
||||
|
||||
<h3 id="TTSmodels">TTS Models/Methods</h3>
|
||||
<p>It's worth noting that all models and methods can and do sound different from one another. Many people complained about the quality of audio produced by the 2.0.<b>3</b> model, so this extension will download the 2.0.<b>2</b> model to your models folder and give you the choice to use 2.0.<b>2</b> <b>(API Local and XTTSv2 Local)</b> or use the most current model 2.0.<b>3</b> <b>(API TTS)</b>. As/When a new model is released by Coqui it will be downloaded by the TTS service on startup and stored wherever the TTS service keeps new models on your operating system of choice.</p>
|
||||
<p>It's worth noting that all models and methods can and do sound different from one another. Many people complained about the quality of audio produced by the 2.0.<b>3</b> model, so this extension will download the 2.0.<b>2</b> model to your models folder and give you the choice to use 2.0.<b>2</b> <b>(API Local and XTTSv2 Local)</b> or use the most current model 2.0.<b>3</b> <b>(API TTS)</b>. As/When a new model is released by AllTalk it will be downloaded by the TTS service on startup and stored wherever the TTS service keeps new models on your operating system of choice.</p>
|
||||
<ul>
|
||||
<li><strong>API TTS:</strong> Uses the current TTS model available that's downloaded by the TTS API process (e.g. version 2.0.3 at the time of writing). This model is not stored in your "models" folder, but elsewhere on your system and managed by the TTS software.</li>
|
||||
<li><strong>API Local:</strong> Utilizes the <b>2.0.2</b> local model stored at <b>/coqui_tts/models/xttsv2_2.0.2</b>.</li>
|
||||
<li><strong>XTTSv2 Local:</strong> Employs the <b>2.0.2</b> local model <b>/coqui_tts/models/xttsv2_2.0.2</b> and utilizes a distinct TTS generation method. <b>Supports DeepSpeed acceleration</b>.</li>
|
||||
<li><strong>API Local:</strong> Utilizes the <b>2.0.2</b> local model stored at <b>/alltalk_tts/models/xttsv2_2.0.2</b>.</li>
|
||||
<li><strong>XTTSv2 Local:</strong> Employs the <b>2.0.2</b> local model <b>/alltalk_tts/models/xttsv2_2.0.2</b> and utilizes a distinct TTS generation method. <b>Supports DeepSpeed acceleration</b>.</li>
|
||||
</ul>
|
||||
<p><a href="#toc">Back to top of page</a></p>
|
||||
|
||||
<h3 id="customTTSmodels">Custom TTS Models and Model path</h3>
|
||||
|
||||
<p>Its possible to set a custom model for the <strong>API Local</strong> and<strong> XTTSv2</strong> Local methods, or ideed point it at the same model that <strong>API TTS</strong> uses (wherever it is stored on your OS of choice). Many people did not like the sound quality of the Coqui <strong>2.0.<span style="color:#e74c3c">3</span></strong> model, and as such the Coqui_tts extension downloads the <strong>2.0.<span style="color:#2980b9">2</span></strong> model seperately to the <strong>2.0.<span style="color:#e74c3c">3</span></strong> model that TTS service downloads and manages. Typically the <strong>2.0.<span style="color:#2980b9">2</span></strong> model is stored in your <strong>/extensions/coqui_tts/models</strong> folder and it is always downloaded on first start-up of the Coqui_tts extension. However, you may either want to use a custom model version of your choosing, or point it to a different path on your system, or even point it so that API Local and XTTSv2 <strong>both</strong> use the same model that API TTS is using.</p>
|
||||
<p>Its possible to set a custom model for the <strong>API Local</strong> and<strong> XTTSv2</strong> Local methods, or ideed point it at the same model that <strong>API TTS</strong> uses (wherever it is stored on your OS of choice). Many people did not like the sound quality of the Coqui <strong>2.0.<span style="color:#e74c3c">3</span></strong> model, and as such the AllTalk tts extension downloads the <strong>2.0.<span style="color:#2980b9">2</span></strong> model seperately to the <strong>2.0.<span style="color:#e74c3c">3</span></strong> model that TTS service downloads and manages. Typically the <strong>2.0.<span style="color:#2980b9">2</span></strong> model is stored in your <strong>/extensions/alltalk_tts/models</strong> folder and it is always downloaded on first start-up of the AllTalk_tts extension. However, you may either want to use a custom model version of your choosing, or point it to a different path on your system, or even point it so that API Local and XTTSv2 <strong>both</strong> use the same model that API TTS is using.</p>
|
||||
<p>If you do choose to change the location there are a couple of things to note. </p>
|
||||
<p>- The folder you place the model in, <strong><span style="color:#e74c3c">cannot</span></strong> be called "<strong>models</strong>". This name is reserved solely for the system to identify you are or are not using a custom model.</p>
|
||||
<p>- On each startup, the Coqui_tts extension will check the custom location and if it does not exist, it will create it and download the files it needs. It will also re download any missing files in that location that are needed for the model to function.</p>
|
||||
<p>- There will be extra output at the console to inform you that you are using a custom model and each time you load up the Coqui_tts extension or switch between models.</p>
|
||||
<p>- On each startup, the AllTalk tts extension will check the custom location and if it does not exist, it will create it and download the files it needs. It will also re download any missing files in that location that are needed for the model to function.</p>
|
||||
<p>- There will be extra output at the console to inform you that you are using a custom model and each time you load up the AllTalk_tts extension or switch between models.</p>
|
||||
<p>To change the model path, there are at minimum 2x settings you need to alter in the <strong>modeldownload.json</strong> file, <strong>base_path</strong> and <strong>model_path</strong>. These two settings are further detailed in the section below called <strong>Explanation of the modeldownload.json file</strong></p>
|
||||
<p>You would edit the settings in the <strong>modeldownload.json</strong> file as follows (make a backup of your current file in case): </p>
|
||||
<p><strong>Windows example:</strong> <span style="color:#2980b9">c:\mystuff\mydownloads\myTTSmodel\</span><em>{files in here}</em></p>
|
||||
@@ -733,8 +863,8 @@ simple_webpage = """
|
||||
<li> <strong>model_path</strong> would be:<span style="color:#2980b9"> "TTSmodel"</span></li>
|
||||
</ul>
|
||||
|
||||
<p>Once you restart the Coqui_tts extension, it will check this path for the files and output any details at the console.</p>
|
||||
<p>When you are happy it's' working correctly, you are welcome to go delete the models folder stored at <strong>/extensions/coqui_tts/models.</strong></p>
|
||||
<p>Once you restart the AllTalk_tts extension, it will check this path for the files and output any details at the console.</p>
|
||||
<p>When you are happy it's' working correctly, you are welcome to go delete the models folder stored at <strong>/extensions/alltalk_tts/models.</strong></p>
|
||||
<p>If you wish to change the files that the modeldownloader is pulling at startup, you can futher edit the <strong>modeldownload.json</strong> and change the http addresses within this files <strong>files_to_download</strong> section e.g.</p>
|
||||
<p> "files_to_download": {<br />
|
||||
"LICENSE.txt": "https://huggingface.co/coqui/XTTS-v2/resolve/v2.0.2/LICENSE.txt?download=true",<br />
|
||||
@@ -758,7 +888,7 @@ simple_webpage = """
|
||||
<code><span class="key">"model_loaded:"</span> <span class="value">true</span>,</code><span class="key"> Used within the code, do not change.</span><br>
|
||||
<code><span class="key">"model_name:"</span> <span class="value">"tts_models/multilingual/multi-dataset/xtts_v2"</span>,</code><span class="key"> Specifies the model that the "API TTS" method will use for TTS generation.</span><br>
|
||||
<code><span class="key">"port_number:"</span> <span class="value">"7851"</span>,</code><span class="key"> Specifies the default port number for the web server.</span><br>
|
||||
<code><span class="key">"output_folder_wav:"</span> <span class="value">"extensions/coqui_tts/outputs/"</span>,</code><span class="key"> Sets the output folder to send files to on generating TTS.</span><br>
|
||||
<code><span class="key">"output_folder_wav:"</span> <span class="value">"extensions/alltalk_tts/outputs/"</span>,</code><span class="key"> Sets the output folder to send files to on generating TTS.</span><br>
|
||||
<code><span class="key">"remove_trailing_dots:"</span> <span class="value">false</span>,</code><span class="key"> Controls whether trailing dots are removed from text segments before generation.</span><br>
|
||||
<code><span class="key">"show_text:"</span> <span class="value">true</span>,</code><span class="key"> Controls whether message text is shown under the audio player.</span><br>
|
||||
<code><span class="key">"tts_method_api_local:"</span> <span class="value">false</span>,</code><span class="key"> Controls whether the "API Local" model/method is turned on or off.</span><br>
|
||||
@@ -811,7 +941,7 @@ simple_webpage = """
|
||||
|
||||
<h3 id="debugging-and-tts-generation-information"><strong>Debugging and TTS Generation Information:</strong></h3>
|
||||
<p>Command line outputs are more verbose to assist in understanding backend processes and debugging.</p>
|
||||
<p>Its possible during startup you can get a warning message such as <b>[CoquiTTS Startup] Warning TTS Subprocess has NOT started up yet, Will keep trying for 60 seconds maximum</b> This is normal behavior if the subprocess is taking a while to start, however, if there is an issue starting the subprocess, you may see multiples of this message and an it will time out after 60 seconds, resulting in the TTS engine not starting. Its likely that you are not in the correct python environment or one that has a TTS engine inside, if this happens, though the system will output a warning about that ahead of this message</p>
|
||||
<p>Its possible during startup you can get a warning message such as <b>[AllTalk Startup] Warning TTS Subprocess has NOT started up yet, Will keep trying for 60 seconds maximum</b> This is normal behavior if the subprocess is taking a while to start, however, if there is an issue starting the subprocess, you may see multiples of this message and an it will time out after 60 seconds, resulting in the TTS engine not starting. Its likely that you are not in the correct python environment or one that has a TTS engine inside, if this happens, though the system will output a warning about that ahead of this message</p>
|
||||
<p>Typically the command line console will output any warning or error messages. If you need to reset your default configuation, the settings are all listed above in the configuration details.</p>
|
||||
<p><a href="#toc">Back to top of page</a></p>
|
||||
|
||||
@@ -841,21 +971,25 @@ simple_webpage = """
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
###################################################
|
||||
#### Webserver Startup & Initial model Loading ####
|
||||
###################################################
|
||||
@app.get("/ready")
|
||||
@app.get("/ready")
|
||||
async def ready():
|
||||
return Response("Ready endpoint")
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return HTMLResponse(content=simple_webpage, status_code=200)
|
||||
|
||||
#Start Uvicorn Webserver
|
||||
|
||||
# Start Uvicorn Webserver
|
||||
host_parameter = {params["ip_address"]}
|
||||
port_parameter = str(params["port_number"])
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host=host_parameter, port=port_parameter, log_level="warning")
|
||||
Reference in new issue
Block a user