yta-audio-narration 0.0.1__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.
@@ -0,0 +1,263 @@
1
+ """
2
+ For anything else you need, check this:
3
+ - https://www.tetyys.com/SAPI4/
4
+
5
+ Each voice has an specific pitch and speed
6
+ so please, pay attention to it. Here are
7
+ some examples of this:
8
+ 'Male Whisper' p: 113, s: 140
9
+ 'Female Whisper' p: 169, s: 140
10
+ 'Mary' p: 169, s: 140
11
+ """
12
+ from yta_audio_narration.consts import DEFAULT_VOICE
13
+ from yta_audio_narration.enums import NarrationLanguage, VoiceEmotion, VoiceSpeed, VoicePitch
14
+ from yta_audio_narration.voice import NarrationVoice
15
+ from yta_file.handler import FileHandler
16
+ from yta_constants.enum import YTAEnum as Enum
17
+ from yta_constants.file import FileType
18
+ from yta_programming.output import Output
19
+ from typing import Union
20
+
21
+ import requests
22
+
23
+
24
+ """
25
+ The options below are specified even if we
26
+ don't use them later when processing the
27
+ voice narration. This is to keep the same
28
+ structure for any voice narration and to
29
+ simplify the way we offer the options in
30
+ an API that is able to make requests.
31
+ """
32
+
33
+ # 1. The voices we accept, as Enums
34
+ class TetyysVoiceName(Enum):
35
+ """
36
+ Available voices. The value is what is used
37
+ for the audio creation.
38
+ """
39
+
40
+ DEFAULT = DEFAULT_VOICE
41
+ SAM = 'Sam'
42
+ MALE_WHISPER = 'Male Whisper'
43
+ FEMALE_WHISPER = 'Female Whisper'
44
+ MARY = 'Mary'
45
+ MARY_IN_SPACE = 'Mary in Space'
46
+ MIKE_IN_SPACE = 'Mike in Space'
47
+ ROBOSOFT_ONE = 'RobosoftOne'
48
+ # TODO: There are more voices
49
+
50
+ # 2. The languages we accept
51
+ LANGUAGE_OPTIONS = [
52
+ NarrationLanguage.ENGLISH,
53
+ NarrationLanguage.DEFAULT
54
+ ]
55
+
56
+ # 3. The emotions we accept
57
+ EMOTION_OPTIONS = [
58
+ VoiceEmotion.DEFAULT,
59
+ VoiceEmotion.NORMAL,
60
+ ]
61
+
62
+ # 4. The speeds we accept
63
+ SPEED_OPTIONS = [
64
+ VoiceSpeed.DEFAULT,
65
+ VoiceSpeed.NORMAL,
66
+ ]
67
+
68
+ # 5. The pitches we accept
69
+ PITCH_OPTIONS = [
70
+ VoicePitch.DEFAULT,
71
+ VoicePitch.NORMAL,
72
+ ]
73
+
74
+
75
+ class TetyysNarrationVoice(NarrationVoice):
76
+ """
77
+ Voice instance to be used when narrating with
78
+ Tiktok engine.
79
+ """
80
+
81
+ @property
82
+ def processed_name(
83
+ self
84
+ ) -> str:
85
+ """
86
+ Get the usable name value from the one that has
87
+ been set when instantiating the instance.
88
+ """
89
+ # TODO: Maybe this DEFAULT value has to exist
90
+ # for each language so it chooses one voice name
91
+ # for that language
92
+ return (
93
+ TetyysVoiceName.SAM.value
94
+ if TetyysVoiceName.to_enum(self.name) == TetyysVoiceName.DEFAULT else
95
+ TetyysVoiceName.to_enum(self.name).value
96
+ )
97
+
98
+ @property
99
+ def processed_emotion(
100
+ self
101
+ ) -> str:
102
+ """
103
+ Get the usable emotion value from the one that
104
+ has been set when instantiating the instance.
105
+ """
106
+ # This narration is not able to handle any
107
+ # emotion (at least by now)
108
+ return None
109
+
110
+ @property
111
+ def processed_speed(
112
+ self
113
+ ) -> int:
114
+ """
115
+ Get the usable speed value from the one that
116
+ has been set when instantiating the instance.
117
+ """
118
+ # By now all the voices I'm using have the same
119
+ # speed value so I'm just returning it
120
+ return 140
121
+
122
+ @property
123
+ def processed_pitch(
124
+ self
125
+ ) -> int:
126
+ """
127
+ Get the usable pitch value from the one that
128
+ has been set when instantiating the instance.
129
+ """
130
+ return {
131
+ TetyysVoiceName.MALE_WHISPER: 113,
132
+ TetyysVoiceName.FEMALE_WHISPER: 169,
133
+ TetyysVoiceName.MARY: 169,
134
+ TetyysVoiceName.MARY_IN_SPACE: 169,
135
+ TetyysVoiceName.MIKE_IN_SPACE: 113,
136
+ TetyysVoiceName.SAM: 100
137
+ }[TetyysVoiceName.to_enum(self.processed_name)]
138
+
139
+ @property
140
+ def processed_language(
141
+ self
142
+ ) -> str:
143
+ """
144
+ Get the usable language value from the one that
145
+ has been set when instantiating the instance.
146
+ """
147
+ # TODO: There is not language associated with this
148
+ # narration voice engine
149
+ return None
150
+
151
+ def validate_and_process(
152
+ self,
153
+ name: str,
154
+ emotion: VoiceEmotion,
155
+ speed: VoiceSpeed,
156
+ pitch: VoicePitch,
157
+ language: NarrationLanguage
158
+ ):
159
+ TetyysVoiceName.to_enum(name)
160
+ if VoiceEmotion.to_enum(emotion) not in EMOTION_OPTIONS:
161
+ raise Exception(f'The provided {emotion} is not valid for this narration voice.')
162
+ if VoiceSpeed.to_enum(speed) not in SPEED_OPTIONS:
163
+ raise Exception(f'The provided {speed} is not valid for this narration voice.')
164
+ if VoicePitch.to_enum(pitch) not in PITCH_OPTIONS:
165
+ raise Exception(f'The provided {pitch} is not valid for this narration voice.')
166
+ if NarrationLanguage.to_enum(language) not in LANGUAGE_OPTIONS:
167
+ raise Exception(f'The provided {language} is not valid for this narration voice.')
168
+
169
+ @staticmethod
170
+ def default():
171
+ return TetyysNarrationVoice(
172
+ name = TetyysVoiceName.DEFAULT.value,
173
+ emotion = VoiceEmotion.DEFAULT,
174
+ speed = VoiceSpeed.DEFAULT,
175
+ pitch = VoicePitch.DEFAULT,
176
+ language = NarrationLanguage.DEFAULT
177
+ )
178
+
179
+
180
+ # The voices but for a specific language, to be able to
181
+ # choose one when this is requested from the outside
182
+ def get_narrator_names_by_language(
183
+ language: NarrationLanguage
184
+ ) -> list[str]:
185
+ language = NarrationLanguage.to_enum(language)
186
+ language = (
187
+ NarrationLanguage.ENGLISH
188
+ if language is NarrationLanguage.DEFAULT else
189
+ language
190
+ )
191
+
192
+ return {
193
+ NarrationLanguage.ENGLISH: [
194
+ TetyysVoiceName.DEFAULT.value,
195
+ TetyysVoiceName.SAM.value,
196
+ TetyysVoiceName.MALE_WHISPER.value,
197
+ TetyysVoiceName.FEMALE_WHISPER.value,
198
+ TetyysVoiceName.MARY.value,
199
+ TetyysVoiceName.MARY_IN_SPACE.value,
200
+ TetyysVoiceName.MIKE_IN_SPACE.value,
201
+ ]
202
+ }[language]
203
+
204
+ # All the remaining functionality we need to make it
205
+ # work properly
206
+ def narrate_tetyys(
207
+ text: str,
208
+ voice: TetyysNarrationVoice = TetyysNarrationVoice.default(),
209
+ output_filename: Union[str, None] = None
210
+ ) -> str:
211
+ """
212
+ This method creates an audio voice narration of the provided
213
+ 'text' read with tthe tetyys system voice (Microsoft Speech
214
+ API 4.0 from 1998) and stores it as 'output_filename'. It is
215
+ only available for ENGLISH speaking.
216
+
217
+ You can change some voice parameters in code to make it a
218
+ different voice.
219
+
220
+ This method is requesting an external (but apparently stable
221
+ website).
222
+
223
+ This method returns the filename that has been written.
224
+ """
225
+ headers = {
226
+ 'accept': '*/*',
227
+ 'accept-language': 'es-ES,es;q=0.9',
228
+ 'priority': 'u=1, i',
229
+ 'referer': 'https://www.tetyys.com/SAPI4/',
230
+ 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
231
+ 'sec-ch-ua-mobile': '?0',
232
+ 'sec-ch-ua-platform': '"Windows"',
233
+ 'sec-fetch-dest': 'empty',
234
+ 'sec-fetch-mode': 'cors',
235
+ 'sec-fetch-site': 'same-origin',
236
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
237
+ }
238
+
239
+ params = {
240
+ 'text': text,
241
+ # Inspect options 'value' from https://www.tetyys.com/SAPI4/ but
242
+ # each voice has a pre-set 'pitch' and 'speed'
243
+ 'voice': voice.processed_name,
244
+ 'pitch': str(voice.processed_pitch),
245
+ 'speed': str(voice.processed_speed)
246
+ }
247
+
248
+ """
249
+ Some VOICE options:
250
+ 'Male Whisper' 113, 140
251
+ 'Female Whisper' 169, 140
252
+ 'Mary' 169, 140
253
+ 'Mary in Space'|'Mary in Hall'|'Mary in Stadium'|Mary (for Telephone) 169, 140
254
+ 'Mike in Space'|... 113, 140
255
+ 'RobosoftOne'|'RobosoftTwo'
256
+ 'Sam' 100, 140
257
+ """
258
+
259
+ output_filename = Output.get_filename(output_filename, FileType.AUDIO)
260
+
261
+ response = requests.get('https://www.tetyys.com/SAPI4/SAPI4', params = params, headers = headers)
262
+
263
+ return FileHandler.write_binary(output_filename, response.content)
@@ -0,0 +1,232 @@
1
+ """
2
+ This was extracted from here:
3
+ - https://gesserit.co/tiktok
4
+
5
+ And you have more projects here:
6
+ - Project to use Tiktok API and cookie (https://github.com/Steve0929/tiktok-tts)
7
+ - Pproject to use Tiktok API and session id (https://github.com/oscie57/tiktok-voice)
8
+ - Project that is install and play (I think) https://github.com/Giooorgiooo/TikTok-Voice-TTS/blob/main/tiktokvoice.py
9
+ """
10
+ from yta_audio_narration.consts import DEFAULT_VOICE
11
+ from yta_audio_narration.enums import NarrationLanguage, VoiceEmotion, VoiceSpeed, VoicePitch
12
+ from yta_audio_narration.voice import NarrationVoice
13
+ from yta_text.handler import TextHandler
14
+ from yta_file.handler import FileHandler
15
+ from yta_constants.enum import YTAEnum as Enum
16
+ from yta_constants.file import FileType
17
+ from yta_programming.output import Output
18
+ from typing import Union
19
+
20
+ import requests
21
+ import base64
22
+
23
+
24
+ """
25
+ The options below are specified even if we
26
+ don't use them later when processing the
27
+ voice narration. This is to keep the same
28
+ structure for any voice narration and to
29
+ simplify the way we offer the options in
30
+ an API that is able to make requests.
31
+ """
32
+
33
+ # 1. The voices we accept, as Enums
34
+ class TiktokVoiceName(Enum):
35
+ """
36
+ Available voices. The value is what is used
37
+ for the audio creation.
38
+ """
39
+
40
+ DEFAULT = DEFAULT_VOICE
41
+ SPANISH = 'es_002'
42
+ MEXICAN = 'es_mx_002'
43
+ # TODO: There a a lot of English US and more languages voices
44
+
45
+ # 2. The languages we accept
46
+ LANGUAGE_OPTIONS = [
47
+ NarrationLanguage.SPANISH,
48
+ NarrationLanguage.DEFAULT
49
+ ]
50
+
51
+ # 3. The emotions we accept
52
+ EMOTION_OPTIONS = [
53
+ VoiceEmotion.DEFAULT,
54
+ VoiceEmotion.NORMAL,
55
+ ]
56
+
57
+ # 4. The speeds we accept
58
+ SPEED_OPTIONS = [
59
+ VoiceSpeed.DEFAULT,
60
+ VoiceSpeed.NORMAL,
61
+ ]
62
+
63
+ # 5. The pitches we accept
64
+ PITCH_OPTIONS = [
65
+ VoicePitch.DEFAULT,
66
+ VoicePitch.NORMAL,
67
+ ]
68
+
69
+ class TiktokNarrationVoice(NarrationVoice):
70
+ """
71
+ Voice instance to be used when narrating with
72
+ Tiktok engine.
73
+ """
74
+
75
+ @property
76
+ def processed_name(
77
+ self
78
+ ) -> str:
79
+ """
80
+ Get the usable name value from the one that has
81
+ been set when instantiating the instance.
82
+ """
83
+ # TODO: Maybe this DEFAULT value has to exist
84
+ # for each language so it chooses one voice name
85
+ # for that language
86
+ return (
87
+ TiktokVoiceName.SPANISH.value
88
+ if TiktokVoiceName.to_enum(self.name) == TiktokVoiceName.DEFAULT else
89
+ TiktokVoiceName.to_enum(self.name).value
90
+ )
91
+
92
+ @property
93
+ def processed_emotion(
94
+ self
95
+ ) -> str:
96
+ """
97
+ Get the usable emotion value from the one that
98
+ has been set when instantiating the instance.
99
+ """
100
+ # This narration is not able to handle any
101
+ # emotion (at least by now)
102
+ return None
103
+
104
+ @property
105
+ def processed_speed(
106
+ self
107
+ ) -> int:
108
+ """
109
+ Get the usable speed value from the one that
110
+ has been set when instantiating the instance.
111
+ """
112
+ # This is not used here
113
+ return None
114
+
115
+ @property
116
+ def processed_pitch(
117
+ self
118
+ ) -> int:
119
+ """
120
+ Get the usable pitch value from the one that
121
+ has been set when instantiating the instance.
122
+ """
123
+ # This is not used here
124
+ return None
125
+
126
+ @property
127
+ def processed_language(
128
+ self
129
+ ) -> str:
130
+ """
131
+ Get the usable language value from the one that
132
+ has been set when instantiating the instance.
133
+ """
134
+ # TODO: There is not language associated with this
135
+ # narration voice engine. The language is set in
136
+ # the voice name
137
+ return None
138
+
139
+ def validate_and_process(
140
+ self,
141
+ name: str,
142
+ emotion: VoiceEmotion,
143
+ speed: VoiceSpeed,
144
+ pitch: VoicePitch,
145
+ language: NarrationLanguage
146
+ ):
147
+ TiktokVoiceName.to_enum(name)
148
+ if VoiceEmotion.to_enum(emotion) not in EMOTION_OPTIONS:
149
+ raise Exception(f'The provided {emotion} is not valid for this narration voice.')
150
+ if VoiceSpeed.to_enum(speed) not in SPEED_OPTIONS:
151
+ raise Exception(f'The provided {speed} is not valid for this narration voice.')
152
+ if VoicePitch.to_enum(pitch) not in PITCH_OPTIONS:
153
+ raise Exception(f'The provided {pitch} is not valid for this narration voice.')
154
+ if NarrationLanguage.to_enum(language) not in LANGUAGE_OPTIONS:
155
+ raise Exception(f'The provided {language} is not valid for this narration voice.')
156
+
157
+ @staticmethod
158
+ def default():
159
+ return TiktokNarrationVoice(
160
+ name = TiktokVoiceName.DEFAULT.value,
161
+ emotion = VoiceEmotion.DEFAULT,
162
+ speed = VoiceSpeed.DEFAULT,
163
+ pitch = VoicePitch.DEFAULT,
164
+ language = NarrationLanguage.DEFAULT
165
+ )
166
+
167
+ # The voices but for a specific language, to be able to
168
+ # choose one when this is requested from the outside
169
+ def get_narrator_names_by_language(
170
+ language: NarrationLanguage
171
+ ) -> list[str]:
172
+ language = NarrationLanguage.to_enum(language)
173
+ language = (
174
+ NarrationLanguage.SPANISH
175
+ if language is NarrationLanguage.DEFAULT else
176
+ language
177
+ )
178
+
179
+ return {
180
+ NarrationLanguage.SPANISH: [
181
+ TiktokVoiceName.DEFAULT.value,
182
+ TiktokVoiceName.SPANISH.value,
183
+ TiktokVoiceName.MEXICAN.value
184
+ ]
185
+ }[language]
186
+
187
+ # All the remaining functionality we need to make it
188
+ # work properly
189
+ def narrate_tiktok(
190
+ text: str,
191
+ voice: TiktokNarrationVoice = TiktokNarrationVoice.default(),
192
+ output_filename: Union[str, None] = None
193
+ ) -> str:
194
+ """
195
+ This is the tiktok voice based on a platform that generates it.
196
+ This will make a narration with the tiktok voice. You can
197
+ change the code to use the mexican voice.
198
+
199
+ As this is based on an external platform, it could fail.
200
+
201
+ This method returns the filename that has been written.
202
+ """
203
+ headers = {
204
+ 'accept': '*/*',
205
+ 'accept-language': 'es-ES,es;q=0.9',
206
+ 'content-type': 'text/plain;charset=UTF-8',
207
+ 'origin': 'https://gesserit.co',
208
+ 'referer': 'https://gesserit.co/tiktok',
209
+ 'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
210
+ 'sec-ch-ua-mobile': '?0',
211
+ 'sec-ch-ua-platform': '"Windows"',
212
+ 'sec-fetch-dest': 'empty',
213
+ 'sec-fetch-mode': 'cors',
214
+ 'sec-fetch-site': 'same-origin',
215
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
216
+ }
217
+
218
+ # Non-English characters are not accepted by Tiktok TTS generation, so:
219
+ text = TextHandler.remove_non_ascii_characters(text)
220
+
221
+ #data = f'{"text":"{text}","voice":"{voice.name}"}'
222
+ data = '{"text":"' + text + '","voice":"' + voice.processed_name + '"}'
223
+
224
+ base64_content = requests.post('https://gesserit.co/api/tiktok-tts', headers = headers, data = data).json()['base64']
225
+
226
+ output_filename = Output.get_filename(output_filename, FileType.AUDIO)
227
+
228
+ return FileHandler.write_binary(
229
+ filename = output_filename,
230
+ binary_data = base64.b64decode(base64_content)
231
+ )
232
+
@@ -0,0 +1,217 @@
1
+ """
2
+ This voice engine is based in Coqui and I
3
+ have another voice engine which is Coqui,
4
+ but using other voice narrators.
5
+
6
+ TODO: Consider mixing both voice engines
7
+ and appending this voice narrator to the
8
+ Coqui system and keep only one of them.
9
+
10
+ -- Update 19/04/2025 --
11
+ I've found that they created a fork in
12
+ https://github.com/idiap/coqui-ai-TTS with
13
+ a new version that is maintained, and the
14
+ 'tts' was generating conflicts.
15
+ """
16
+ from yta_audio_narration.consts import DEFAULT_VOICE
17
+ from yta_audio_narration.enums import NarrationLanguage, VoiceEmotion, VoiceSpeed, VoicePitch
18
+ from yta_audio_narration.voice import NarrationVoice
19
+ from yta_constants.enum import YTAEnum as Enum
20
+ from yta_constants.file import FileType
21
+ from yta_programming.output import Output
22
+ from typing import Union
23
+ from TTS.api import TTS
24
+
25
+
26
+ """
27
+ The options below are specified even if we
28
+ don't use them later when processing the
29
+ voice narration. This is to keep the same
30
+ structure for any voice narration and to
31
+ simplify the way we offer the options in
32
+ an API that is able to make requests.
33
+ """
34
+
35
+ # 1. The voices we accept, as Enums
36
+ class TortoiseVoiceName(Enum):
37
+ """
38
+ Available voices. The value is what is used
39
+ for the audio creation.
40
+ """
41
+
42
+ DEFAULT = DEFAULT_VOICE
43
+ SPANISH = 'es_002'
44
+ MEXICAN = 'es_mx_002'
45
+ # TODO: There a a lot of English US and more languages voices
46
+
47
+ # 2. The languages we accept
48
+ LANGUAGE_OPTIONS = [
49
+ NarrationLanguage.SPANISH,
50
+ NarrationLanguage.DEFAULT
51
+ ]
52
+
53
+ # 3. The emotions we accept
54
+ EMOTION_OPTIONS = [
55
+ VoiceEmotion.DEFAULT,
56
+ VoiceEmotion.NORMAL,
57
+ ]
58
+
59
+ # 4. The speeds we accept
60
+ SPEED_OPTIONS = [
61
+ VoiceSpeed.DEFAULT,
62
+ VoiceSpeed.NORMAL,
63
+ ]
64
+
65
+ # 5. The pitches we accept
66
+ PITCH_OPTIONS = [
67
+ VoicePitch.DEFAULT,
68
+ VoicePitch.NORMAL,
69
+ ]
70
+
71
+ class TortoiseNarrationVoice(NarrationVoice):
72
+ """
73
+ Voice instance to be used when narrating with
74
+ Tortoise engine.
75
+ """
76
+
77
+ @property
78
+ def processed_name(
79
+ self
80
+ ) -> str:
81
+ """
82
+ Get the usable name value from the one that has
83
+ been set when instantiating the instance.
84
+ """
85
+ # TODO: We are not using voice names here
86
+ return None
87
+
88
+ @property
89
+ def processed_emotion(
90
+ self
91
+ ) -> str:
92
+ """
93
+ Get the usable emotion value from the one that
94
+ has been set when instantiating the instance.
95
+ """
96
+ # This narration is not able to handle any
97
+ # emotion (at least by now)
98
+ return None
99
+
100
+ @property
101
+ def processed_speed(
102
+ self
103
+ ) -> int:
104
+ """
105
+ Get the usable speed value from the one that
106
+ has been set when instantiating the instance.
107
+ """
108
+ # This is not used here
109
+ return None
110
+
111
+ @property
112
+ def processed_pitch(
113
+ self
114
+ ) -> int:
115
+ """
116
+ Get the usable pitch value from the one that
117
+ has been set when instantiating the instance.
118
+ """
119
+ # This is not used here
120
+ return None
121
+
122
+ @property
123
+ def processed_language(
124
+ self
125
+ ) -> str:
126
+ """
127
+ Get the usable language value from the one that
128
+ has been set when instantiating the instance.
129
+ """
130
+ language = (
131
+ NarrationLanguage.SPANISH
132
+ if self.language == NarrationLanguage.DEFAULT else
133
+ self.language
134
+ )
135
+
136
+ return {
137
+ NarrationLanguage.SPANISH: 'es'
138
+ }[language]
139
+
140
+ def validate_and_process(
141
+ self,
142
+ name: str,
143
+ emotion: VoiceEmotion,
144
+ speed: VoiceSpeed,
145
+ pitch: VoicePitch,
146
+ language: NarrationLanguage
147
+ ):
148
+ TortoiseVoiceName.to_enum(name)
149
+ if VoiceEmotion.to_enum(emotion) not in EMOTION_OPTIONS:
150
+ raise Exception(f'The provided {emotion} is not valid for this narration voice.')
151
+ if VoiceSpeed.to_enum(speed) not in SPEED_OPTIONS:
152
+ raise Exception(f'The provided {speed} is not valid for this narration voice.')
153
+ if VoicePitch.to_enum(pitch) not in PITCH_OPTIONS:
154
+ raise Exception(f'The provided {pitch} is not valid for this narration voice.')
155
+ if NarrationLanguage.to_enum(language) not in LANGUAGE_OPTIONS:
156
+ raise Exception(f'The provided {language} is not valid for this narration voice.')
157
+
158
+ @staticmethod
159
+ def default():
160
+ return TortoiseNarrationVoice(
161
+ name = TortoiseVoiceName.DEFAULT.value,
162
+ emotion = VoiceEmotion.DEFAULT,
163
+ speed = VoiceSpeed.DEFAULT,
164
+ pitch = VoicePitch.DEFAULT,
165
+ language = NarrationLanguage.DEFAULT
166
+ )
167
+
168
+ # The voices but for a specific language, to be able to
169
+ # choose one when this is requested from the outside
170
+ def get_narrator_names_by_language(
171
+ language: NarrationLanguage
172
+ ) -> list[str]:
173
+ language = NarrationLanguage.to_enum(language)
174
+ language = (
175
+ NarrationLanguage.SPANISH
176
+ if language is NarrationLanguage.DEFAULT else
177
+ language
178
+ )
179
+
180
+ return {
181
+ NarrationLanguage.SPANISH: [
182
+ TortoiseVoiceName.DEFAULT.value,
183
+ ]
184
+ }[language]
185
+
186
+ # All the remaining functionality we need to make it
187
+ # work properly
188
+ def narrate(
189
+ text: str,
190
+ voice: TortoiseNarrationVoice = TortoiseNarrationVoice.default(),
191
+ output_filename: Union[str, None] = None
192
+ ):
193
+ """
194
+ @deprecated
195
+
196
+ TODO: Remove this file and method if useless. Please, read below to check.
197
+ This method should be removed and also the file as it is only one specific
198
+ model in TTS narration library. It is not a different system. So please,
199
+ remove it if it won't be used.
200
+ """
201
+ output_filename = Output.get_filename(output_filename, FileType.AUDIO)
202
+
203
+ # TODO: Delete tortoise lib?
204
+ # TODO: Delete en/multi-datase/tortoise-v2 model
205
+ tts = TTS("tts_models/es/multi-dataset/tortoise-v2")
206
+
207
+ # Check code here: https://docs.coqui.ai/en/latest/models/tortoise.html
208
+ tts.tts_to_file(text = text, language = voice.processed_language, file_path = output_filename)
209
+
210
+ return output_filename
211
+
212
+ #reference_clips = [utils.audio.load_audio(p, 22050) for p in clips_paths]
213
+
214
+ #pcm_audio = tts.tts(text)
215
+ #pcm_audio = tts.tts_with_preset("your text here", voice_samples=reference_clips, preset='fast')
216
+
217
+ #from tortoise.utils.audio import load_audio, load_voice