xinference 1.2.0__py3-none-any.whl → 1.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xinference might be problematic. Click here for more details.
- xinference/_version.py +3 -3
- xinference/api/restful_api.py +4 -7
- xinference/client/handlers.py +3 -0
- xinference/core/chat_interface.py +6 -1
- xinference/core/model.py +2 -0
- xinference/core/scheduler.py +4 -7
- xinference/core/supervisor.py +114 -23
- xinference/core/worker.py +70 -4
- xinference/deploy/local.py +2 -1
- xinference/model/audio/core.py +11 -0
- xinference/model/audio/cosyvoice.py +16 -5
- xinference/model/audio/kokoro.py +139 -0
- xinference/model/audio/melotts.py +110 -0
- xinference/model/audio/model_spec.json +80 -0
- xinference/model/audio/model_spec_modelscope.json +18 -0
- xinference/model/audio/whisper.py +35 -10
- xinference/model/llm/llama_cpp/core.py +21 -14
- xinference/model/llm/llm_family.json +527 -1
- xinference/model/llm/llm_family.py +4 -1
- xinference/model/llm/llm_family_modelscope.json +495 -3
- xinference/model/llm/memory.py +1 -1
- xinference/model/llm/mlx/core.py +24 -6
- xinference/model/llm/transformers/core.py +9 -1
- xinference/model/llm/transformers/qwen2_audio.py +3 -1
- xinference/model/llm/transformers/qwen2_vl.py +20 -3
- xinference/model/llm/transformers/utils.py +22 -11
- xinference/model/llm/utils.py +115 -1
- xinference/model/llm/vllm/core.py +14 -4
- xinference/model/llm/vllm/xavier/block.py +3 -4
- xinference/model/llm/vllm/xavier/block_tracker.py +71 -58
- xinference/model/llm/vllm/xavier/collective.py +74 -0
- xinference/model/llm/vllm/xavier/collective_manager.py +147 -0
- xinference/model/llm/vllm/xavier/executor.py +18 -16
- xinference/model/llm/vllm/xavier/scheduler.py +79 -63
- xinference/model/llm/vllm/xavier/test/test_xavier.py +60 -35
- xinference/model/llm/vllm/xavier/transfer.py +53 -32
- xinference/thirdparty/cosyvoice/bin/spk2info.pt +0 -0
- xinference/thirdparty/melo/__init__.py +0 -0
- xinference/thirdparty/melo/api.py +135 -0
- xinference/thirdparty/melo/app.py +61 -0
- xinference/thirdparty/melo/attentions.py +459 -0
- xinference/thirdparty/melo/commons.py +160 -0
- xinference/thirdparty/melo/configs/config.json +94 -0
- xinference/thirdparty/melo/data/example/metadata.list +20 -0
- xinference/thirdparty/melo/data_utils.py +413 -0
- xinference/thirdparty/melo/download_utils.py +67 -0
- xinference/thirdparty/melo/infer.py +25 -0
- xinference/thirdparty/melo/init_downloads.py +14 -0
- xinference/thirdparty/melo/losses.py +58 -0
- xinference/thirdparty/melo/main.py +36 -0
- xinference/thirdparty/melo/mel_processing.py +174 -0
- xinference/thirdparty/melo/models.py +1030 -0
- xinference/thirdparty/melo/modules.py +598 -0
- xinference/thirdparty/melo/monotonic_align/__init__.py +16 -0
- xinference/thirdparty/melo/monotonic_align/core.py +46 -0
- xinference/thirdparty/melo/preprocess_text.py +135 -0
- xinference/thirdparty/melo/split_utils.py +174 -0
- xinference/thirdparty/melo/text/__init__.py +35 -0
- xinference/thirdparty/melo/text/chinese.py +199 -0
- xinference/thirdparty/melo/text/chinese_bert.py +107 -0
- xinference/thirdparty/melo/text/chinese_mix.py +253 -0
- xinference/thirdparty/melo/text/cleaner.py +36 -0
- xinference/thirdparty/melo/text/cleaner_multiling.py +110 -0
- xinference/thirdparty/melo/text/cmudict.rep +129530 -0
- xinference/thirdparty/melo/text/cmudict_cache.pickle +0 -0
- xinference/thirdparty/melo/text/english.py +284 -0
- xinference/thirdparty/melo/text/english_bert.py +39 -0
- xinference/thirdparty/melo/text/english_utils/__init__.py +0 -0
- xinference/thirdparty/melo/text/english_utils/abbreviations.py +35 -0
- xinference/thirdparty/melo/text/english_utils/number_norm.py +97 -0
- xinference/thirdparty/melo/text/english_utils/time_norm.py +47 -0
- xinference/thirdparty/melo/text/es_phonemizer/__init__.py +0 -0
- xinference/thirdparty/melo/text/es_phonemizer/base.py +140 -0
- xinference/thirdparty/melo/text/es_phonemizer/cleaner.py +109 -0
- xinference/thirdparty/melo/text/es_phonemizer/es_symbols.json +79 -0
- xinference/thirdparty/melo/text/es_phonemizer/es_symbols.txt +1 -0
- xinference/thirdparty/melo/text/es_phonemizer/es_symbols_v2.json +83 -0
- xinference/thirdparty/melo/text/es_phonemizer/es_to_ipa.py +12 -0
- xinference/thirdparty/melo/text/es_phonemizer/example_ipa.txt +400 -0
- xinference/thirdparty/melo/text/es_phonemizer/gruut_wrapper.py +253 -0
- xinference/thirdparty/melo/text/es_phonemizer/punctuation.py +174 -0
- xinference/thirdparty/melo/text/es_phonemizer/spanish_symbols.txt +1 -0
- xinference/thirdparty/melo/text/es_phonemizer/test.ipynb +124 -0
- xinference/thirdparty/melo/text/fr_phonemizer/__init__.py +0 -0
- xinference/thirdparty/melo/text/fr_phonemizer/base.py +140 -0
- xinference/thirdparty/melo/text/fr_phonemizer/cleaner.py +122 -0
- xinference/thirdparty/melo/text/fr_phonemizer/en_symbols.json +78 -0
- xinference/thirdparty/melo/text/fr_phonemizer/example_ipa.txt +1 -0
- xinference/thirdparty/melo/text/fr_phonemizer/fr_symbols.json +89 -0
- xinference/thirdparty/melo/text/fr_phonemizer/fr_to_ipa.py +30 -0
- xinference/thirdparty/melo/text/fr_phonemizer/french_abbreviations.py +48 -0
- xinference/thirdparty/melo/text/fr_phonemizer/french_symbols.txt +1 -0
- xinference/thirdparty/melo/text/fr_phonemizer/gruut_wrapper.py +258 -0
- xinference/thirdparty/melo/text/fr_phonemizer/punctuation.py +172 -0
- xinference/thirdparty/melo/text/french.py +94 -0
- xinference/thirdparty/melo/text/french_bert.py +39 -0
- xinference/thirdparty/melo/text/japanese.py +647 -0
- xinference/thirdparty/melo/text/japanese_bert.py +49 -0
- xinference/thirdparty/melo/text/ko_dictionary.py +44 -0
- xinference/thirdparty/melo/text/korean.py +192 -0
- xinference/thirdparty/melo/text/opencpop-strict.txt +429 -0
- xinference/thirdparty/melo/text/spanish.py +122 -0
- xinference/thirdparty/melo/text/spanish_bert.py +39 -0
- xinference/thirdparty/melo/text/symbols.py +290 -0
- xinference/thirdparty/melo/text/tone_sandhi.py +769 -0
- xinference/thirdparty/melo/train.py +635 -0
- xinference/thirdparty/melo/train.sh +19 -0
- xinference/thirdparty/melo/transforms.py +209 -0
- xinference/thirdparty/melo/utils.py +424 -0
- xinference/types.py +2 -0
- xinference/web/ui/build/asset-manifest.json +3 -3
- xinference/web/ui/build/index.html +1 -1
- xinference/web/ui/build/static/js/{main.1eb206d1.js → main.b0936c54.js} +3 -3
- xinference/web/ui/build/static/js/main.b0936c54.js.map +1 -0
- xinference/web/ui/node_modules/.cache/babel-loader/a3ff866acddf34917a7ee399e0e571a4dfd8ba66d5057db885f243e16a6eb17d.json +1 -0
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/METADATA +37 -27
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/RECORD +122 -45
- xinference/web/ui/build/static/js/main.1eb206d1.js.map +0 -1
- xinference/web/ui/node_modules/.cache/babel-loader/2213d49de260e1f67c888081b18f120f5225462b829ae57c9e05a05cec83689d.json +0 -1
- /xinference/web/ui/build/static/js/{main.1eb206d1.js.LICENSE.txt → main.b0936c54.js.LICENSE.txt} +0 -0
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/LICENSE +0 -0
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/WHEEL +0 -0
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/entry_points.txt +0 -0
- {xinference-1.2.0.dist-info → xinference-1.2.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"symbols": [
|
|
3
|
+
"_",
|
|
4
|
+
",",
|
|
5
|
+
".",
|
|
6
|
+
"!",
|
|
7
|
+
"?",
|
|
8
|
+
"-",
|
|
9
|
+
"~",
|
|
10
|
+
"\u2026",
|
|
11
|
+
"N",
|
|
12
|
+
"Q",
|
|
13
|
+
"a",
|
|
14
|
+
"b",
|
|
15
|
+
"d",
|
|
16
|
+
"e",
|
|
17
|
+
"f",
|
|
18
|
+
"g",
|
|
19
|
+
"h",
|
|
20
|
+
"i",
|
|
21
|
+
"j",
|
|
22
|
+
"k",
|
|
23
|
+
"l",
|
|
24
|
+
"m",
|
|
25
|
+
"n",
|
|
26
|
+
"o",
|
|
27
|
+
"p",
|
|
28
|
+
"s",
|
|
29
|
+
"t",
|
|
30
|
+
"u",
|
|
31
|
+
"v",
|
|
32
|
+
"w",
|
|
33
|
+
"x",
|
|
34
|
+
"y",
|
|
35
|
+
"z",
|
|
36
|
+
"\u0251",
|
|
37
|
+
"\u00e6",
|
|
38
|
+
"\u0283",
|
|
39
|
+
"\u0291",
|
|
40
|
+
"\u00e7",
|
|
41
|
+
"\u026f",
|
|
42
|
+
"\u026a",
|
|
43
|
+
"\u0254",
|
|
44
|
+
"\u025b",
|
|
45
|
+
"\u0279",
|
|
46
|
+
"\u00f0",
|
|
47
|
+
"\u0259",
|
|
48
|
+
"\u026b",
|
|
49
|
+
"\u0265",
|
|
50
|
+
"\u0278",
|
|
51
|
+
"\u028a",
|
|
52
|
+
"\u027e",
|
|
53
|
+
"\u0292",
|
|
54
|
+
"\u03b8",
|
|
55
|
+
"\u03b2",
|
|
56
|
+
"\u014b",
|
|
57
|
+
"\u0266",
|
|
58
|
+
"\u207c",
|
|
59
|
+
"\u02b0",
|
|
60
|
+
"`",
|
|
61
|
+
"^",
|
|
62
|
+
"#",
|
|
63
|
+
"*",
|
|
64
|
+
"=",
|
|
65
|
+
"\u02c8",
|
|
66
|
+
"\u02cc",
|
|
67
|
+
"\u2192",
|
|
68
|
+
"\u2193",
|
|
69
|
+
"\u2191",
|
|
70
|
+
" ",
|
|
71
|
+
"\u0263",
|
|
72
|
+
"\u0261",
|
|
73
|
+
"r",
|
|
74
|
+
"\u0272",
|
|
75
|
+
"\u029d",
|
|
76
|
+
"\u028e",
|
|
77
|
+
"\u02d0",
|
|
78
|
+
|
|
79
|
+
"\u0303",
|
|
80
|
+
"\u0153",
|
|
81
|
+
"\u00f8",
|
|
82
|
+
"\u0281",
|
|
83
|
+
"\u0252",
|
|
84
|
+
"\u028c",
|
|
85
|
+
"\u2014",
|
|
86
|
+
"\u025c",
|
|
87
|
+
"\u0250"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from .cleaner import french_cleaners
|
|
2
|
+
from .gruut_wrapper import Gruut
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def remove_consecutive_t(input_str):
|
|
6
|
+
result = []
|
|
7
|
+
count = 0
|
|
8
|
+
|
|
9
|
+
for char in input_str:
|
|
10
|
+
if char == 't':
|
|
11
|
+
count += 1
|
|
12
|
+
else:
|
|
13
|
+
if count < 3:
|
|
14
|
+
result.extend(['t'] * count)
|
|
15
|
+
count = 0
|
|
16
|
+
result.append(char)
|
|
17
|
+
|
|
18
|
+
if count < 3:
|
|
19
|
+
result.extend(['t'] * count)
|
|
20
|
+
|
|
21
|
+
return ''.join(result)
|
|
22
|
+
|
|
23
|
+
def fr2ipa(text):
|
|
24
|
+
e = Gruut(language="fr-fr", keep_puncs=True, keep_stress=True, use_espeak_phonemes=True)
|
|
25
|
+
# text = french_cleaners(text)
|
|
26
|
+
phonemes = e.phonemize(text, separator="")
|
|
27
|
+
# print(phonemes)
|
|
28
|
+
phonemes = remove_consecutive_t(phonemes)
|
|
29
|
+
# print(phonemes)
|
|
30
|
+
return phonemes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
# List of (regular expression, replacement) pairs for abbreviations in french:
|
|
4
|
+
abbreviations_fr = [
|
|
5
|
+
(re.compile("\\b%s\\." % x[0], re.IGNORECASE), x[1])
|
|
6
|
+
for x in [
|
|
7
|
+
("M", "monsieur"),
|
|
8
|
+
("Mlle", "mademoiselle"),
|
|
9
|
+
("Mlles", "mesdemoiselles"),
|
|
10
|
+
("Mme", "Madame"),
|
|
11
|
+
("Mmes", "Mesdames"),
|
|
12
|
+
("N.B", "nota bene"),
|
|
13
|
+
("M", "monsieur"),
|
|
14
|
+
("p.c.q", "parce que"),
|
|
15
|
+
("Pr", "professeur"),
|
|
16
|
+
("qqch", "quelque chose"),
|
|
17
|
+
("rdv", "rendez-vous"),
|
|
18
|
+
("max", "maximum"),
|
|
19
|
+
("min", "minimum"),
|
|
20
|
+
("no", "numéro"),
|
|
21
|
+
("adr", "adresse"),
|
|
22
|
+
("dr", "docteur"),
|
|
23
|
+
("st", "saint"),
|
|
24
|
+
("co", "companie"),
|
|
25
|
+
("jr", "junior"),
|
|
26
|
+
("sgt", "sergent"),
|
|
27
|
+
("capt", "capitain"),
|
|
28
|
+
("col", "colonel"),
|
|
29
|
+
("av", "avenue"),
|
|
30
|
+
("av. J.-C", "avant Jésus-Christ"),
|
|
31
|
+
("apr. J.-C", "après Jésus-Christ"),
|
|
32
|
+
("art", "article"),
|
|
33
|
+
("boul", "boulevard"),
|
|
34
|
+
("c.-à-d", "c’est-à-dire"),
|
|
35
|
+
("etc", "et cetera"),
|
|
36
|
+
("ex", "exemple"),
|
|
37
|
+
("excl", "exclusivement"),
|
|
38
|
+
("boul", "boulevard"),
|
|
39
|
+
]
|
|
40
|
+
] + [
|
|
41
|
+
(re.compile("\\b%s" % x[0]), x[1])
|
|
42
|
+
for x in [
|
|
43
|
+
("Mlle", "mademoiselle"),
|
|
44
|
+
("Mlles", "mesdemoiselles"),
|
|
45
|
+
("Mme", "Madame"),
|
|
46
|
+
("Mmes", "Mesdames"),
|
|
47
|
+
]
|
|
48
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
_,.!?-~…NQabdefghijklmnopstuvwxyzɑæʃʑçɯɪɔɛɹðəɫɥɸʊɾʒθβŋɦ⁼ʰ`^#*=ˈˌ→↓↑ ɣɡrɲʝʎː̃œøʁɒʌ—ɜɐ
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
import gruut
|
|
5
|
+
from gruut_ipa import IPA # pip install gruut_ipa
|
|
6
|
+
|
|
7
|
+
from .base import BasePhonemizer
|
|
8
|
+
from .punctuation import Punctuation
|
|
9
|
+
|
|
10
|
+
# Table for str.translate to fix gruut/TTS phoneme mismatch
|
|
11
|
+
GRUUT_TRANS_TABLE = str.maketrans("g", "ɡ")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Gruut(BasePhonemizer):
|
|
15
|
+
"""Gruut wrapper for G2P
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
language (str):
|
|
19
|
+
Valid language code for the used backend.
|
|
20
|
+
|
|
21
|
+
punctuations (str):
|
|
22
|
+
Characters to be treated as punctuation. Defaults to `Punctuation.default_puncs()`.
|
|
23
|
+
|
|
24
|
+
keep_puncs (bool):
|
|
25
|
+
If true, keep the punctuations after phonemization. Defaults to True.
|
|
26
|
+
|
|
27
|
+
use_espeak_phonemes (bool):
|
|
28
|
+
If true, use espeak lexicons instead of default Gruut lexicons. Defaults to False.
|
|
29
|
+
|
|
30
|
+
keep_stress (bool):
|
|
31
|
+
If true, keep the stress characters after phonemization. Defaults to False.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
|
|
35
|
+
>>> from TTS.tts.utils.text.phonemizers.gruut_wrapper import Gruut
|
|
36
|
+
>>> phonemizer = Gruut('en-us')
|
|
37
|
+
>>> phonemizer.phonemize("Be a voice, not an! echo?", separator="|")
|
|
38
|
+
'b|i| ə| v|ɔ|ɪ|s, n|ɑ|t| ə|n! ɛ|k|o|ʊ?'
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
language: str,
|
|
44
|
+
punctuations=Punctuation.default_puncs(),
|
|
45
|
+
keep_puncs=True,
|
|
46
|
+
use_espeak_phonemes=False,
|
|
47
|
+
keep_stress=False,
|
|
48
|
+
):
|
|
49
|
+
super().__init__(language, punctuations=punctuations, keep_puncs=keep_puncs)
|
|
50
|
+
self.use_espeak_phonemes = use_espeak_phonemes
|
|
51
|
+
self.keep_stress = keep_stress
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def name():
|
|
55
|
+
return "gruut"
|
|
56
|
+
|
|
57
|
+
def phonemize_gruut(self, text: str, separator: str = "|", tie=False) -> str: # pylint: disable=unused-argument
|
|
58
|
+
"""Convert input text to phonemes.
|
|
59
|
+
|
|
60
|
+
Gruut phonemizes the given `str` by seperating each phoneme character with `separator`, even for characters
|
|
61
|
+
that constitude a single sound.
|
|
62
|
+
|
|
63
|
+
It doesn't affect 🐸TTS since it individually converts each character to token IDs.
|
|
64
|
+
|
|
65
|
+
Examples::
|
|
66
|
+
"hello how are you today?" -> `h|ɛ|l|o|ʊ| h|a|ʊ| ɑ|ɹ| j|u| t|ə|d|e|ɪ`
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
text (str):
|
|
70
|
+
Text to be converted to phonemes.
|
|
71
|
+
|
|
72
|
+
tie (bool, optional) : When True use a '͡' character between
|
|
73
|
+
consecutive characters of a single phoneme. Else separate phoneme
|
|
74
|
+
with '_'. This option requires espeak>=1.49. Default to False.
|
|
75
|
+
"""
|
|
76
|
+
ph_list = []
|
|
77
|
+
for sentence in gruut.sentences(text, lang=self.language, espeak=self.use_espeak_phonemes):
|
|
78
|
+
for word in sentence:
|
|
79
|
+
if word.is_break:
|
|
80
|
+
# Use actual character for break phoneme (e.g., comma)
|
|
81
|
+
if ph_list:
|
|
82
|
+
# Join with previous word
|
|
83
|
+
ph_list[-1].append(word.text)
|
|
84
|
+
else:
|
|
85
|
+
# First word is punctuation
|
|
86
|
+
ph_list.append([word.text])
|
|
87
|
+
elif word.phonemes:
|
|
88
|
+
# Add phonemes for word
|
|
89
|
+
word_phonemes = []
|
|
90
|
+
|
|
91
|
+
for word_phoneme in word.phonemes:
|
|
92
|
+
if not self.keep_stress:
|
|
93
|
+
# Remove primary/secondary stress
|
|
94
|
+
word_phoneme = IPA.without_stress(word_phoneme)
|
|
95
|
+
|
|
96
|
+
word_phoneme = word_phoneme.translate(GRUUT_TRANS_TABLE)
|
|
97
|
+
|
|
98
|
+
if word_phoneme:
|
|
99
|
+
# Flatten phonemes
|
|
100
|
+
word_phonemes.extend(word_phoneme)
|
|
101
|
+
|
|
102
|
+
if word_phonemes:
|
|
103
|
+
ph_list.append(word_phonemes)
|
|
104
|
+
|
|
105
|
+
ph_words = [separator.join(word_phonemes) for word_phonemes in ph_list]
|
|
106
|
+
ph = f"{separator} ".join(ph_words)
|
|
107
|
+
return ph
|
|
108
|
+
|
|
109
|
+
def _phonemize(self, text, separator):
|
|
110
|
+
return self.phonemize_gruut(text, separator, tie=False)
|
|
111
|
+
|
|
112
|
+
def is_supported_language(self, language):
|
|
113
|
+
"""Returns True if `language` is supported by the backend"""
|
|
114
|
+
return gruut.is_language_supported(language)
|
|
115
|
+
|
|
116
|
+
@staticmethod
|
|
117
|
+
def supported_languages() -> List:
|
|
118
|
+
"""Get a dictionary of supported languages.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
List: List of language codes.
|
|
122
|
+
"""
|
|
123
|
+
return list(gruut.get_supported_languages())
|
|
124
|
+
|
|
125
|
+
def version(self):
|
|
126
|
+
"""Get the version of the used backend.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
str: Version of the used backend.
|
|
130
|
+
"""
|
|
131
|
+
return gruut.__version__
|
|
132
|
+
|
|
133
|
+
@classmethod
|
|
134
|
+
def is_available(cls):
|
|
135
|
+
"""Return true if ESpeak is available else false"""
|
|
136
|
+
return importlib.util.find_spec("gruut") is not None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
from cleaner import french_cleaners
|
|
141
|
+
import json
|
|
142
|
+
|
|
143
|
+
e = Gruut(language="fr-fr", keep_puncs=True, keep_stress=True, use_espeak_phonemes=True)
|
|
144
|
+
symbols = [ # en + sp
|
|
145
|
+
"_",
|
|
146
|
+
",",
|
|
147
|
+
".",
|
|
148
|
+
"!",
|
|
149
|
+
"?",
|
|
150
|
+
"-",
|
|
151
|
+
"~",
|
|
152
|
+
"\u2026",
|
|
153
|
+
"N",
|
|
154
|
+
"Q",
|
|
155
|
+
"a",
|
|
156
|
+
"b",
|
|
157
|
+
"d",
|
|
158
|
+
"e",
|
|
159
|
+
"f",
|
|
160
|
+
"g",
|
|
161
|
+
"h",
|
|
162
|
+
"i",
|
|
163
|
+
"j",
|
|
164
|
+
"k",
|
|
165
|
+
"l",
|
|
166
|
+
"m",
|
|
167
|
+
"n",
|
|
168
|
+
"o",
|
|
169
|
+
"p",
|
|
170
|
+
"s",
|
|
171
|
+
"t",
|
|
172
|
+
"u",
|
|
173
|
+
"v",
|
|
174
|
+
"w",
|
|
175
|
+
"x",
|
|
176
|
+
"y",
|
|
177
|
+
"z",
|
|
178
|
+
"\u0251",
|
|
179
|
+
"\u00e6",
|
|
180
|
+
"\u0283",
|
|
181
|
+
"\u0291",
|
|
182
|
+
"\u00e7",
|
|
183
|
+
"\u026f",
|
|
184
|
+
"\u026a",
|
|
185
|
+
"\u0254",
|
|
186
|
+
"\u025b",
|
|
187
|
+
"\u0279",
|
|
188
|
+
"\u00f0",
|
|
189
|
+
"\u0259",
|
|
190
|
+
"\u026b",
|
|
191
|
+
"\u0265",
|
|
192
|
+
"\u0278",
|
|
193
|
+
"\u028a",
|
|
194
|
+
"\u027e",
|
|
195
|
+
"\u0292",
|
|
196
|
+
"\u03b8",
|
|
197
|
+
"\u03b2",
|
|
198
|
+
"\u014b",
|
|
199
|
+
"\u0266",
|
|
200
|
+
"\u207c",
|
|
201
|
+
"\u02b0",
|
|
202
|
+
"`",
|
|
203
|
+
"^",
|
|
204
|
+
"#",
|
|
205
|
+
"*",
|
|
206
|
+
"=",
|
|
207
|
+
"\u02c8",
|
|
208
|
+
"\u02cc",
|
|
209
|
+
"\u2192",
|
|
210
|
+
"\u2193",
|
|
211
|
+
"\u2191",
|
|
212
|
+
" ",
|
|
213
|
+
"ɣ",
|
|
214
|
+
"ɡ",
|
|
215
|
+
"r",
|
|
216
|
+
"ɲ",
|
|
217
|
+
"ʝ",
|
|
218
|
+
"ʎ",
|
|
219
|
+
"ː"
|
|
220
|
+
]
|
|
221
|
+
with open('/home/xumin/workspace/VITS-Training-Multiling/230715_fr/metadata.txt', 'r') as f:
|
|
222
|
+
lines = f.readlines()
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
used_sym = []
|
|
226
|
+
not_existed_sym = []
|
|
227
|
+
phonemes = []
|
|
228
|
+
|
|
229
|
+
for line in lines:
|
|
230
|
+
text = line.split('|')[-1].strip()
|
|
231
|
+
text = french_cleaners(text)
|
|
232
|
+
ipa = e.phonemize(text, separator="")
|
|
233
|
+
phonemes.append(ipa)
|
|
234
|
+
for s in ipa:
|
|
235
|
+
if s not in symbols:
|
|
236
|
+
if s not in not_existed_sym:
|
|
237
|
+
print(f'not_existed char: {s}')
|
|
238
|
+
not_existed_sym.append(s)
|
|
239
|
+
else:
|
|
240
|
+
if s not in used_sym:
|
|
241
|
+
# print(f'used char: {s}')
|
|
242
|
+
used_sym.append(s)
|
|
243
|
+
|
|
244
|
+
print(used_sym)
|
|
245
|
+
print(not_existed_sym)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
with open('./text/fr_phonemizer/french_symbols.txt', 'w') as g:
|
|
249
|
+
g.writelines(symbols + not_existed_sym)
|
|
250
|
+
|
|
251
|
+
with open('./text/fr_phonemizer/example_ipa.txt', 'w') as g:
|
|
252
|
+
g.writelines(phonemes)
|
|
253
|
+
|
|
254
|
+
data = {'symbols': symbols + not_existed_sym}
|
|
255
|
+
|
|
256
|
+
with open('./text/fr_phonemizer/fr_symbols.json', 'w') as f:
|
|
257
|
+
json.dump(data, f, indent=4)
|
|
258
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import collections
|
|
2
|
+
import re
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
import six
|
|
6
|
+
|
|
7
|
+
_DEF_PUNCS = ';:,.!?¡¿—…"«»“”'
|
|
8
|
+
|
|
9
|
+
_PUNC_IDX = collections.namedtuple("_punc_index", ["punc", "position"])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PuncPosition(Enum):
|
|
13
|
+
"""Enum for the punctuations positions"""
|
|
14
|
+
|
|
15
|
+
BEGIN = 0
|
|
16
|
+
END = 1
|
|
17
|
+
MIDDLE = 2
|
|
18
|
+
ALONE = 3
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Punctuation:
|
|
22
|
+
"""Handle punctuations in text.
|
|
23
|
+
|
|
24
|
+
Just strip punctuations from text or strip and restore them later.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
puncs (str): The punctuations to be processed. Defaults to `_DEF_PUNCS`.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
>>> punc = Punctuation()
|
|
31
|
+
>>> punc.strip("This is. example !")
|
|
32
|
+
'This is example'
|
|
33
|
+
|
|
34
|
+
>>> text_striped, punc_map = punc.strip_to_restore("This is. example !")
|
|
35
|
+
>>> ' '.join(text_striped)
|
|
36
|
+
'This is example'
|
|
37
|
+
|
|
38
|
+
>>> text_restored = punc.restore(text_striped, punc_map)
|
|
39
|
+
>>> text_restored[0]
|
|
40
|
+
'This is. example !'
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, puncs: str = _DEF_PUNCS):
|
|
44
|
+
self.puncs = puncs
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def default_puncs():
|
|
48
|
+
"""Return default set of punctuations."""
|
|
49
|
+
return _DEF_PUNCS
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def puncs(self):
|
|
53
|
+
return self._puncs
|
|
54
|
+
|
|
55
|
+
@puncs.setter
|
|
56
|
+
def puncs(self, value):
|
|
57
|
+
if not isinstance(value, six.string_types):
|
|
58
|
+
raise ValueError("[!] Punctuations must be of type str.")
|
|
59
|
+
self._puncs = "".join(list(dict.fromkeys(list(value)))) # remove duplicates without changing the oreder
|
|
60
|
+
self.puncs_regular_exp = re.compile(rf"(\s*[{re.escape(self._puncs)}]+\s*)+")
|
|
61
|
+
|
|
62
|
+
def strip(self, text):
|
|
63
|
+
"""Remove all the punctuations by replacing with `space`.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
text (str): The text to be processed.
|
|
67
|
+
|
|
68
|
+
Example::
|
|
69
|
+
|
|
70
|
+
"This is. example !" -> "This is example "
|
|
71
|
+
"""
|
|
72
|
+
return re.sub(self.puncs_regular_exp, " ", text).rstrip().lstrip()
|
|
73
|
+
|
|
74
|
+
def strip_to_restore(self, text):
|
|
75
|
+
"""Remove punctuations from text to restore them later.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
text (str): The text to be processed.
|
|
79
|
+
|
|
80
|
+
Examples ::
|
|
81
|
+
|
|
82
|
+
"This is. example !" -> [["This is", "example"], [".", "!"]]
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
text, puncs = self._strip_to_restore(text)
|
|
86
|
+
return text, puncs
|
|
87
|
+
|
|
88
|
+
def _strip_to_restore(self, text):
|
|
89
|
+
"""Auxiliary method for Punctuation.preserve()"""
|
|
90
|
+
matches = list(re.finditer(self.puncs_regular_exp, text))
|
|
91
|
+
if not matches:
|
|
92
|
+
return [text], []
|
|
93
|
+
# the text is only punctuations
|
|
94
|
+
if len(matches) == 1 and matches[0].group() == text:
|
|
95
|
+
return [], [_PUNC_IDX(text, PuncPosition.ALONE)]
|
|
96
|
+
# build a punctuation map to be used later to restore punctuations
|
|
97
|
+
puncs = []
|
|
98
|
+
for match in matches:
|
|
99
|
+
position = PuncPosition.MIDDLE
|
|
100
|
+
if match == matches[0] and text.startswith(match.group()):
|
|
101
|
+
position = PuncPosition.BEGIN
|
|
102
|
+
elif match == matches[-1] and text.endswith(match.group()):
|
|
103
|
+
position = PuncPosition.END
|
|
104
|
+
puncs.append(_PUNC_IDX(match.group(), position))
|
|
105
|
+
# convert str text to a List[str], each item is separated by a punctuation
|
|
106
|
+
splitted_text = []
|
|
107
|
+
for idx, punc in enumerate(puncs):
|
|
108
|
+
split = text.split(punc.punc)
|
|
109
|
+
prefix, suffix = split[0], punc.punc.join(split[1:])
|
|
110
|
+
splitted_text.append(prefix)
|
|
111
|
+
# if the text does not end with a punctuation, add it to the last item
|
|
112
|
+
if idx == len(puncs) - 1 and len(suffix) > 0:
|
|
113
|
+
splitted_text.append(suffix)
|
|
114
|
+
text = suffix
|
|
115
|
+
return splitted_text, puncs
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def restore(cls, text, puncs):
|
|
119
|
+
"""Restore punctuation in a text.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
text (str): The text to be processed.
|
|
123
|
+
puncs (List[str]): The list of punctuations map to be used for restoring.
|
|
124
|
+
|
|
125
|
+
Examples ::
|
|
126
|
+
|
|
127
|
+
['This is', 'example'], ['.', '!'] -> "This is. example!"
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
return cls._restore(text, puncs, 0)
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def _restore(cls, text, puncs, num): # pylint: disable=too-many-return-statements
|
|
134
|
+
"""Auxiliary method for Punctuation.restore()"""
|
|
135
|
+
if not puncs:
|
|
136
|
+
return text
|
|
137
|
+
|
|
138
|
+
# nothing have been phonemized, returns the puncs alone
|
|
139
|
+
if not text:
|
|
140
|
+
return ["".join(m.punc for m in puncs)]
|
|
141
|
+
|
|
142
|
+
current = puncs[0]
|
|
143
|
+
|
|
144
|
+
if current.position == PuncPosition.BEGIN:
|
|
145
|
+
return cls._restore([current.punc + text[0]] + text[1:], puncs[1:], num)
|
|
146
|
+
|
|
147
|
+
if current.position == PuncPosition.END:
|
|
148
|
+
return [text[0] + current.punc] + cls._restore(text[1:], puncs[1:], num + 1)
|
|
149
|
+
|
|
150
|
+
if current.position == PuncPosition.ALONE:
|
|
151
|
+
return [current.mark] + cls._restore(text, puncs[1:], num + 1)
|
|
152
|
+
|
|
153
|
+
# POSITION == MIDDLE
|
|
154
|
+
if len(text) == 1: # pragma: nocover
|
|
155
|
+
# a corner case where the final part of an intermediate
|
|
156
|
+
# mark (I) has not been phonemized
|
|
157
|
+
return cls._restore([text[0] + current.punc], puncs[1:], num)
|
|
158
|
+
|
|
159
|
+
return cls._restore([text[0] + current.punc + text[1]] + text[2:], puncs[1:], num)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
# if __name__ == "__main__":
|
|
163
|
+
# punc = Punctuation()
|
|
164
|
+
# text = "This is. This is, example!"
|
|
165
|
+
|
|
166
|
+
# print(punc.strip(text))
|
|
167
|
+
|
|
168
|
+
# split_text, puncs = punc.strip_to_restore(text)
|
|
169
|
+
# print(split_text, " ---- ", puncs)
|
|
170
|
+
|
|
171
|
+
# restored_text = punc.restore(split_text, puncs)
|
|
172
|
+
# print(restored_text)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import pickle
|
|
2
|
+
import os
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from . import symbols
|
|
6
|
+
from .fr_phonemizer import cleaner as fr_cleaner
|
|
7
|
+
from .fr_phonemizer import fr_to_ipa
|
|
8
|
+
from transformers import AutoTokenizer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def distribute_phone(n_phone, n_word):
|
|
12
|
+
phones_per_word = [0] * n_word
|
|
13
|
+
for task in range(n_phone):
|
|
14
|
+
min_tasks = min(phones_per_word)
|
|
15
|
+
min_index = phones_per_word.index(min_tasks)
|
|
16
|
+
phones_per_word[min_index] += 1
|
|
17
|
+
return phones_per_word
|
|
18
|
+
|
|
19
|
+
def text_normalize(text):
|
|
20
|
+
text = fr_cleaner.french_cleaners(text)
|
|
21
|
+
return text
|
|
22
|
+
|
|
23
|
+
model_id = 'dbmdz/bert-base-french-europeana-cased'
|
|
24
|
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
|
25
|
+
|
|
26
|
+
def g2p(text, pad_start_end=True, tokenized=None):
|
|
27
|
+
if tokenized is None:
|
|
28
|
+
tokenized = tokenizer.tokenize(text)
|
|
29
|
+
# import pdb; pdb.set_trace()
|
|
30
|
+
phs = []
|
|
31
|
+
ph_groups = []
|
|
32
|
+
for t in tokenized:
|
|
33
|
+
if not t.startswith("#"):
|
|
34
|
+
ph_groups.append([t])
|
|
35
|
+
else:
|
|
36
|
+
ph_groups[-1].append(t.replace("#", ""))
|
|
37
|
+
|
|
38
|
+
phones = []
|
|
39
|
+
tones = []
|
|
40
|
+
word2ph = []
|
|
41
|
+
# print(ph_groups)
|
|
42
|
+
for group in ph_groups:
|
|
43
|
+
w = "".join(group)
|
|
44
|
+
phone_len = 0
|
|
45
|
+
word_len = len(group)
|
|
46
|
+
if w == '[UNK]':
|
|
47
|
+
phone_list = ['UNK']
|
|
48
|
+
else:
|
|
49
|
+
phone_list = list(filter(lambda p: p != " ", fr_to_ipa.fr2ipa(w)))
|
|
50
|
+
|
|
51
|
+
for ph in phone_list:
|
|
52
|
+
phones.append(ph)
|
|
53
|
+
tones.append(0)
|
|
54
|
+
phone_len += 1
|
|
55
|
+
aaa = distribute_phone(phone_len, word_len)
|
|
56
|
+
word2ph += aaa
|
|
57
|
+
# print(phone_list, aaa)
|
|
58
|
+
# print('=' * 10)
|
|
59
|
+
|
|
60
|
+
if pad_start_end:
|
|
61
|
+
phones = ["_"] + phones + ["_"]
|
|
62
|
+
tones = [0] + tones + [0]
|
|
63
|
+
word2ph = [1] + word2ph + [1]
|
|
64
|
+
return phones, tones, word2ph
|
|
65
|
+
|
|
66
|
+
def get_bert_feature(text, word2ph, device=None):
|
|
67
|
+
from text import french_bert
|
|
68
|
+
return french_bert.get_bert_feature(text, word2ph, device=device)
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
ori_text = 'Ce service gratuit est“”"" 【disponible》 en chinois 【simplifié] et autres 123'
|
|
72
|
+
# ori_text = "Ils essayaient vainement de faire comprendre à ma mère qu'avec les cent mille francs que m'avait laissé mon père,"
|
|
73
|
+
# print(ori_text)
|
|
74
|
+
text = text_normalize(ori_text)
|
|
75
|
+
print(text)
|
|
76
|
+
phoneme = fr_to_ipa.fr2ipa(text)
|
|
77
|
+
print(phoneme)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
from TTS.tts.utils.text.phonemizers.multi_phonemizer import MultiPhonemizer
|
|
81
|
+
from text.cleaner_multiling import unicleaners
|
|
82
|
+
|
|
83
|
+
def text_normalize(text):
|
|
84
|
+
text = unicleaners(text, cased=True, lang='fr')
|
|
85
|
+
return text
|
|
86
|
+
|
|
87
|
+
# print(ori_text)
|
|
88
|
+
text = text_normalize(ori_text)
|
|
89
|
+
print(text)
|
|
90
|
+
phonemizer = MultiPhonemizer({"fr-fr": "espeak"})
|
|
91
|
+
# phonemizer.lang_to_phonemizer['fr'].keep_stress = True
|
|
92
|
+
# phonemizer.lang_to_phonemizer['fr'].use_espeak_phonemes = True
|
|
93
|
+
phoneme = phonemizer.phonemize(text, separator="", language='fr-fr')
|
|
94
|
+
print(phoneme)
|