PyThaiTTS 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- pythaitts-0.4.0/PKG-INFO +125 -0
- pythaitts-0.4.0/PyThaiTTS.egg-info/PKG-INFO +125 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/PyThaiTTS.egg-info/SOURCES.txt +6 -1
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/PyThaiTTS.egg-info/requires.txt +1 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/PyThaiTTS.egg-info/top_level.txt +1 -0
- pythaitts-0.4.0/README.md +84 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/pythaitts/__init__.py +21 -6
- pythaitts-0.4.0/pythaitts/preprocess.py +254 -0
- pythaitts-0.4.0/pythaitts/pretrained/vachana_tts.py +111 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/setup.py +1 -1
- pythaitts-0.4.0/tests/__init__.py +4 -0
- pythaitts-0.4.0/tests/test_preprocess.py +125 -0
- pythaitts-0.4.0/tests/test_vachana.py +113 -0
- PyThaiTTS-0.3.0/PKG-INFO +0 -51
- PyThaiTTS-0.3.0/PyThaiTTS.egg-info/PKG-INFO +0 -51
- PyThaiTTS-0.3.0/README.md +0 -24
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/LICENSE +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/PyThaiTTS.egg-info/dependency_links.txt +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/PyThaiTTS.egg-info/not-zip-safe +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/pythaitts/pretrained/__init__.py +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/pythaitts/pretrained/khanomtan_tts.py +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/pythaitts/pretrained/lunarlist_model.py +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/pythaitts/pretrained/lunarlist_onnx.py +0 -0
- {PyThaiTTS-0.3.0 → pythaitts-0.4.0}/setup.cfg +0 -0
pythaitts-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyThaiTTS
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Open Source Thai Text-to-speech library in Python
|
|
5
|
+
Home-page: https://github.com/pythainlp/pythaitts
|
|
6
|
+
Author: Wannaphong
|
|
7
|
+
Author-email: wannaphong@yahoo.com
|
|
8
|
+
License: Apache Software License 2.0
|
|
9
|
+
Project-URL: Documentation, https://github.com/pythainlp/pythaitts
|
|
10
|
+
Project-URL: Source, https://github.com/pythainlp/pythaitts
|
|
11
|
+
Project-URL: Bug Reports, https://github.com/pythainlp/pythaitts/issues
|
|
12
|
+
Keywords: Thai,NLP,natural language processing,text analytics,text processing,localization,computational linguistics,text-to-speech
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Topic :: Text Processing
|
|
19
|
+
Classifier: Topic :: Text Processing :: General
|
|
20
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
21
|
+
Requires-Python: >=3.6
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: huggingface_hub
|
|
25
|
+
Requires-Dist: numpy>=1.22
|
|
26
|
+
Requires-Dist: onnxruntime
|
|
27
|
+
Requires-Dist: vachanatts
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
Dynamic: project-url
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
Dynamic: summary
|
|
41
|
+
|
|
42
|
+
# PyThaiTTS
|
|
43
|
+
Open Source Thai Text-to-speech library in Python
|
|
44
|
+
|
|
45
|
+
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
46
|
+
<a href="https://pepy.tech/project/pythaitts"><img alt="Download" src="https://pepy.tech/badge/pythaitts/month"/></a>
|
|
47
|
+
|
|
48
|
+
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
Install by pip:
|
|
53
|
+
|
|
54
|
+
> pip install pythaitts
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
### Basic Usage
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from pythaitts import TTS
|
|
62
|
+
|
|
63
|
+
tts = TTS()
|
|
64
|
+
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
65
|
+
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Using Different TTS Models
|
|
69
|
+
|
|
70
|
+
PyThaiTTS supports multiple TTS models. You can specify which model to use:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from pythaitts import TTS
|
|
74
|
+
|
|
75
|
+
# Use VachanaTTS (default voices: th_f_1, th_m_1, th_f_2, th_m_2)
|
|
76
|
+
tts = TTS(pretrained="vachana")
|
|
77
|
+
file = tts.tts("สวัสดีครับ", speaker_idx="th_f_1", filename="output.wav")
|
|
78
|
+
|
|
79
|
+
# Use Lunarlist ONNX (default)
|
|
80
|
+
tts = TTS(pretrained="lunarlist_onnx")
|
|
81
|
+
file = tts.tts("ภาษาไทย ง่าย มาก", filename="output.wav")
|
|
82
|
+
|
|
83
|
+
# Use KhanomTan
|
|
84
|
+
tts = TTS(pretrained="khanomtan")
|
|
85
|
+
file = tts.tts("ภาษาไทย", speaker_idx="Linda", filename="output.wav")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Text Preprocessing
|
|
89
|
+
|
|
90
|
+
PyThaiTTS includes automatic text preprocessing to improve TTS quality:
|
|
91
|
+
- **Number to Thai text conversion**: Converts digits (e.g., "123") to Thai text (e.g., "หนึ่งร้อยยี่สิบสาม")
|
|
92
|
+
- **Mai yamok (ๆ) expansion**: Expands the Thai repetition character (e.g., "ดีๆ" becomes "ดีดี")
|
|
93
|
+
|
|
94
|
+
Preprocessing is enabled by default:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from pythaitts import TTS
|
|
98
|
+
|
|
99
|
+
tts = TTS()
|
|
100
|
+
# Automatic preprocessing: "มี 5 คนๆ" becomes "มี ห้า คนคน"
|
|
101
|
+
file = tts.tts("มี 5 คนๆ", filename="output.wav")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can disable preprocessing if needed:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
file = tts.tts("มี 5 คนๆ", preprocess=False, filename="output.wav")
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You can also use preprocessing functions directly:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from pythaitts import num_to_thai, expand_maiyamok, preprocess_text
|
|
114
|
+
|
|
115
|
+
# Convert numbers to Thai text
|
|
116
|
+
print(num_to_thai("123")) # Output: หนึ่งร้อยยี่สิบสาม
|
|
117
|
+
|
|
118
|
+
# Expand mai yamok
|
|
119
|
+
print(expand_maiyamok("ดีๆ")) # Output: ดีดี
|
|
120
|
+
|
|
121
|
+
# Full preprocessing
|
|
122
|
+
print(preprocess_text("มี 5 คนๆ")) # Output: มี ห้า คนคน
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyThaiTTS
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Open Source Thai Text-to-speech library in Python
|
|
5
|
+
Home-page: https://github.com/pythainlp/pythaitts
|
|
6
|
+
Author: Wannaphong
|
|
7
|
+
Author-email: wannaphong@yahoo.com
|
|
8
|
+
License: Apache Software License 2.0
|
|
9
|
+
Project-URL: Documentation, https://github.com/pythainlp/pythaitts
|
|
10
|
+
Project-URL: Source, https://github.com/pythainlp/pythaitts
|
|
11
|
+
Project-URL: Bug Reports, https://github.com/pythainlp/pythaitts/issues
|
|
12
|
+
Keywords: Thai,NLP,natural language processing,text analytics,text processing,localization,computational linguistics,text-to-speech
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Topic :: Text Processing
|
|
19
|
+
Classifier: Topic :: Text Processing :: General
|
|
20
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
21
|
+
Requires-Python: >=3.6
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: huggingface_hub
|
|
25
|
+
Requires-Dist: numpy>=1.22
|
|
26
|
+
Requires-Dist: onnxruntime
|
|
27
|
+
Requires-Dist: vachanatts
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: keywords
|
|
35
|
+
Dynamic: license
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
Dynamic: project-url
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
Dynamic: summary
|
|
41
|
+
|
|
42
|
+
# PyThaiTTS
|
|
43
|
+
Open Source Thai Text-to-speech library in Python
|
|
44
|
+
|
|
45
|
+
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
46
|
+
<a href="https://pepy.tech/project/pythaitts"><img alt="Download" src="https://pepy.tech/badge/pythaitts/month"/></a>
|
|
47
|
+
|
|
48
|
+
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
Install by pip:
|
|
53
|
+
|
|
54
|
+
> pip install pythaitts
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
### Basic Usage
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from pythaitts import TTS
|
|
62
|
+
|
|
63
|
+
tts = TTS()
|
|
64
|
+
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
65
|
+
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Using Different TTS Models
|
|
69
|
+
|
|
70
|
+
PyThaiTTS supports multiple TTS models. You can specify which model to use:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from pythaitts import TTS
|
|
74
|
+
|
|
75
|
+
# Use VachanaTTS (default voices: th_f_1, th_m_1, th_f_2, th_m_2)
|
|
76
|
+
tts = TTS(pretrained="vachana")
|
|
77
|
+
file = tts.tts("สวัสดีครับ", speaker_idx="th_f_1", filename="output.wav")
|
|
78
|
+
|
|
79
|
+
# Use Lunarlist ONNX (default)
|
|
80
|
+
tts = TTS(pretrained="lunarlist_onnx")
|
|
81
|
+
file = tts.tts("ภาษาไทย ง่าย มาก", filename="output.wav")
|
|
82
|
+
|
|
83
|
+
# Use KhanomTan
|
|
84
|
+
tts = TTS(pretrained="khanomtan")
|
|
85
|
+
file = tts.tts("ภาษาไทย", speaker_idx="Linda", filename="output.wav")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Text Preprocessing
|
|
89
|
+
|
|
90
|
+
PyThaiTTS includes automatic text preprocessing to improve TTS quality:
|
|
91
|
+
- **Number to Thai text conversion**: Converts digits (e.g., "123") to Thai text (e.g., "หนึ่งร้อยยี่สิบสาม")
|
|
92
|
+
- **Mai yamok (ๆ) expansion**: Expands the Thai repetition character (e.g., "ดีๆ" becomes "ดีดี")
|
|
93
|
+
|
|
94
|
+
Preprocessing is enabled by default:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from pythaitts import TTS
|
|
98
|
+
|
|
99
|
+
tts = TTS()
|
|
100
|
+
# Automatic preprocessing: "มี 5 คนๆ" becomes "มี ห้า คนคน"
|
|
101
|
+
file = tts.tts("มี 5 คนๆ", filename="output.wav")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can disable preprocessing if needed:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
file = tts.tts("มี 5 คนๆ", preprocess=False, filename="output.wav")
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You can also use preprocessing functions directly:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from pythaitts import num_to_thai, expand_maiyamok, preprocess_text
|
|
114
|
+
|
|
115
|
+
# Convert numbers to Thai text
|
|
116
|
+
print(num_to_thai("123")) # Output: หนึ่งร้อยยี่สิบสาม
|
|
117
|
+
|
|
118
|
+
# Expand mai yamok
|
|
119
|
+
print(expand_maiyamok("ดีๆ")) # Output: ดีดี
|
|
120
|
+
|
|
121
|
+
# Full preprocessing
|
|
122
|
+
print(preprocess_text("มี 5 คนๆ")) # Output: มี ห้า คนคน
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
|
@@ -8,7 +8,12 @@ PyThaiTTS.egg-info/not-zip-safe
|
|
|
8
8
|
PyThaiTTS.egg-info/requires.txt
|
|
9
9
|
PyThaiTTS.egg-info/top_level.txt
|
|
10
10
|
pythaitts/__init__.py
|
|
11
|
+
pythaitts/preprocess.py
|
|
11
12
|
pythaitts/pretrained/__init__.py
|
|
12
13
|
pythaitts/pretrained/khanomtan_tts.py
|
|
13
14
|
pythaitts/pretrained/lunarlist_model.py
|
|
14
|
-
pythaitts/pretrained/lunarlist_onnx.py
|
|
15
|
+
pythaitts/pretrained/lunarlist_onnx.py
|
|
16
|
+
pythaitts/pretrained/vachana_tts.py
|
|
17
|
+
tests/__init__.py
|
|
18
|
+
tests/test_preprocess.py
|
|
19
|
+
tests/test_vachana.py
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# PyThaiTTS
|
|
2
|
+
Open Source Thai Text-to-speech library in Python
|
|
3
|
+
|
|
4
|
+
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
5
|
+
<a href="https://pepy.tech/project/pythaitts"><img alt="Download" src="https://pepy.tech/badge/pythaitts/month"/></a>
|
|
6
|
+
|
|
7
|
+
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Install by pip:
|
|
12
|
+
|
|
13
|
+
> pip install pythaitts
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from pythaitts import TTS
|
|
21
|
+
|
|
22
|
+
tts = TTS()
|
|
23
|
+
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
24
|
+
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Using Different TTS Models
|
|
28
|
+
|
|
29
|
+
PyThaiTTS supports multiple TTS models. You can specify which model to use:
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from pythaitts import TTS
|
|
33
|
+
|
|
34
|
+
# Use VachanaTTS (default voices: th_f_1, th_m_1, th_f_2, th_m_2)
|
|
35
|
+
tts = TTS(pretrained="vachana")
|
|
36
|
+
file = tts.tts("สวัสดีครับ", speaker_idx="th_f_1", filename="output.wav")
|
|
37
|
+
|
|
38
|
+
# Use Lunarlist ONNX (default)
|
|
39
|
+
tts = TTS(pretrained="lunarlist_onnx")
|
|
40
|
+
file = tts.tts("ภาษาไทย ง่าย มาก", filename="output.wav")
|
|
41
|
+
|
|
42
|
+
# Use KhanomTan
|
|
43
|
+
tts = TTS(pretrained="khanomtan")
|
|
44
|
+
file = tts.tts("ภาษาไทย", speaker_idx="Linda", filename="output.wav")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Text Preprocessing
|
|
48
|
+
|
|
49
|
+
PyThaiTTS includes automatic text preprocessing to improve TTS quality:
|
|
50
|
+
- **Number to Thai text conversion**: Converts digits (e.g., "123") to Thai text (e.g., "หนึ่งร้อยยี่สิบสาม")
|
|
51
|
+
- **Mai yamok (ๆ) expansion**: Expands the Thai repetition character (e.g., "ดีๆ" becomes "ดีดี")
|
|
52
|
+
|
|
53
|
+
Preprocessing is enabled by default:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from pythaitts import TTS
|
|
57
|
+
|
|
58
|
+
tts = TTS()
|
|
59
|
+
# Automatic preprocessing: "มี 5 คนๆ" becomes "มี ห้า คนคน"
|
|
60
|
+
file = tts.tts("มี 5 คนๆ", filename="output.wav")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
You can disable preprocessing if needed:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
file = tts.tts("มี 5 คนๆ", preprocess=False, filename="output.wav")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
You can also use preprocessing functions directly:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from pythaitts import num_to_thai, expand_maiyamok, preprocess_text
|
|
73
|
+
|
|
74
|
+
# Convert numbers to Thai text
|
|
75
|
+
print(num_to_thai("123")) # Output: หนึ่งร้อยยี่สิบสาม
|
|
76
|
+
|
|
77
|
+
# Expand mai yamok
|
|
78
|
+
print(expand_maiyamok("ดีๆ")) # Output: ดีดี
|
|
79
|
+
|
|
80
|
+
# Full preprocessing
|
|
81
|
+
print(preprocess_text("มี 5 คนๆ")) # Output: มี ห้า คนคน
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
|
@@ -4,14 +4,16 @@ PyThaiTTS
|
|
|
4
4
|
"""
|
|
5
5
|
__version__ = "0.3.0"
|
|
6
6
|
|
|
7
|
+
from pythaitts.preprocess import preprocess_text, num_to_thai, expand_maiyamok
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class TTS:
|
|
9
11
|
def __init__(self, pretrained="lunarlist_onnx", mode="last_checkpoint", version="1.0", device:str="cpu") -> None:
|
|
10
12
|
"""
|
|
11
|
-
:param str pretrained: TTS pretrained (lunarlist_onnx, khanomtan, lunarlist)
|
|
12
|
-
:param str mode: pretrained mode (lunarlist_onnx don't support)
|
|
13
|
+
:param str pretrained: TTS pretrained (lunarlist_onnx, khanomtan, lunarlist, vachana)
|
|
14
|
+
:param str mode: pretrained mode (lunarlist_onnx and vachana don't support)
|
|
13
15
|
:param str version: model version (default is 1.0 or 1.1)
|
|
14
|
-
:param str device: device for running model. (lunarlist_onnx support CPU only.)
|
|
16
|
+
:param str device: device for running model. (lunarlist_onnx and vachana support CPU only.)
|
|
15
17
|
|
|
16
18
|
**Options for mode**
|
|
17
19
|
* *last_checkpoint* (default) - last checkpoint of model
|
|
@@ -26,6 +28,8 @@ class TTS:
|
|
|
26
28
|
For lunarlist_onnx tts model, \
|
|
27
29
|
You can see more about lunarlist tts at `https://github.com/PyThaiNLP/thaitts-onnx <https://github.com/PyThaiNLP/thaitts-onnx>`_
|
|
28
30
|
|
|
31
|
+
For vachana tts model, \
|
|
32
|
+
You can see more about vachana tts at `https://github.com/VYNCX/VachanaTTS2 <https://github.com/VYNCX/VachanaTTS2>`_
|
|
29
33
|
|
|
30
34
|
|
|
31
35
|
"""
|
|
@@ -47,23 +51,34 @@ class TTS:
|
|
|
47
51
|
elif self.pretrained == "lunarlist":
|
|
48
52
|
from pythaitts.pretrained.lunarlist_model import LunarlistModel
|
|
49
53
|
self.model = LunarlistModel(mode=self.mode, device=self.device)
|
|
54
|
+
elif self.pretrained == "vachana":
|
|
55
|
+
from pythaitts.pretrained.vachana_tts import VachanaTTS
|
|
56
|
+
self.model = VachanaTTS()
|
|
50
57
|
else:
|
|
51
|
-
raise
|
|
58
|
+
raise NotImplementedError(
|
|
52
59
|
"PyThaiTTS doesn't support %s pretrained." % self.pretrained
|
|
53
60
|
)
|
|
54
61
|
|
|
55
|
-
def tts(self, text: str, speaker_idx: str = "Linda", language_idx: str = "th-th", return_type: str = "file", filename: str = None):
|
|
62
|
+
def tts(self, text: str, speaker_idx: str = "Linda", language_idx: str = "th-th", return_type: str = "file", filename: str = None, preprocess: bool = True):
|
|
56
63
|
"""
|
|
57
64
|
speech synthesis
|
|
58
65
|
|
|
59
66
|
:param str text: text
|
|
60
|
-
:param str speaker_idx: speaker (default is Linda)
|
|
67
|
+
:param str speaker_idx: speaker (default is Linda for khanomtan, th_f_1 for vachana)
|
|
61
68
|
:param str language_idx: language (default is th-th)
|
|
62
69
|
:param str return_type: return type (default is file)
|
|
63
70
|
:param str filename: path filename for save wav file if return_type is file.
|
|
71
|
+
:param bool preprocess: whether to preprocess text (convert numbers to Thai text and expand ๆ). Default is True.
|
|
64
72
|
"""
|
|
73
|
+
# Preprocess text if requested
|
|
74
|
+
if preprocess:
|
|
75
|
+
from pythaitts.preprocess import preprocess_text
|
|
76
|
+
text = preprocess_text(text)
|
|
77
|
+
|
|
65
78
|
if self.pretrained == "lunarlist" or self.pretrained == "lunarlist_onnx":
|
|
66
79
|
return self.model(text=text,return_type=return_type,filename=filename)
|
|
80
|
+
elif self.pretrained == "vachana":
|
|
81
|
+
return self.model(text=text,speaker_idx=speaker_idx,return_type=return_type,filename=filename)
|
|
67
82
|
return self.model(
|
|
68
83
|
text=text,
|
|
69
84
|
speaker_idx=speaker_idx,
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Thai Text Preprocessing for TTS
|
|
4
|
+
|
|
5
|
+
This module provides text preprocessing functions for Thai Text-to-Speech,
|
|
6
|
+
including number to Thai text conversion and handling of Thai repetition character (ๆ).
|
|
7
|
+
"""
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Thai number words
|
|
12
|
+
THAI_ONES = ["", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า"]
|
|
13
|
+
THAI_TENS = ["", "สิบ", "ยี่สิบ", "สามสิบ", "สี่สิบ", "ห้าสิบ", "หกสิบ", "เจ็ดสิบ", "แปดสิบ", "เก้าสิบ"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _num_to_thai_under_hundred(num: int) -> str:
|
|
17
|
+
"""
|
|
18
|
+
Convert numbers 0-99 to Thai text.
|
|
19
|
+
|
|
20
|
+
:param int num: Number to convert (0-99)
|
|
21
|
+
:return: Thai text representation
|
|
22
|
+
:rtype: str
|
|
23
|
+
"""
|
|
24
|
+
if num == 0:
|
|
25
|
+
return "ศูนย์"
|
|
26
|
+
elif num < 10:
|
|
27
|
+
return THAI_ONES[num]
|
|
28
|
+
elif num < 20:
|
|
29
|
+
if num == 10:
|
|
30
|
+
return "สิบ"
|
|
31
|
+
elif num == 11:
|
|
32
|
+
return "สิบเอ็ด"
|
|
33
|
+
else:
|
|
34
|
+
return "สิบ" + THAI_ONES[num % 10]
|
|
35
|
+
elif num < 100:
|
|
36
|
+
tens = num // 10
|
|
37
|
+
ones = num % 10
|
|
38
|
+
result = THAI_TENS[tens]
|
|
39
|
+
if ones == 1:
|
|
40
|
+
result += "เอ็ด"
|
|
41
|
+
elif ones > 1:
|
|
42
|
+
result += THAI_ONES[ones]
|
|
43
|
+
return result
|
|
44
|
+
return ""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _num_to_thai_under_thousand(num: int) -> str:
|
|
48
|
+
"""
|
|
49
|
+
Convert numbers 0-999 to Thai text.
|
|
50
|
+
|
|
51
|
+
:param int num: Number to convert (0-999)
|
|
52
|
+
:return: Thai text representation
|
|
53
|
+
:rtype: str
|
|
54
|
+
"""
|
|
55
|
+
if num < 100:
|
|
56
|
+
return _num_to_thai_under_hundred(num)
|
|
57
|
+
|
|
58
|
+
hundreds = num // 100
|
|
59
|
+
remainder = num % 100
|
|
60
|
+
|
|
61
|
+
if hundreds == 1:
|
|
62
|
+
result = "หนึ่งร้อย"
|
|
63
|
+
elif hundreds == 2:
|
|
64
|
+
result = "สองร้อย"
|
|
65
|
+
else:
|
|
66
|
+
result = THAI_ONES[hundreds] + "ร้อย"
|
|
67
|
+
|
|
68
|
+
if remainder > 0:
|
|
69
|
+
result += _num_to_thai_under_hundred(remainder)
|
|
70
|
+
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def num_to_thai(num_str: str) -> str:
|
|
75
|
+
"""
|
|
76
|
+
Convert number string to Thai text.
|
|
77
|
+
Supports integers and decimals.
|
|
78
|
+
|
|
79
|
+
:param str num_str: Number string to convert (e.g., "123", "1234", "12.5")
|
|
80
|
+
:return: Thai text representation
|
|
81
|
+
:rtype: str
|
|
82
|
+
|
|
83
|
+
Examples:
|
|
84
|
+
>>> num_to_thai("0")
|
|
85
|
+
'ศูนย์'
|
|
86
|
+
>>> num_to_thai("123")
|
|
87
|
+
'หนึ่งร้อยยี่สิบสาม'
|
|
88
|
+
>>> num_to_thai("1000")
|
|
89
|
+
'หนึ่งพัน'
|
|
90
|
+
"""
|
|
91
|
+
# Handle decimal numbers
|
|
92
|
+
if '.' in num_str:
|
|
93
|
+
integer_part, decimal_part = num_str.split('.')
|
|
94
|
+
result = num_to_thai(integer_part) + "จุด"
|
|
95
|
+
for digit in decimal_part:
|
|
96
|
+
result += THAI_ONES[int(digit)] if int(digit) > 0 else "ศูนย์"
|
|
97
|
+
return result
|
|
98
|
+
|
|
99
|
+
# Convert to integer
|
|
100
|
+
try:
|
|
101
|
+
num = int(num_str)
|
|
102
|
+
except ValueError:
|
|
103
|
+
return num_str # Return original if cannot convert
|
|
104
|
+
|
|
105
|
+
if num == 0:
|
|
106
|
+
return "ศูนย์"
|
|
107
|
+
|
|
108
|
+
if num < 0:
|
|
109
|
+
return "ลบ" + num_to_thai(str(-num))
|
|
110
|
+
|
|
111
|
+
# Handle numbers by magnitude
|
|
112
|
+
if num < 1000:
|
|
113
|
+
return _num_to_thai_under_thousand(num)
|
|
114
|
+
elif num < 10000:
|
|
115
|
+
thousands = num // 1000
|
|
116
|
+
remainder = num % 1000
|
|
117
|
+
result = THAI_ONES[thousands] + "พัน"
|
|
118
|
+
if remainder > 0:
|
|
119
|
+
result += _num_to_thai_under_thousand(remainder)
|
|
120
|
+
return result
|
|
121
|
+
elif num < 100000:
|
|
122
|
+
ten_thousands = num // 10000
|
|
123
|
+
remainder = num % 10000
|
|
124
|
+
if ten_thousands == 1:
|
|
125
|
+
result = "หนึ่งหมื่น"
|
|
126
|
+
elif ten_thousands == 2:
|
|
127
|
+
result = "สองหมื่น"
|
|
128
|
+
else:
|
|
129
|
+
result = THAI_ONES[ten_thousands] + "หมื่น"
|
|
130
|
+
if remainder > 0:
|
|
131
|
+
thousands = remainder // 1000
|
|
132
|
+
if thousands > 0:
|
|
133
|
+
result += THAI_ONES[thousands] + "พัน"
|
|
134
|
+
remainder = remainder % 1000
|
|
135
|
+
if remainder > 0:
|
|
136
|
+
result += _num_to_thai_under_thousand(remainder)
|
|
137
|
+
return result
|
|
138
|
+
elif num < 1000000:
|
|
139
|
+
hundred_thousands = num // 100000
|
|
140
|
+
remainder = num % 100000
|
|
141
|
+
result = THAI_ONES[hundred_thousands] + "แสน"
|
|
142
|
+
if remainder > 0:
|
|
143
|
+
ten_thousands = remainder // 10000
|
|
144
|
+
if ten_thousands > 0:
|
|
145
|
+
result += THAI_ONES[ten_thousands] + "หมื่น"
|
|
146
|
+
remainder = remainder % 10000
|
|
147
|
+
thousands = remainder // 1000
|
|
148
|
+
if thousands > 0:
|
|
149
|
+
result += THAI_ONES[thousands] + "พัน"
|
|
150
|
+
remainder = remainder % 1000
|
|
151
|
+
if remainder > 0:
|
|
152
|
+
result += _num_to_thai_under_thousand(remainder)
|
|
153
|
+
return result
|
|
154
|
+
elif num < 10000000:
|
|
155
|
+
millions = num // 1000000
|
|
156
|
+
remainder = num % 1000000
|
|
157
|
+
result = THAI_ONES[millions] + "ล้าน"
|
|
158
|
+
if remainder > 0:
|
|
159
|
+
result += num_to_thai(str(remainder))
|
|
160
|
+
return result
|
|
161
|
+
else:
|
|
162
|
+
# For very large numbers, use a simple approach
|
|
163
|
+
millions = num // 1000000
|
|
164
|
+
remainder = num % 1000000
|
|
165
|
+
result = num_to_thai(str(millions)) + "ล้าน"
|
|
166
|
+
if remainder > 0:
|
|
167
|
+
result += num_to_thai(str(remainder))
|
|
168
|
+
return result
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def expand_maiyamok(text: str) -> str:
|
|
172
|
+
"""
|
|
173
|
+
Expand Thai repetition character (ๆ) by repeating the previous word or syllable.
|
|
174
|
+
|
|
175
|
+
The mai yamok (ๆ) is a Thai repetition mark that indicates the previous
|
|
176
|
+
word or syllable should be repeated.
|
|
177
|
+
|
|
178
|
+
:param str text: Text containing ๆ character
|
|
179
|
+
:return: Text with ๆ expanded
|
|
180
|
+
:rtype: str
|
|
181
|
+
|
|
182
|
+
Examples:
|
|
183
|
+
>>> expand_maiyamok("ช้าๆ")
|
|
184
|
+
'ช้าช้า'
|
|
185
|
+
>>> expand_maiyamok("ดีๆ")
|
|
186
|
+
'ดีดี'
|
|
187
|
+
"""
|
|
188
|
+
if 'ๆ' not in text:
|
|
189
|
+
return text
|
|
190
|
+
|
|
191
|
+
result = []
|
|
192
|
+
i = 0
|
|
193
|
+
while i < len(text):
|
|
194
|
+
if text[i] == 'ๆ':
|
|
195
|
+
# Find the previous word/syllable to repeat
|
|
196
|
+
if result:
|
|
197
|
+
# Look back to find the word to repeat
|
|
198
|
+
# Thai words are typically separated by spaces or are continuous
|
|
199
|
+
# We'll repeat the last word or syllable
|
|
200
|
+
prev_text = ''.join(result)
|
|
201
|
+
|
|
202
|
+
# Find the last word (sequence of Thai characters)
|
|
203
|
+
thai_char_pattern = r'[ก-๙]+'
|
|
204
|
+
matches = list(re.finditer(thai_char_pattern, prev_text))
|
|
205
|
+
if matches:
|
|
206
|
+
last_match = matches[-1]
|
|
207
|
+
word_to_repeat = last_match.group()
|
|
208
|
+
result.append(word_to_repeat)
|
|
209
|
+
else:
|
|
210
|
+
# If no Thai characters found, just skip the ๆ
|
|
211
|
+
pass
|
|
212
|
+
i += 1
|
|
213
|
+
else:
|
|
214
|
+
result.append(text[i])
|
|
215
|
+
i += 1
|
|
216
|
+
|
|
217
|
+
return ''.join(result)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def preprocess_text(text: str, expand_numbers: bool = True, expand_maiyamok_char: bool = True) -> str:
|
|
221
|
+
"""
|
|
222
|
+
Preprocess Thai text for TTS by converting numbers to text and expanding ๆ.
|
|
223
|
+
|
|
224
|
+
:param str text: Input text to preprocess
|
|
225
|
+
:param bool expand_numbers: Whether to convert numbers to Thai text (default: True)
|
|
226
|
+
:param bool expand_maiyamok_char: Whether to expand ๆ character (default: True)
|
|
227
|
+
:return: Preprocessed text
|
|
228
|
+
:rtype: str
|
|
229
|
+
|
|
230
|
+
Examples:
|
|
231
|
+
>>> preprocess_text("ฉันมี 123 บาท")
|
|
232
|
+
'ฉันมี หนึ่งร้อยยี่สิบสาม บาท'
|
|
233
|
+
>>> preprocess_text("ดีๆ")
|
|
234
|
+
'ดีดี'
|
|
235
|
+
>>> preprocess_text("มี 5 คนๆ")
|
|
236
|
+
'มี ห้า คนคน'
|
|
237
|
+
"""
|
|
238
|
+
result = text
|
|
239
|
+
|
|
240
|
+
# Expand mai yamok (ๆ) first
|
|
241
|
+
if expand_maiyamok_char:
|
|
242
|
+
result = expand_maiyamok(result)
|
|
243
|
+
|
|
244
|
+
# Convert numbers to Thai text
|
|
245
|
+
if expand_numbers:
|
|
246
|
+
# Find all numbers in the text and replace them
|
|
247
|
+
def replace_number(match):
|
|
248
|
+
return num_to_thai(match.group())
|
|
249
|
+
|
|
250
|
+
# Match integers and decimals, including optional negative sign
|
|
251
|
+
# Handles: -5, 123, 123.45
|
|
252
|
+
result = re.sub(r'-?\d+(?:\.\d+)?', replace_number, result)
|
|
253
|
+
|
|
254
|
+
return result
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
VachanaTTS2 model
|
|
4
|
+
|
|
5
|
+
VachanaTTS2 is a Thai text-to-speech model built on VITS architecture.
|
|
6
|
+
It supports multiple Thai voices and is optimized for both CPU and GPU usage.
|
|
7
|
+
|
|
8
|
+
See more: https://github.com/VYNCX/VachanaTTS2
|
|
9
|
+
"""
|
|
10
|
+
import tempfile
|
|
11
|
+
import wave
|
|
12
|
+
import numpy as np
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class VachanaTTS:
|
|
17
|
+
# Supported voice options
|
|
18
|
+
SUPPORTED_VOICES = ["th_f_1", "th_m_1", "th_f_2", "th_m_2"]
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
"""
|
|
22
|
+
Initialize VachanaTTS model.
|
|
23
|
+
The model will be automatically downloaded from HuggingFace on first use.
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
from vachanatts import TTS as VachanaTTS_TTS
|
|
27
|
+
self.tts_func = VachanaTTS_TTS
|
|
28
|
+
except ImportError:
|
|
29
|
+
raise ImportError(
|
|
30
|
+
"vachanatts is not installed. Please install it with: pip install vachanatts"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def __call__(self, text: str, speaker_idx: str = "th_f_1", return_type: str = "file", filename: str = None, **kwargs):
|
|
34
|
+
"""
|
|
35
|
+
Generate speech from text using VachanaTTS.
|
|
36
|
+
|
|
37
|
+
:param str text: Input text to synthesize
|
|
38
|
+
:param str speaker_idx: Voice to use (th_f_1, th_m_1, th_f_2, th_m_2). Default is "th_f_1"
|
|
39
|
+
:param str return_type: Return type ("file" or "waveform")
|
|
40
|
+
:param str filename: Output filename for the generated audio
|
|
41
|
+
:param kwargs: Additional parameters (volume, speed, noise_scale, noise_w_scale)
|
|
42
|
+
:return: File path if return_type is "file", otherwise audio waveform data
|
|
43
|
+
"""
|
|
44
|
+
# Validate speaker_idx
|
|
45
|
+
if speaker_idx not in self.SUPPORTED_VOICES:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"Unsupported voice '{speaker_idx}'. Supported voices are: {', '.join(self.SUPPORTED_VOICES)}"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Extract additional parameters with defaults
|
|
51
|
+
volume = kwargs.get('volume', 1.0)
|
|
52
|
+
speed = kwargs.get('speed', 1.0)
|
|
53
|
+
noise_scale = kwargs.get('noise_scale', 0.667)
|
|
54
|
+
noise_w_scale = kwargs.get('noise_w_scale', 0.8)
|
|
55
|
+
|
|
56
|
+
if return_type == "waveform":
|
|
57
|
+
# For waveform return, we need to generate to a temp file then read it
|
|
58
|
+
temp_filename = None
|
|
59
|
+
try:
|
|
60
|
+
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as fp:
|
|
61
|
+
temp_filename = fp.name
|
|
62
|
+
|
|
63
|
+
# Generate the audio file
|
|
64
|
+
self.tts_func(
|
|
65
|
+
text,
|
|
66
|
+
voice=speaker_idx,
|
|
67
|
+
output=temp_filename,
|
|
68
|
+
volume=volume,
|
|
69
|
+
speed=speed,
|
|
70
|
+
noise_scale=noise_scale,
|
|
71
|
+
noise_w_scale=noise_w_scale
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Read the waveform from the file
|
|
75
|
+
with wave.open(temp_filename, 'rb') as wav_file:
|
|
76
|
+
n_frames = wav_file.getnframes()
|
|
77
|
+
audio_data = wav_file.readframes(n_frames)
|
|
78
|
+
sample_width = wav_file.getsampwidth()
|
|
79
|
+
|
|
80
|
+
# Convert bytes to numpy array based on sample width
|
|
81
|
+
if sample_width == 1:
|
|
82
|
+
waveform = np.frombuffer(audio_data, dtype=np.int8)
|
|
83
|
+
elif sample_width == 2:
|
|
84
|
+
waveform = np.frombuffer(audio_data, dtype=np.int16)
|
|
85
|
+
elif sample_width == 4:
|
|
86
|
+
waveform = np.frombuffer(audio_data, dtype=np.int32)
|
|
87
|
+
else:
|
|
88
|
+
raise ValueError(f"Unsupported sample width: {sample_width} bytes")
|
|
89
|
+
|
|
90
|
+
return waveform
|
|
91
|
+
finally:
|
|
92
|
+
# Clean up temp file
|
|
93
|
+
if temp_filename and os.path.exists(temp_filename):
|
|
94
|
+
os.unlink(temp_filename)
|
|
95
|
+
else:
|
|
96
|
+
# File output
|
|
97
|
+
if filename is None:
|
|
98
|
+
with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as fp:
|
|
99
|
+
filename = fp.name
|
|
100
|
+
|
|
101
|
+
self.tts_func(
|
|
102
|
+
text,
|
|
103
|
+
voice=speaker_idx,
|
|
104
|
+
output=filename,
|
|
105
|
+
volume=volume,
|
|
106
|
+
speed=speed,
|
|
107
|
+
noise_scale=noise_scale,
|
|
108
|
+
noise_w_scale=noise_w_scale
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return filename
|
|
@@ -9,7 +9,7 @@ with open("requirements.txt","r",encoding="utf-8-sig") as f:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="PyThaiTTS",
|
|
12
|
-
version="0.
|
|
12
|
+
version="0.4.0",
|
|
13
13
|
description="Open Source Thai Text-to-speech library in Python",
|
|
14
14
|
long_description=readme,
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Unit tests for Thai text preprocessing module
|
|
4
|
+
"""
|
|
5
|
+
import unittest
|
|
6
|
+
from pythaitts.preprocess import num_to_thai, expand_maiyamok, preprocess_text
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestNumToThai(unittest.TestCase):
|
|
10
|
+
"""Test number to Thai text conversion"""
|
|
11
|
+
|
|
12
|
+
def test_single_digits(self):
|
|
13
|
+
"""Test single digit numbers"""
|
|
14
|
+
self.assertEqual(num_to_thai("0"), "ศูนย์")
|
|
15
|
+
self.assertEqual(num_to_thai("1"), "หนึ่ง")
|
|
16
|
+
self.assertEqual(num_to_thai("5"), "ห้า")
|
|
17
|
+
self.assertEqual(num_to_thai("9"), "เก้า")
|
|
18
|
+
|
|
19
|
+
def test_tens(self):
|
|
20
|
+
"""Test numbers 10-99"""
|
|
21
|
+
self.assertEqual(num_to_thai("10"), "สิบ")
|
|
22
|
+
self.assertEqual(num_to_thai("11"), "สิบเอ็ด")
|
|
23
|
+
self.assertEqual(num_to_thai("15"), "สิบห้า")
|
|
24
|
+
self.assertEqual(num_to_thai("20"), "ยี่สิบ")
|
|
25
|
+
self.assertEqual(num_to_thai("21"), "ยี่สิบเอ็ด")
|
|
26
|
+
self.assertEqual(num_to_thai("99"), "เก้าสิบเก้า")
|
|
27
|
+
|
|
28
|
+
def test_hundreds(self):
|
|
29
|
+
"""Test numbers 100-999"""
|
|
30
|
+
self.assertEqual(num_to_thai("100"), "หนึ่งร้อย")
|
|
31
|
+
self.assertEqual(num_to_thai("123"), "หนึ่งร้อยยี่สิบสาม")
|
|
32
|
+
self.assertEqual(num_to_thai("200"), "สองร้อย")
|
|
33
|
+
self.assertEqual(num_to_thai("999"), "เก้าร้อยเก้าสิบเก้า")
|
|
34
|
+
|
|
35
|
+
def test_thousands(self):
|
|
36
|
+
"""Test numbers 1000-9999"""
|
|
37
|
+
self.assertEqual(num_to_thai("1000"), "หนึ่งพัน")
|
|
38
|
+
self.assertEqual(num_to_thai("1234"), "หนึ่งพันสองร้อยสามสิบสี่")
|
|
39
|
+
self.assertEqual(num_to_thai("5000"), "ห้าพัน")
|
|
40
|
+
|
|
41
|
+
def test_ten_thousands(self):
|
|
42
|
+
"""Test numbers 10000-99999"""
|
|
43
|
+
self.assertEqual(num_to_thai("10000"), "หนึ่งหมื่น")
|
|
44
|
+
self.assertEqual(num_to_thai("50000"), "ห้าหมื่น")
|
|
45
|
+
|
|
46
|
+
def test_negative_numbers(self):
|
|
47
|
+
"""Test negative numbers"""
|
|
48
|
+
self.assertEqual(num_to_thai("-5"), "ลบห้า")
|
|
49
|
+
self.assertEqual(num_to_thai("-123"), "ลบหนึ่งร้อยยี่สิบสาม")
|
|
50
|
+
|
|
51
|
+
def test_decimal_numbers(self):
|
|
52
|
+
"""Test decimal numbers"""
|
|
53
|
+
result = num_to_thai("12.5")
|
|
54
|
+
self.assertIn("จุด", result)
|
|
55
|
+
self.assertIn("สิบสอง", result)
|
|
56
|
+
self.assertIn("ห้า", result)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestExpandMaiyamok(unittest.TestCase):
|
|
60
|
+
"""Test Thai repetition character (ๆ) expansion"""
|
|
61
|
+
|
|
62
|
+
def test_basic_maiyamok(self):
|
|
63
|
+
"""Test basic mai yamok expansion"""
|
|
64
|
+
self.assertEqual(expand_maiyamok("ดีๆ"), "ดีดี")
|
|
65
|
+
self.assertEqual(expand_maiyamok("ช้าๆ"), "ช้าช้า")
|
|
66
|
+
self.assertEqual(expand_maiyamok("คนๆ"), "คนคน")
|
|
67
|
+
|
|
68
|
+
def test_no_maiyamok(self):
|
|
69
|
+
"""Test text without mai yamok"""
|
|
70
|
+
self.assertEqual(expand_maiyamok("ภาษาไทย"), "ภาษาไทย")
|
|
71
|
+
self.assertEqual(expand_maiyamok("สวัสดี"), "สวัสดี")
|
|
72
|
+
|
|
73
|
+
def test_maiyamok_in_sentence(self):
|
|
74
|
+
"""Test mai yamok in longer sentences"""
|
|
75
|
+
result = expand_maiyamok("เดินช้าๆ")
|
|
76
|
+
self.assertNotIn("ๆ", result)
|
|
77
|
+
self.assertIn("ช้า", result)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class TestPreprocessText(unittest.TestCase):
|
|
81
|
+
"""Test full text preprocessing"""
|
|
82
|
+
|
|
83
|
+
def test_number_conversion(self):
|
|
84
|
+
"""Test number conversion in text"""
|
|
85
|
+
result = preprocess_text("ฉันมี 123 บาท")
|
|
86
|
+
self.assertNotIn("123", result)
|
|
87
|
+
self.assertIn("หนึ่งร้อยยี่สิบสาม", result)
|
|
88
|
+
|
|
89
|
+
def test_maiyamok_expansion(self):
|
|
90
|
+
"""Test mai yamok expansion in text"""
|
|
91
|
+
result = preprocess_text("ดีๆ")
|
|
92
|
+
self.assertEqual(result, "ดีดี")
|
|
93
|
+
|
|
94
|
+
def test_combined_preprocessing(self):
|
|
95
|
+
"""Test both number conversion and mai yamok expansion"""
|
|
96
|
+
result = preprocess_text("มี 5 คนๆ")
|
|
97
|
+
self.assertNotIn("5", result)
|
|
98
|
+
self.assertNotIn("ๆ", result)
|
|
99
|
+
self.assertIn("ห้า", result)
|
|
100
|
+
self.assertIn("คนคน", result)
|
|
101
|
+
|
|
102
|
+
def test_no_preprocessing_numbers(self):
|
|
103
|
+
"""Test with number preprocessing disabled"""
|
|
104
|
+
result = preprocess_text("มี 5 คน", expand_numbers=False)
|
|
105
|
+
self.assertIn("5", result)
|
|
106
|
+
|
|
107
|
+
def test_no_preprocessing_maiyamok(self):
|
|
108
|
+
"""Test with mai yamok preprocessing disabled"""
|
|
109
|
+
result = preprocess_text("ดีๆ", expand_maiyamok_char=False)
|
|
110
|
+
self.assertIn("ๆ", result)
|
|
111
|
+
|
|
112
|
+
def test_empty_text(self):
|
|
113
|
+
"""Test empty text"""
|
|
114
|
+
result = preprocess_text("")
|
|
115
|
+
self.assertEqual(result, "")
|
|
116
|
+
|
|
117
|
+
def test_text_without_preprocessing_needs(self):
|
|
118
|
+
"""Test text that doesn't need preprocessing"""
|
|
119
|
+
text = "ภาษาไทย ง่าย มาก"
|
|
120
|
+
result = preprocess_text(text)
|
|
121
|
+
self.assertEqual(result, text)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
if __name__ == '__main__':
|
|
125
|
+
unittest.main()
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Unit tests for VachanaTTS integration
|
|
4
|
+
"""
|
|
5
|
+
import unittest
|
|
6
|
+
from unittest.mock import Mock, patch, MagicMock
|
|
7
|
+
import numpy as np
|
|
8
|
+
from pythaitts import TTS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestVachanaIntegration(unittest.TestCase):
|
|
12
|
+
"""Test VachanaTTS integration"""
|
|
13
|
+
|
|
14
|
+
@patch('pythaitts.pretrained.vachana_tts.VachanaTTS')
|
|
15
|
+
def test_vachana_model_initialization(self, mock_vachana):
|
|
16
|
+
"""Test that VachanaTTS model can be initialized"""
|
|
17
|
+
# Create TTS instance with vachana model
|
|
18
|
+
tts = TTS(pretrained="vachana")
|
|
19
|
+
|
|
20
|
+
# Verify model is loaded
|
|
21
|
+
self.assertIsNotNone(tts.model)
|
|
22
|
+
self.assertEqual(tts.pretrained, "vachana")
|
|
23
|
+
|
|
24
|
+
@patch('pythaitts.pretrained.vachana_tts.VachanaTTS')
|
|
25
|
+
def test_vachana_tts_call(self, mock_vachana_class):
|
|
26
|
+
"""Test calling tts method with vachana model"""
|
|
27
|
+
# Setup mock
|
|
28
|
+
mock_instance = Mock()
|
|
29
|
+
mock_instance.return_value = "/tmp/output.wav"
|
|
30
|
+
mock_vachana_class.return_value = mock_instance
|
|
31
|
+
|
|
32
|
+
# Create TTS instance
|
|
33
|
+
tts = TTS(pretrained="vachana")
|
|
34
|
+
|
|
35
|
+
# Call tts method
|
|
36
|
+
result = tts.tts("สวัสดีครับ", speaker_idx="th_f_1", filename="/tmp/test.wav")
|
|
37
|
+
|
|
38
|
+
# Verify the model was called with correct parameters
|
|
39
|
+
mock_instance.assert_called_once()
|
|
40
|
+
call_args = mock_instance.call_args
|
|
41
|
+
self.assertEqual(call_args.kwargs['text'], "สวัสดีครับ")
|
|
42
|
+
self.assertEqual(call_args.kwargs['speaker_idx'], "th_f_1")
|
|
43
|
+
self.assertEqual(call_args.kwargs['filename'], "/tmp/test.wav")
|
|
44
|
+
self.assertEqual(call_args.kwargs['return_type'], "file")
|
|
45
|
+
|
|
46
|
+
@patch('pythaitts.pretrained.vachana_tts.VachanaTTS')
|
|
47
|
+
def test_vachana_with_preprocessing(self, mock_vachana_class):
|
|
48
|
+
"""Test that preprocessing works with vachana model"""
|
|
49
|
+
# Setup mock
|
|
50
|
+
mock_instance = Mock()
|
|
51
|
+
mock_instance.return_value = "/tmp/output.wav"
|
|
52
|
+
mock_vachana_class.return_value = mock_instance
|
|
53
|
+
|
|
54
|
+
# Create TTS instance
|
|
55
|
+
tts = TTS(pretrained="vachana")
|
|
56
|
+
|
|
57
|
+
# Call tts method with text that needs preprocessing
|
|
58
|
+
result = tts.tts("มี 5 คนๆ", speaker_idx="th_f_1", preprocess=True)
|
|
59
|
+
|
|
60
|
+
# Verify preprocessing was applied
|
|
61
|
+
mock_instance.assert_called_once()
|
|
62
|
+
call_args = mock_instance.call_args
|
|
63
|
+
processed_text = call_args.kwargs['text']
|
|
64
|
+
|
|
65
|
+
# Text should have numbers converted and ๆ expanded
|
|
66
|
+
self.assertNotIn("5", processed_text)
|
|
67
|
+
self.assertNotIn("ๆ", processed_text)
|
|
68
|
+
self.assertIn("ห้า", processed_text)
|
|
69
|
+
self.assertIn("คนคน", processed_text)
|
|
70
|
+
|
|
71
|
+
@patch('pythaitts.pretrained.vachana_tts.VachanaTTS')
|
|
72
|
+
def test_vachana_all_supported_voices(self, mock_vachana_class):
|
|
73
|
+
"""Test that all supported voices work correctly"""
|
|
74
|
+
# Setup mock
|
|
75
|
+
mock_instance = Mock()
|
|
76
|
+
mock_instance.return_value = "/tmp/output.wav"
|
|
77
|
+
mock_vachana_class.return_value = mock_instance
|
|
78
|
+
|
|
79
|
+
# Create TTS instance
|
|
80
|
+
tts = TTS(pretrained="vachana")
|
|
81
|
+
|
|
82
|
+
# Test all supported voices
|
|
83
|
+
supported_voices = ["th_f_1", "th_m_1", "th_f_2", "th_m_2"]
|
|
84
|
+
for voice in supported_voices:
|
|
85
|
+
mock_instance.reset_mock()
|
|
86
|
+
result = tts.tts("สวัสดี", speaker_idx=voice)
|
|
87
|
+
|
|
88
|
+
# Verify the voice was passed correctly
|
|
89
|
+
call_args = mock_instance.call_args
|
|
90
|
+
self.assertEqual(call_args.kwargs['speaker_idx'], voice)
|
|
91
|
+
|
|
92
|
+
@patch('pythaitts.pretrained.vachana_tts.VachanaTTS')
|
|
93
|
+
def test_vachana_waveform_return(self, mock_vachana_class):
|
|
94
|
+
"""Test waveform return type functionality"""
|
|
95
|
+
# Setup mock
|
|
96
|
+
mock_instance = Mock()
|
|
97
|
+
mock_waveform = np.array([0.1, 0.2, 0.3, 0.4])
|
|
98
|
+
mock_instance.return_value = mock_waveform
|
|
99
|
+
mock_vachana_class.return_value = mock_instance
|
|
100
|
+
|
|
101
|
+
# Create TTS instance
|
|
102
|
+
tts = TTS(pretrained="vachana")
|
|
103
|
+
|
|
104
|
+
# Call tts method with waveform return type
|
|
105
|
+
result = tts.tts("สวัสดี", speaker_idx="th_f_1", return_type="waveform")
|
|
106
|
+
|
|
107
|
+
# Verify the return type was set correctly
|
|
108
|
+
call_args = mock_instance.call_args
|
|
109
|
+
self.assertEqual(call_args.kwargs['return_type'], "waveform")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == '__main__':
|
|
113
|
+
unittest.main()
|
PyThaiTTS-0.3.0/PKG-INFO
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyThaiTTS
|
|
3
|
-
Version: 0.3.0
|
|
4
|
-
Summary: Open Source Thai Text-to-speech library in Python
|
|
5
|
-
Home-page: https://github.com/pythainlp/pythaitts
|
|
6
|
-
Author: Wannaphong
|
|
7
|
-
Author-email: wannaphong@yahoo.com
|
|
8
|
-
License: Apache Software License 2.0
|
|
9
|
-
Project-URL: Documentation, https://github.com/pythainlp/pythaitts
|
|
10
|
-
Project-URL: Source, https://github.com/pythainlp/pythaitts
|
|
11
|
-
Project-URL: Bug Reports, https://github.com/pythainlp/pythaitts/issues
|
|
12
|
-
Keywords: Thai,NLP,natural language processing,text analytics,text processing,localization,computational linguistics,text-to-speech
|
|
13
|
-
Classifier: Development Status :: 3 - Alpha
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Intended Audience :: Developers
|
|
16
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
-
Classifier: Topic :: Text Processing
|
|
19
|
-
Classifier: Topic :: Text Processing :: General
|
|
20
|
-
Classifier: Topic :: Text Processing :: Linguistic
|
|
21
|
-
Requires-Python: >=3.6
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
License-File: LICENSE
|
|
24
|
-
Requires-Dist: huggingface_hub
|
|
25
|
-
Requires-Dist: numpy>=1.22
|
|
26
|
-
Requires-Dist: onnxruntime
|
|
27
|
-
|
|
28
|
-
# PyThaiTTS
|
|
29
|
-
Open Source Thai Text-to-speech library in Python
|
|
30
|
-
|
|
31
|
-
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
32
|
-
|
|
33
|
-
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
34
|
-
|
|
35
|
-
## Install
|
|
36
|
-
|
|
37
|
-
Install by pip:
|
|
38
|
-
|
|
39
|
-
> pip install pythaitts
|
|
40
|
-
|
|
41
|
-
## Usage
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
from pythaitts import TTS
|
|
45
|
-
|
|
46
|
-
tts = TTS()
|
|
47
|
-
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
48
|
-
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: PyThaiTTS
|
|
3
|
-
Version: 0.3.0
|
|
4
|
-
Summary: Open Source Thai Text-to-speech library in Python
|
|
5
|
-
Home-page: https://github.com/pythainlp/pythaitts
|
|
6
|
-
Author: Wannaphong
|
|
7
|
-
Author-email: wannaphong@yahoo.com
|
|
8
|
-
License: Apache Software License 2.0
|
|
9
|
-
Project-URL: Documentation, https://github.com/pythainlp/pythaitts
|
|
10
|
-
Project-URL: Source, https://github.com/pythainlp/pythaitts
|
|
11
|
-
Project-URL: Bug Reports, https://github.com/pythainlp/pythaitts/issues
|
|
12
|
-
Keywords: Thai,NLP,natural language processing,text analytics,text processing,localization,computational linguistics,text-to-speech
|
|
13
|
-
Classifier: Development Status :: 3 - Alpha
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Intended Audience :: Developers
|
|
16
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
-
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
-
Classifier: Topic :: Text Processing
|
|
19
|
-
Classifier: Topic :: Text Processing :: General
|
|
20
|
-
Classifier: Topic :: Text Processing :: Linguistic
|
|
21
|
-
Requires-Python: >=3.6
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
License-File: LICENSE
|
|
24
|
-
Requires-Dist: huggingface_hub
|
|
25
|
-
Requires-Dist: numpy>=1.22
|
|
26
|
-
Requires-Dist: onnxruntime
|
|
27
|
-
|
|
28
|
-
# PyThaiTTS
|
|
29
|
-
Open Source Thai Text-to-speech library in Python
|
|
30
|
-
|
|
31
|
-
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
32
|
-
|
|
33
|
-
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
34
|
-
|
|
35
|
-
## Install
|
|
36
|
-
|
|
37
|
-
Install by pip:
|
|
38
|
-
|
|
39
|
-
> pip install pythaitts
|
|
40
|
-
|
|
41
|
-
## Usage
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
from pythaitts import TTS
|
|
45
|
-
|
|
46
|
-
tts = TTS()
|
|
47
|
-
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
48
|
-
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
PyThaiTTS-0.3.0/README.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# PyThaiTTS
|
|
2
|
-
Open Source Thai Text-to-speech library in Python
|
|
3
|
-
|
|
4
|
-
[Google Colab](https://colab.research.google.com/github/PyThaiNLP/PyThaiTTS/blob/dev/notebook/use_lunarlist_model.ipynb) | [Docs](https://pythainlp.github.io/PyThaiTTS/) | [Notebooks](https://github.com/PyThaiNLP/PyThaiTTS/tree/dev/notebook)
|
|
5
|
-
|
|
6
|
-
License: [Apache-2.0 License](https://github.com/PyThaiNLP/pythaitts/blob/main/LICENSE)
|
|
7
|
-
|
|
8
|
-
## Install
|
|
9
|
-
|
|
10
|
-
Install by pip:
|
|
11
|
-
|
|
12
|
-
> pip install pythaitts
|
|
13
|
-
|
|
14
|
-
## Usage
|
|
15
|
-
|
|
16
|
-
```python
|
|
17
|
-
from pythaitts import TTS
|
|
18
|
-
|
|
19
|
-
tts = TTS()
|
|
20
|
-
file = tts.tts("ภาษาไทย ง่าย มาก มาก", filename="cat.wav") # It will get wav file path.
|
|
21
|
-
wave = tts.tts("ภาษาไทย ง่าย มาก มาก",return_type="waveform") # It will get waveform.
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
You can see more at [https://pythainlp.github.io/PyThaiTTS/](https://pythainlp.github.io/PyThaiTTS/).
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|