Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import spaCy languages dynamically in XTTS Tokenizer.py #3615

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion TTS/.models.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"hf_url": [
"https://coqui.gateway.scarf.sh/hf/bark/coarse_2.pt",
"https://coqui.gateway.scarf.sh/hf/bark/fine_2.pt",
"https://coqui.gateway.scarf.sh/hf/text_2.pt",
"https://coqui.gateway.scarf.sh/hf/bark/text_2.pt",
"https://coqui.gateway.scarf.sh/hf/bark/config.json",
"https://coqui.gateway.scarf.sh/hf/bark/hubert.pt",
"https://coqui.gateway.scarf.sh/hf/bark/tokenizer.pth"
Expand Down
17 changes: 13 additions & 4 deletions TTS/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,19 @@ def details():
@app.route("/api/tts", methods=["GET", "POST"])
def tts():
with lock:
text = request.headers.get("text") or request.values.get("text", "")
speaker_idx = request.headers.get("speaker-id") or request.values.get("speaker_id", "")
language_idx = request.headers.get("language-id") or request.values.get("language_id", "")
style_wav = request.headers.get("style-wav") or request.values.get("style_wav", "")
try:
data = request.get_json()
text = data.get("text", "")
speaker_idx = data.get("speaker-id", "")
language_idx = data.get("language-id", "")
style_wav = data.get("style-wav", "")
except:
# Fallback to headers and form data if JSON data is not present
text = request.headers.get("text") or request.values.get("text", "")
speaker_idx = request.headers.get("speaker-id") or request.values.get("speaker_id", "")
language_idx = request.headers.get("language-id") or request.values.get("language_id", "")
style_wav = request.headers.get("style-wav") or request.values.get("style_wav", "")

style_wav = style_wav_uri_to_dict(style_wav)

print(f" > Model input: {text}")
Expand Down
40 changes: 24 additions & 16 deletions TTS/tts/layers/xtts/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,37 @@
from hangul_romanize import Transliter
from hangul_romanize.rule import academic
from num2words import num2words
from spacy.lang.ar import Arabic
from spacy.lang.en import English
from spacy.lang.es import Spanish
from spacy.lang.ja import Japanese
from spacy.lang.zh import Chinese
from spacy.util import get_lang_class

from tokenizers import Tokenizer

from TTS.tts.layers.xtts.zh_num2words import TextNorm as zh_num2words

import spacy

# These 2 functions are to verify that any language can be instantiated
def get_spacy_available_langs():
from pathlib import Path
spacy_path = Path(spacy.__file__.replace('__init__.py',''))
spacy_langs = spacy_path / 'lang'
SPACY_LANGS = [str(x).split('/')[-1] for x in spacy_langs.iterdir() if x.is_dir() and str(x).split('/')[-1] != '__pycache__']
print("Available languages in Spacy:", SPACY_LANGS)
return SPACY_LANGS
def get_all_spacy_langs():
SPACY_LANGS = get_spacy_available_langs()
spacy_lang_instances = []
for lang in SPACY_LANGS:
spacy_lang_instances.append(get_spacy_lang(lang))

def get_spacy_lang(lang):
if lang == "zh":
return Chinese()
elif lang == "ja":
return Japanese()
elif lang == "ar":
return Arabic()
elif lang == "es":
return Spanish()
else:
# For most languages, Enlish does the job
return English()

try:
lang_model = get_lang_class(lang)()
except ImportError as e:
print("Error", e)
# Fallback to English if the language model is not available
lang_model = English()
return lang_model

def split_sentence(text, lang, text_split_length=250):
"""Preprocess the input text"""
Expand Down
9 changes: 6 additions & 3 deletions TTS/utils/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,13 @@ def set_model_url(model_item: Dict):
def _set_model_item(self, model_name):
# fetch model info from the dict
if "fairseq" in model_name:
model_type = "tts_models"
lang = model_name.split("/")[1]
split = model_name.split("/")
model_type = split[0]
lang = split[1]
dataset = split[2]
model = split[3]
model_item = {
"model_type": "tts_models",
"model_type": model_type,
"license": "CC BY-NC 4.0",
"default_vocoder": None,
"author": "fairseq",
Expand Down
25 changes: 16 additions & 9 deletions TTS/utils/synthesizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ def tts(
style_text=None,
reference_wav=None,
reference_speaker_name=None,
verbose: bool = True,
split_sentences: bool = True,
**kwargs,
) -> List[int]:
Expand All @@ -278,6 +279,7 @@ def tts(
style_text ([type], optional): transcription of style_wav for Capacitron. Defaults to None.
reference_wav ([type], optional): reference waveform for voice conversion. Defaults to None.
reference_speaker_name ([type], optional): speaker id of reference waveform. Defaults to None.
verbose (bool, optional): print verbose output. Defaults to True.
split_sentences (bool, optional): split the input text into sentences. Defaults to True.
**kwargs: additional arguments to pass to the TTS model.
Returns:
Expand All @@ -294,9 +296,11 @@ def tts(
if text:
sens = [text]
if split_sentences:
print(" > Text splitted to sentences.")
if verbose:
print(" > Text splitted to sentences.")
sens = self.split_into_sentences(text)
print(sens)
if verbose:
print(sens)

# handle multi-speaker
if "voice_dir" in kwargs:
Expand Down Expand Up @@ -420,7 +424,8 @@ def tts(
self.vocoder_config["audio"]["sample_rate"] / self.tts_model.ap.sample_rate,
]
if scale_factor[1] != 1:
print(" > interpolating tts model output.")
if verbose:
print(" > interpolating tts model output.")
vocoder_input = interpolate_vocoder_input(scale_factor, vocoder_input)
else:
vocoder_input = torch.tensor(vocoder_input).unsqueeze(0) # pylint: disable=not-callable
Expand Down Expand Up @@ -484,7 +489,8 @@ def tts(
self.vocoder_config["audio"]["sample_rate"] / self.tts_model.ap.sample_rate,
]
if scale_factor[1] != 1:
print(" > interpolating tts model output.")
if verbose:
print(" > interpolating tts model output.")
vocoder_input = interpolate_vocoder_input(scale_factor, vocoder_input)
else:
vocoder_input = torch.tensor(vocoder_input).unsqueeze(0) # pylint: disable=not-callable
Expand All @@ -497,9 +503,10 @@ def tts(
waveform = waveform.numpy()
wavs = waveform.squeeze()

# compute stats
process_time = time.time() - start_time
audio_time = len(wavs) / self.tts_config.audio["sample_rate"]
print(f" > Processing time: {process_time}")
print(f" > Real-time factor: {process_time / audio_time}")
if verbose:
# compute stats
process_time = time.time() - start_time
audio_time = len(wavs) / self.tts_config.audio["sample_rate"]
print(f" > Processing time: {process_time}")
print(f" > Real-time factor: {process_time / audio_time}")
return wavs
8 changes: 7 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,10 @@ encodec>=0.1.1
# deps for XTTS
unidecode>=1.3.2
num2words
spacy[ja]>=3
spacy[ja]>=3

# spacy thai
pythainlp>=5.0.1

#spacy vietnamese
pyvi>=0.1.1
Loading