Updated Parler to the v1 model (mini and large available)

This commit is contained in:
erew123 authored and GitHub committed 2024-08-09 10:32:47 +01:00
1 parent df764f71ef
commit c1c7b8cf65
5 files changed
+219 -31

No files matched your search

@@ -13,6 +13,21 @@
"https://huggingface.co/parler-tts/parler-tts-mini-v1/resolve/main/tokenizer_config.json?download=true", "https://huggingface.co/parler-tts/parler-tts-mini-v1/resolve/main/tokenizer_config.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-mini-v1/resolve/main/model.safetensors?download=true" "https://huggingface.co/parler-tts/parler-tts-mini-v1/resolve/main/model.safetensors?download=true"
] ]
},
{
"model_name": "parler-tts-large-v1",
"files_to_download": [
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/config.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/generation_config.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/preprocessor_config.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/special_tokens_map.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/spiece.model?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/tokenizer.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/tokenizer_config.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/model.safetensors.index.json?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/model-00001-of-00002.safetensors?download=true",
"https://huggingface.co/parler-tts/parler-tts-large-v1/resolve/main/model-00002-of-00002.safetensors?download=true"
]
} }
] ]
} }
+33 -26
View File
@@ -172,12 +172,7 @@ class tts_class:
################################## ##################################
# If your model does load into CUDA and you want to support LowVRAM, aka moving the model # If your model does load into CUDA and you want to support LowVRAM, aka moving the model
# on the fly between CUDA and System RAM on each generation request, you will be adding # on the fly between CUDA and System RAM on each generation request, you will be adding
# The code in here to do it. See the XTTS tts engine for an example. Piper however, doesnt # The code in here to do it. See the XTTS tts engine for an example.
# Load into VRAM or System RAM, also low vram is set globally disabled by the model_settings.JSON
# file, so this would never get called anywyay, however, we still need to keep an empty
# function in place. Piper TTS uses "pass" telling function to just exit out cleanly if called.
# However, its quite a simple check along the lines of "if CUDA is available and model is
# in X place, then send it to Y place (or Y to X).
async def handle_lowvram_change(self): async def handle_lowvram_change(self):
if torch.cuda.is_available(): if torch.cuda.is_available():
if self.device == "cuda": if self.device == "cuda":
@@ -238,26 +233,40 @@ class tts_class:
# ↑↑↑ Keep everything above this line ↑↑↑ # ↑↑↑ Keep everything above this line ↑↑↑
# ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ # ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
# Check if model_path exists # Check if model_path exists
if not os.path.exists(models_folder): common_required_files = [
print(f"[{self.branding}ENG] \033[91mError\033[0m: The specified model path '{models_folder}' does not exist.") "config.json", "generation_config.json", "preprocessor_config.json",
self.available_models = {'No Models Available': 'parler'} # Change the name in here to your TTS engine name "special_tokens_map.json", "spiece.model", "tokenizer.json", "tokenizer_config.json"
return self.available_models ]
required_files = ["config.json", "generation_config.json", "model.safetensors", "preprocessor_config.json", "special_tokens_map.json", "spiece.model", "tokenizer.json", "tokenizer_config.json"]
for subfolder in models_folder.iterdir(): for subfolder in models_folder.iterdir():
if subfolder.is_dir(): if subfolder.is_dir():
model_name = subfolder.name model_name = subfolder.name
print("model_name is:", model_name) if self.debug_tts else None print("model_name is:", model_name) if self.debug_tts else None
if all(subfolder.joinpath(file).exists() for file in required_files):
self.available_models[f"parler - {model_name}"] = "parler"
print("self.available_models is:", self.available_models) if self.debug_tts else None
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ # Check for common required files
# ↓↓↓ Keep everything below this line ↓↓↓ if all(subfolder.joinpath(file).exists() for file in common_required_files):
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ # Check for mini model (single safetensors file)
if subfolder.joinpath("model.safetensors").exists():
self.available_models[f"parler - {model_name}"] = "parler"
print("self.available_models is:", self.available_models) if self.debug_tts else None
# Check for large model (split safetensors files and index)
elif (subfolder.joinpath("model.safetensors.index.json").exists() and
subfolder.joinpath("model-00001-of-00002.safetensors").exists() and
subfolder.joinpath("model-00002-of-00002.safetensors").exists()):
self.available_models[f"parler - {model_name}"] = "parler"
print("self.available_models is:", self.available_models) if self.debug_tts else None
else:
print(f"[{self.branding}ENG] \033[91mWarning\033[0m: Model folder '{model_name}' is missing required model files.")
else: else:
self.available_models = {'No Models Available': 'parler'} # Change the name in here to your TTS engine name print(f"[{self.branding}ENG] \033[91mWarning\033[0m: Model folder '{model_name}' is missing common required files.")
print(f"[{self.branding}ENG] \033[91mWarning\033[0m: Model folder '{model_name}' is missing required")
print(f"[{self.branding}ENG] \033[91mWarning\033[0m: files or the folder does not exist.") # ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
# ↓↓↓ Keep everything below this line ↓↓↓
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
else:
self.available_models = {'No Models Available': 'parler'} # Change the name in here to your TTS engine name
print(f"[{self.branding}ENG] \033[91mWarning\033[0m: Model folder '{model_name}' is missing required")
print(f"[{self.branding}ENG] \033[91mWarning\033[0m: files or the folder does not exist.")
return self.available_models return self.available_models
############################################################# #############################################################
@@ -301,7 +310,7 @@ class tts_class:
############################# #############################
# This function will handle the loading of your model, into VRAM/CUDA, System RAM or whatever. # This function will handle the loading of your model, into VRAM/CUDA, System RAM or whatever.
# In XTTS, which has 2x model loader types, there are 2x loaders. They are called by "def handle_tts_method_change" # In XTTS, which has 2x model loader types, there are 2x loaders. They are called by "def handle_tts_method_change"
# In Piper we fake a model loader as Piper doesnt actually load a model into CUDA/System RAM as such. So, in that # In Parler we fake a model loader as Parler doesnt actually load a model into CUDA/System RAM as such. So, in that
# situation, api_manual_load_model is kind of a blank function. Though we do set self.is_tts_model_loaded = True # situation, api_manual_load_model is kind of a blank function. Though we do set self.is_tts_model_loaded = True
# as this is used elsewhere in the scripts to confirm that a model is available to be used for TTS generation. # as this is used elsewhere in the scripts to confirm that a model is available to be used for TTS generation.
# We always check for "No Models Available" being sent as that means we are trying to load in a model that # We always check for "No Models Available" being sent as that means we are trying to load in a model that
@@ -332,10 +341,10 @@ class tts_class:
############################### ###############################
# This function will handle the UN-loading of your model, from VRAM/CUDA, System RAM or whatever. # This function will handle the UN-loading of your model, from VRAM/CUDA, System RAM or whatever.
# In XTTS, that model loads into CUDA/System Ram, so when we swap models, we want to unload the current model # In XTTS, that model loads into CUDA/System Ram, so when we swap models, we want to unload the current model
# free up the memory and then load in the new model to VRAM/CUDA. On the flip side of that, Piper doesnt # free up the memory and then load in the new model to VRAM/CUDA. On the flip side of that, Parler doesnt
# doesnt load into memory, so we just need to put a fake function here that doesnt really do anything # doesnt load into memory, so we just need to put a fake function here that doesnt really do anything
# other than set "self.is_tts_model_loaded = False", which would be set back to true by the model loader. # other than set "self.is_tts_model_loaded = False", which would be set back to true by the model loader.
# So look at the Piper model_engine.py if you DONT need to unload models. # So look at the Parler model_engine.py if you DONT need to unload models.
async def unload_model(self): async def unload_model(self):
self.is_tts_model_loaded = False self.is_tts_model_loaded = False
if not self.current_model_loaded == None: if not self.current_model_loaded == None:
@@ -354,7 +363,7 @@ class tts_class:
# This function is your central model loading/unloading handler that deals with the above functions as necesary, to call loading, unloading, # This function is your central model loading/unloading handler that deals with the above functions as necesary, to call loading, unloading,
# swappng DeepSpeed, Low vram etc. This function gets called with a "engine name - model name" type call. In XTTS, because there are 2x # swappng DeepSpeed, Low vram etc. This function gets called with a "engine name - model name" type call. In XTTS, because there are 2x
# model loader types, (XTTS and APILocal), we take tts_method and split the "engine name - model name" into a loader type and the model # model loader types, (XTTS and APILocal), we take tts_method and split the "engine name - model name" into a loader type and the model
# that it needs to load in and then we call the correct loader function. Whereas in Piper, which doesnt load models into memory at all, # that it needs to load in and then we call the correct loader function. Whereas in Parler, which doesnt load models into memory at all,
# we just have a fake function that doesnt really do anything. We always check to see if the model name has "No Models Available" in the # we just have a fake function that doesnt really do anything. We always check to see if the model name has "No Models Available" in the
# name thats sent over, just to catch any potential errors. We display the start load time and end load time. Thats about it. # name thats sent over, just to catch any potential errors. We display the start load time and end load time. Thats about it.
async def handle_tts_method_change(self, tts_method): async def handle_tts_method_change(self, tts_method):
@@ -402,8 +411,6 @@ class tts_class:
# as false in our model_settings.JSON file, meaning streaming will never be called. However, we have to put a fake streaming routine in our # as false in our model_settings.JSON file, meaning streaming will never be called. However, we have to put a fake streaming routine in our
# function below (or a real function if it does support streaming of course). Parler has an example of a fake streaming function, which is # function below (or a real function if it does support streaming of course). Parler has an example of a fake streaming function, which is
# very clearly highlighted in its model_engine.py script. # very clearly highlighted in its model_engine.py script.
# Piper TTS, which uses command line based calls and therefore has different ones for Windows and Linux/Mac, has an example of doing this
# within its model_engine.py file.
async def generate_tts(self, text, voice, language, temperature, repetition_penalty, speed, pitch, output_file, streaming): async def generate_tts(self, text, voice, language, temperature, repetition_penalty, speed, pitch, output_file, streaming):
print(f"[{self.branding}Debug] Entered model_engine.py generate_tts function") if self.debug_tts else None print(f"[{self.branding}Debug] Entered model_engine.py generate_tts function") if self.debug_tts else None
if not self.is_tts_model_loaded: # Check if a model is loaded and error out if not. if not self.is_tts_model_loaded: # Check if a model is loaded and error out if not.
@@ -7,7 +7,7 @@
"model_capabilties": { "model_capabilties": {
"audio_format": "wav", "audio_format": "wav",
"deepspeed_capable": false, "deepspeed_capable": false,
"generationspeed_capable": true, "generationspeed_capable": false,
"languages_capable": false, "languages_capable": false,
"lowvram_capable": true, "lowvram_capable": true,
"multimodel_capable": true, "multimodel_capable": true,
@@ -26,7 +26,7 @@
"deepspeed_enabled": false, "deepspeed_enabled": false,
"engine_installed": true, "engine_installed": true,
"generationspeed_set": 1, "generationspeed_set": 1,
"lowvram_enabled": true, "lowvram_enabled": false,
"pitch_set": 0, "pitch_set": 0,
"repetitionpenalty_set": 10, "repetitionpenalty_set": 10,
"temperature_set": 0.75 "temperature_set": 0.75
@@ -360,7 +360,9 @@ def parler_model_alltalk_settings(model_config_data):
This extension will download the models to `/alltalk_tts/models/parler/` folder.<br> This extension will download the models to `/alltalk_tts/models/parler/` folder.<br>
### 🟧 Where are the voices stored for parler models? ### 🟧 Where are the voices stored for parler models?
Parler is unlike any other TTS engine. It is actually mode like Stable Diffusion, where you write a text based description of what you want your image to look like, but in this case, you describe what you want the voice to sound like. This means you can have pretty much any voice you want, however, the downside to this is, there is no consistency of the voices, meaning that no 2x TTS generations will sound exactly like the same voice.<br> Parler is unlike any other TTS engine. It is actually mode like Stable Diffusion, where you write a text based description of what you want your image to look like, but in this case, you describe what you want the voice to sound like. For example `A female speaker with an enthusiastic and lively voice. Her tone is bright and energetic, with a fast pace and a lot of inflection. The audio is clear and vibrant.`
This means you can have pretty much any voice you want, however, the downside to this is, there is little consistency of the voices, meaning that no 2x TTS generations will sound exactly like the same voice. You can however use one of the `Native` built in voices to give a level of consistency. Please refer to the Parler website for more infomation https://github.com/huggingface/parler-tts.<br>
### 🟧 So how do I create my voices for Parler? ### 🟧 So how do I create my voices for Parler?
On the settings page for Parler, there is a Voice Editor tab. In there you can add/remove/ammend voices as you wish, or edit the `parler_voices.json` file stored in `system/tts_engines/parler/`. On the settings page for Parler, there is a Voice Editor tab. In there you can add/remove/ammend voices as you wish, or edit the `parler_voices.json` file stored in `system/tts_engines/parler/`.
@@ -370,8 +372,36 @@ def parler_model_alltalk_settings(model_config_data):
> When `Disabled`, your output wav files will be left untouched.<br> > When `Disabled`, your output wav files will be left untouched.<br>
> When set to a setting `1 Day` or greater, your output wav files older than that time period will be automatically deleted on start-up of AllTalk.<br> > When set to a setting `1 Day` or greater, your output wav files older than that time period will be automatically deleted on start-up of AllTalk.<br>
### 🟧 Skipped text/speech
At time of writing, this model is 1x day old and I could see reports of issues with some TTS not being generated, some longer text missing the middle portion of the text etc. You can confirm what AllTalk sent to the Parler TTS engine by looking at the command prompt/terminal window. If your text shows up there, it was sent to the Parler TTS engine. Please refer to the Parler website for more details https://github.com/huggingface/parler-tts.
""") """)
gr.Markdown(""" gr.Markdown("""
### 🟧 How do I use Parler's voice generation system?
To create a voice with Parler:
Describe the voice characteristics in your prompt. For example: `Jon's voice is monotone yet slightly fast in delivery, with a very close recording that almost has no background noise.`
Use one of the 34 inbuilt `Native` speaker names for a level of consistency: `Aaron, Alisa, Anna, Barbara, Bill, Brenda, Bruce, Carol, David, Eileen, Emily, Eric, Gary, James, Jason, Jenna, Jerry, Jon, Jordan, Joy, Karen, Laura, Lauren, Lea, Mike, Naomie, Patrick, Rebecca, Rick, Rose, Tina, Tom, Will, Yann`
Control audio quality in the voice characteristics prompt:
> Include `very clear audio` for highest quality<br>
> Use `very noisy audio` for high levels of background noise
Adjust other features in your voice characteristics prompt:
> Gender<br>
> Speaking rate<br>
> Pitch<br>
> Reverberation
Remember, while you can create diverse voices, each generation may sound slightly different even with the same description.
In the text sent for TTS generation, you can use punctuation to control speech rhythm (e.g. use `,` commas for small breaks)
### 🟧 UserWarning: 1Torch was not compiled with flash attention
This is a limitation of Windows Pytorch not yet having full flash attention support on later builds of Pytorch (is my understanding at this time).
""") """)
return app return app
+138 -2
View File
@@ -1,12 +1,148 @@
{ {
"voices": [ "voices": [
{
"voice_name": "Native Aaron",
"description": "Aaron's voice is a deep male voice with a resonant quality. He speaks slowly and clearly, with a commanding presence."
},
{
"voice_name": "Native Alisa",
"description": "Alisa's voice is a crisp female voice with a hint of assertiveness. She speaks at a brisk pace with clear enunciation."
},
{
"voice_name": "Native Anna",
"description": "Anna's voice is a soft female voice with a slight Eastern European accent. She speaks at a careful pace with gentle tones."
},
{
"voice_name": "Native Barbara",
"description": "Barbara's voice is a sophisticated female voice with a slight huskiness. She speaks at a measured pace with refined intonation."
},
{
"voice_name": "Native Bill",
"description": "Bill's voice is a mature male voice with a gravelly texture. He speaks slowly and deliberately, with a wise tone."
},
{
"voice_name": "Native Brenda",
"description": "Brenda's voice is a soft-spoken female voice with a gentle, soothing quality. She speaks slowly and clearly."
},
{
"voice_name": "Native Bruce",
"description": "Bruce's voice is a strong male voice with a commanding presence. He speaks at a steady pace with authoritative tones."
},
{
"voice_name": "Native Carol",
"description": "Carol's voice is a mature female voice with a warm, motherly quality. She speaks at a gentle pace with nurturing tones."
},
{
"voice_name": "Native David",
"description": "David's voice is an authoritative male voice with a rich timbre. He speaks at a steady pace with precise diction."
},
{
"voice_name": "Native Eileen",
"description": "Eileen's voice is a mature female voice with a slight breathiness. She speaks at a relaxed pace with a warm tone."
},
{
"voice_name": "Native Emily",
"description": "Emily's voice is a sweet female voice with a youthful quality. She speaks at a lively pace with cheerful inflections."
},
{
"voice_name": "Native Eric",
"description": "Eric's voice is a casual male voice with a hint of gruffness. He speaks at a relaxed pace with natural pauses."
},
{
"voice_name": "Native Gary",
"description": "Gary's voice is a deep, resonant male voice with a hint of gravel. He speaks slowly and deliberately, giving weight to each word."
},
{
"voice_name": "Native James",
"description": "James's voice is a refined male voice with a slight British accent. He speaks at a moderate pace with crisp articulation."
},
{
"voice_name": "Native Jason",
"description": "Jason's voice is a calm male voice with a neutral accent. He speaks at a moderate pace with even tones."
},
{
"voice_name": "Native Jenna",
"description": "Jenna's voice is a young female voice with a slight vocal fry. She speaks at a moderate pace with modern inflections."
},
{
"voice_name": "Native Jerry",
"description": "Jerry's voice is a jovial male voice with a hint of a chuckle. He speaks at a relaxed pace with natural inflections."
},
{
"voice_name": "Native Jon",
"description": "Jon's voice is monotone yet slightly fast in delivery, with a very close recording that almost has no background noise."
},
{
"voice_name": "Native Jordan",
"description": "Jordan's voice is a youthful, gender-neutral voice with a slight rasp. They speak at a variable pace with natural inflections."
},
{
"voice_name": "Native Joy",
"description": "Joy's voice is a cheerful female voice with a musical quality. She speaks at a lively pace with expressive intonation."
},
{
"voice_name": "Native Karen",
"description": "Karen's voice is a mature female voice with a slight huskiness. She speaks at a measured pace with a calming tone."
},
{
"voice_name": "Native Laura",
"description": "Laura's voice is a warm and friendly female tone with a slight lilt. She speaks at a moderate pace with clear enunciation."
},
{
"voice_name": "Native Lauren",
"description": "Lauren's voice is a professional female voice with a confident tone. She speaks at a steady pace with clear diction."
},
{
"voice_name": "Native Lea",
"description": "Lea's voice is a bright and energetic female voice with a slight upward inflection at the end of sentences. She speaks at a brisk pace."
},
{
"voice_name": "Native Mike",
"description": "Mike's voice is a friendly male voice with a hint of enthusiasm. He speaks at a brisk pace with clear enunciation."
},
{
"voice_name": "Native Naomie",
"description": "Naomie's voice is a vibrant female voice with a slight exotic accent. She speaks at a variable pace with expressive tones."
},
{
"voice_name": "Native Patrick",
"description": "Patrick's voice is a warm male voice with a slight Irish lilt. He speaks at a moderate pace with a friendly tone."
},
{
"voice_name": "Native Rebecca",
"description": "Rebecca's voice is a clear female voice with a hint of enthusiasm. She speaks at a moderate pace with engaging inflections."
},
{
"voice_name": "Native Rick",
"description": "Rick's voice is a confident male voice with a slight regional accent. He speaks at a moderate pace with clear articulation."
},
{
"voice_name": "Native Rose",
"description": "Rose's voice is a gentle female voice with a slight breathiness. She speaks slowly and softly, with a soothing quality."
},
{
"voice_name": "Native Tina",
"description": "Tina's voice is a bubbly female voice with an upbeat quality. She speaks at a lively pace with enthusiastic tones."
},
{
"voice_name": "Native Tom",
"description": "Tom's voice is a neutral male voice with a clear tone. He speaks at a steady pace with precise articulation."
},
{
"voice_name": "Native Will",
"description": "Will's voice is an energetic male voice with a youthful tone. He speaks at a fast pace with enthusiastic inflections."
},
{
"voice_name": "Native Yann",
"description": "Yann's voice is a sophisticated male voice with a slight foreign accent. He speaks at a measured pace with precise pronunciation."
},
{ {
"voice_name": "soothing_female", "voice_name": "soothing_female",
"description": "A female speaker with a soft, soothing voice. Her tone is gentle and calming, with a slight reverb as if she is in a small, cozy room. She speaks slowly and clearly." "description": "A female speaker with a soft, soothing voice. Her tone is gentle and calming, with a slight reverb as if she is in a small, cozy room."
}, },
{ {
"voice_name": "authoritative_male", "voice_name": "authoritative_male",
"description": "A male speaker with a strong, authoritative voice. His tone is firm and commanding, with a slight bass boost that adds to the depth. He speaks at a moderate pace." "description": "Nicks voice is a male speaker with a strong, authoritative voice. His tone is firm and commanding, with a slight bass boost that adds to the depth. He speaks at a moderate pace."
}, },
{ {
"voice_name": "friendly_young_male", "voice_name": "friendly_young_male",