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.
- yta_audio_narration/__init__.py +3 -0
- yta_audio_narration/consts.py +1 -0
- yta_audio_narration/enums.py +377 -0
- yta_audio_narration/narrator.py +552 -0
- yta_audio_narration/voice.py +88 -0
- yta_audio_narration/voices/__init__.py +0 -0
- yta_audio_narration/voices/coqui.py +278 -0
- yta_audio_narration/voices/google.py +266 -0
- yta_audio_narration/voices/microsoft.py +209 -0
- yta_audio_narration/voices/open_voice.py +348 -0
- yta_audio_narration/voices/tetyys.py +263 -0
- yta_audio_narration/voices/tiktok.py +232 -0
- yta_audio_narration/voices/tortoise.py +217 -0
- yta_audio_narration/voices/ttsmp3.py +266 -0
- yta_audio_narration-0.0.1.dist-info/LICENSE +19 -0
- yta_audio_narration-0.0.1.dist-info/METADATA +27 -0
- yta_audio_narration-0.0.1.dist-info/RECORD +18 -0
- yta_audio_narration-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,552 @@
|
|
1
|
+
from yta_audio_narration.voice import NarrationVoice
|
2
|
+
from yta_audio_narration.enums import NarrationLanguage, VoiceEmotion, VoiceSpeed, VoicePitch
|
3
|
+
from yta_audio_narration.voices.coqui import narrate as narrate_coqui, CoquiNarrationVoice, LANGUAGE_OPTIONS as COQUI_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_coqui_narrator_names_by_language, EMOTION_OPTIONS as COQUI_EMOTION_OPTIONS, SPEED_OPTIONS as COQUI_SPEED_OPTIONS, PITCH_OPTIONS as COQUI_PITCH_OPTIONS, CoquiVoiceName
|
4
|
+
from yta_audio_narration.voices.google import narrate as narrate_google, GoogleNarrationVoice, LANGUAGE_OPTIONS as GOOGLE_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_google_narrator_names_by_language, EMOTION_OPTIONS as GOOGLE_EMOTION_OPTIONS, SPEED_OPTIONS as GOOGLE_SPEED_OPTIONS, PITCH_OPTIONS as GOOGLE_PITCH_OPTIONS, GoogleTld
|
5
|
+
from yta_audio_narration.voices.microsoft import narrate as narrate_microsoft, MicrosoftNarrationVoice, LANGUAGE_OPTIONS as MICROSOFT_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_microsoft_narrator_names_by_language, EMOTION_OPTIONS as MICROSOFT_EMOTION_OPTIONS, SPEED_OPTIONS as MICROSOFT_SPEED_OPTIONS, PITCH_OPTIONS as MICROSOFT_PITCH_OPTIONS, MicrosoftVoiceName
|
6
|
+
# from yta_audio_narration.voices.open_voice import narrate as narrate_open_voice, OpenVoiceNarrationVoice, LANGUAGE_OPTIONS as OPEN_VOICE_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_open_voice_narrator_names_by_language, EMOTION_OPTIONS as OPEN_VOICE_EMOTION_OPTIONS, SPEED_OPTIONS as OPEN_VOICE_SPEED_OPTIONS, PITCH_OPTIONS as OPEN_VOICE_PITCH_OPTIONS, OpenVoiceVoiceName
|
7
|
+
from yta_audio_narration.voices.tetyys import narrate_tetyys, TetyysNarrationVoice, LANGUAGE_OPTIONS as TETYYS_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_tetyys_narrator_names_by_language, EMOTION_OPTIONS as TETYYS_EMOTION_OPTIONS, SPEED_OPTIONS as TETYYS_SPEED_OPTIONS, PITCH_OPTIONS as TETYYS_PITCH_OPTIONS, TetyysVoiceName
|
8
|
+
from yta_audio_narration.voices.tiktok import narrate_tiktok, TiktokNarrationVoice, LANGUAGE_OPTIONS as TIKTOK_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_tiktok_narrator_names_by_language, EMOTION_OPTIONS as TIKTOK_EMOTION_OPTIONS, SPEED_OPTIONS as TIKTOK_SPEED_OPTIONS, PITCH_OPTIONS as TIKTOK_PITCH_OPTIONS, TiktokVoiceName
|
9
|
+
from yta_audio_narration.voices.tortoise import narrate as narrate_tortoise, TortoiseNarrationVoice, LANGUAGE_OPTIONS as TORTOISE_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_tortoise_narrator_names_by_language, EMOTION_OPTIONS as TORTOISE_EMOTION_OPTIONS, SPEED_OPTIONS as TORTOISE_SPEED_OPTIONS, PITCH_OPTIONS as TORTOISE_PITCH_OPTIONS, TortoiseVoiceName
|
10
|
+
from yta_audio_narration.voices.ttsmp3 import narrate_tts3, Ttsmp3NarrationVoice, LANGUAGE_OPTIONS as TTSMP3_LANGUAGE_OPTIONS, get_narrator_names_by_language as get_ttsmp3_narrator_names_by_language, EMOTION_OPTIONS as TTSMP3_EMOTION_OPTIONS, SPEED_OPTIONS as TTSMP3_SPEED_OPTIONS, PITCH_OPTIONS as TTSMP3_PITCH_OPTIONS, Ttsmp3VoiceName
|
11
|
+
from yta_validation.parameter import ParameterValidator
|
12
|
+
from yta_programming.output import Output
|
13
|
+
from yta_constants.file import FileType
|
14
|
+
from abc import ABC, abstractmethod
|
15
|
+
from typing import Union
|
16
|
+
|
17
|
+
|
18
|
+
class VoiceNarrator(ABC):
|
19
|
+
"""
|
20
|
+
Class to simplify and encapsulate the voice
|
21
|
+
narration functionality.
|
22
|
+
"""
|
23
|
+
|
24
|
+
@staticmethod
|
25
|
+
@abstractmethod
|
26
|
+
def narrate(
|
27
|
+
text: str,
|
28
|
+
voice: NarrationVoice = NarrationVoice.default(),
|
29
|
+
output_filename: Union[str, None] = None
|
30
|
+
):
|
31
|
+
"""
|
32
|
+
Create a voice narration of the given 'text' and
|
33
|
+
stores it locally in the 'output_filename'
|
34
|
+
provided (or in a temporary file if not provided).
|
35
|
+
"""
|
36
|
+
pass
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
@abstractmethod
|
40
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
41
|
+
"""
|
42
|
+
Get the list of the languages that are available
|
43
|
+
to be used in the voice narration.
|
44
|
+
|
45
|
+
This method must be overwritten.
|
46
|
+
"""
|
47
|
+
pass
|
48
|
+
|
49
|
+
@staticmethod
|
50
|
+
@abstractmethod
|
51
|
+
def get_available_narrator_names(
|
52
|
+
language: NarrationLanguage
|
53
|
+
) -> list[str]:
|
54
|
+
"""
|
55
|
+
Get the list of the narrator names that are
|
56
|
+
available for the given 'language' to be used
|
57
|
+
in the voice narration.
|
58
|
+
|
59
|
+
This method must be overwritten.
|
60
|
+
"""
|
61
|
+
pass
|
62
|
+
|
63
|
+
@staticmethod
|
64
|
+
@abstractmethod
|
65
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
66
|
+
"""
|
67
|
+
Get the list of the emotions that are
|
68
|
+
available to be used when narrating the
|
69
|
+
text.
|
70
|
+
|
71
|
+
This method must be overwritten.
|
72
|
+
"""
|
73
|
+
pass
|
74
|
+
|
75
|
+
@staticmethod
|
76
|
+
@abstractmethod
|
77
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
78
|
+
"""
|
79
|
+
Get the list of the speeds that are
|
80
|
+
available to be used when narrating the
|
81
|
+
text.
|
82
|
+
|
83
|
+
This method must be overwritten.
|
84
|
+
"""
|
85
|
+
pass
|
86
|
+
|
87
|
+
@staticmethod
|
88
|
+
@abstractmethod
|
89
|
+
def get_available_pitches() -> list[VoicePitch]:
|
90
|
+
"""
|
91
|
+
Get the list of the pitches that are
|
92
|
+
available to be used when narrating the
|
93
|
+
text.
|
94
|
+
|
95
|
+
This method must be overwritten.
|
96
|
+
"""
|
97
|
+
pass
|
98
|
+
|
99
|
+
class CoquiVoiceNarrator(VoiceNarrator):
|
100
|
+
|
101
|
+
@staticmethod
|
102
|
+
def narrate(
|
103
|
+
text: str,
|
104
|
+
name: CoquiVoiceName = CoquiVoiceName.DEFAULT,
|
105
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
106
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
107
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
108
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
109
|
+
output_filename: Union[str, None] = None
|
110
|
+
):
|
111
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
112
|
+
name = CoquiVoiceName.to_enum(name)
|
113
|
+
|
114
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
115
|
+
|
116
|
+
voice = CoquiNarrationVoice(
|
117
|
+
name = name.value,
|
118
|
+
emotion = emotion,
|
119
|
+
speed = speed,
|
120
|
+
pitch = pitch,
|
121
|
+
language = language
|
122
|
+
)
|
123
|
+
|
124
|
+
# TODO: Maybe return a FileReturn (?)
|
125
|
+
return narrate_coqui(text, voice, output_filename = output_filename)
|
126
|
+
|
127
|
+
@staticmethod
|
128
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
129
|
+
return COQUI_LANGUAGE_OPTIONS
|
130
|
+
|
131
|
+
@staticmethod
|
132
|
+
def get_available_narrator_names(
|
133
|
+
language: NarrationLanguage
|
134
|
+
) -> list[str]:
|
135
|
+
language = NarrationLanguage.to_enum(language)
|
136
|
+
|
137
|
+
return get_coqui_narrator_names_by_language(language)
|
138
|
+
|
139
|
+
@staticmethod
|
140
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
141
|
+
return COQUI_EMOTION_OPTIONS
|
142
|
+
|
143
|
+
@staticmethod
|
144
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
145
|
+
return COQUI_SPEED_OPTIONS
|
146
|
+
|
147
|
+
@staticmethod
|
148
|
+
def get_available_pitches() -> list[VoicePitch]:
|
149
|
+
return COQUI_PITCH_OPTIONS
|
150
|
+
|
151
|
+
class GoogleVoiceNarrator(VoiceNarrator):
|
152
|
+
|
153
|
+
@staticmethod
|
154
|
+
def narrate(
|
155
|
+
text: str,
|
156
|
+
name: GoogleTld = GoogleTld.DEFAULT,
|
157
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
158
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
159
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
160
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
161
|
+
output_filename: Union[str, None] = None
|
162
|
+
):
|
163
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
164
|
+
name = GoogleTld.to_enum(name)
|
165
|
+
|
166
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
167
|
+
|
168
|
+
voice = GoogleNarrationVoice(
|
169
|
+
name = name.value,
|
170
|
+
emotion = emotion,
|
171
|
+
speed = speed,
|
172
|
+
pitch = pitch,
|
173
|
+
language = language
|
174
|
+
)
|
175
|
+
|
176
|
+
# TODO: Maybe return a FileReturn (?)
|
177
|
+
return narrate_google(text, voice, output_filename = output_filename)
|
178
|
+
|
179
|
+
@staticmethod
|
180
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
181
|
+
return GOOGLE_LANGUAGE_OPTIONS
|
182
|
+
|
183
|
+
@staticmethod
|
184
|
+
def get_available_narrator_names(
|
185
|
+
language: NarrationLanguage
|
186
|
+
) -> list[str]:
|
187
|
+
language = NarrationLanguage.to_enum(language)
|
188
|
+
|
189
|
+
return get_google_narrator_names_by_language(language)
|
190
|
+
|
191
|
+
@staticmethod
|
192
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
193
|
+
return GOOGLE_EMOTION_OPTIONS
|
194
|
+
|
195
|
+
@staticmethod
|
196
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
197
|
+
return GOOGLE_SPEED_OPTIONS
|
198
|
+
|
199
|
+
@staticmethod
|
200
|
+
def get_available_pitches() -> list[VoicePitch]:
|
201
|
+
return GOOGLE_PITCH_OPTIONS
|
202
|
+
|
203
|
+
class MicrosoftVoiceNarrator(VoiceNarrator):
|
204
|
+
|
205
|
+
@staticmethod
|
206
|
+
def narrate(
|
207
|
+
text: str,
|
208
|
+
name: MicrosoftVoiceName = MicrosoftVoiceName.DEFAULT,
|
209
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
210
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
211
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
212
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
213
|
+
output_filename: Union[str, None] = None
|
214
|
+
):
|
215
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
216
|
+
name = MicrosoftVoiceName.to_enum(name)
|
217
|
+
|
218
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
219
|
+
|
220
|
+
voice = MicrosoftNarrationVoice(
|
221
|
+
name = name.value,
|
222
|
+
emotion = emotion,
|
223
|
+
speed = speed,
|
224
|
+
pitch = pitch,
|
225
|
+
language = language
|
226
|
+
)
|
227
|
+
|
228
|
+
# TODO: Maybe return a FileReturn (?)
|
229
|
+
return narrate_microsoft(text, voice, output_filename = output_filename)
|
230
|
+
|
231
|
+
@staticmethod
|
232
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
233
|
+
return MICROSOFT_LANGUAGE_OPTIONS
|
234
|
+
|
235
|
+
@staticmethod
|
236
|
+
def get_available_narrator_names(
|
237
|
+
language: NarrationLanguage
|
238
|
+
) -> list[str]:
|
239
|
+
language = NarrationLanguage.to_enum(language)
|
240
|
+
|
241
|
+
return get_microsoft_narrator_names_by_language(language)
|
242
|
+
|
243
|
+
@staticmethod
|
244
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
245
|
+
return MICROSOFT_EMOTION_OPTIONS
|
246
|
+
|
247
|
+
@staticmethod
|
248
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
249
|
+
return MICROSOFT_SPEED_OPTIONS
|
250
|
+
|
251
|
+
@staticmethod
|
252
|
+
def get_available_pitches() -> list[VoicePitch]:
|
253
|
+
return MICROSOFT_PITCH_OPTIONS
|
254
|
+
|
255
|
+
# class OpenVoiceVoiceNarrator(VoiceNarrator):
|
256
|
+
|
257
|
+
# @staticmethod
|
258
|
+
# def narrate(
|
259
|
+
# text: str,
|
260
|
+
# name: OpenVoiceVoiceName = OpenVoiceVoiceName.DEFAULT,
|
261
|
+
# emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
262
|
+
# speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
263
|
+
# pitch: VoicePitch = VoicePitch.DEFAULT,
|
264
|
+
# language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
265
|
+
# output_filename: Union[str, None] = None
|
266
|
+
# ):
|
267
|
+
# ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
268
|
+
# name = OpenVoiceVoiceName.to_enum(name)
|
269
|
+
|
270
|
+
# output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
271
|
+
|
272
|
+
# voice = OpenVoiceNarrationVoice(
|
273
|
+
# name = name.value,
|
274
|
+
# emotion = emotion,
|
275
|
+
# speed = speed,
|
276
|
+
# pitch = pitch,
|
277
|
+
# language = language
|
278
|
+
# )
|
279
|
+
|
280
|
+
# # TODO: Maybe return a FileReturn (?)
|
281
|
+
# return narrate_open_voice(text, voice, output_filename = output_filename)
|
282
|
+
|
283
|
+
# @staticmethod
|
284
|
+
# def get_available_languages() -> list[NarrationLanguage]:
|
285
|
+
# return OPEN_VOICE_LANGUAGE_OPTIONS
|
286
|
+
|
287
|
+
# @staticmethod
|
288
|
+
# def get_available_narrator_names(
|
289
|
+
# language: NarrationLanguage
|
290
|
+
# ) -> list[str]:
|
291
|
+
# language = NarrationLanguage.to_enum(language)
|
292
|
+
|
293
|
+
# return get_open_voice_narrator_names_by_language(language)
|
294
|
+
|
295
|
+
# @staticmethod
|
296
|
+
# def get_available_emotions() -> list[VoiceEmotion]:
|
297
|
+
# return OPEN_VOICE_EMOTION_OPTIONS
|
298
|
+
|
299
|
+
# @staticmethod
|
300
|
+
# def get_available_speeds() -> list[VoiceSpeed]:
|
301
|
+
# return OPEN_VOICE_SPEED_OPTIONS
|
302
|
+
|
303
|
+
# @staticmethod
|
304
|
+
# def get_available_pitches() -> list[VoicePitch]:
|
305
|
+
# return OPEN_VOICE_PITCH_OPTIONS
|
306
|
+
|
307
|
+
class TetyysVoiceNarrator(VoiceNarrator):
|
308
|
+
|
309
|
+
@staticmethod
|
310
|
+
def narrate(
|
311
|
+
text: str,
|
312
|
+
name: TetyysVoiceName = TetyysVoiceName.DEFAULT,
|
313
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
314
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
315
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
316
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
317
|
+
output_filename: Union[str, None] = None
|
318
|
+
):
|
319
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
320
|
+
name = TetyysVoiceName.to_enum(name)
|
321
|
+
|
322
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
323
|
+
|
324
|
+
voice = TetyysNarrationVoice(
|
325
|
+
name = name.value,
|
326
|
+
emotion = emotion,
|
327
|
+
speed = speed,
|
328
|
+
pitch = pitch,
|
329
|
+
language = language
|
330
|
+
)
|
331
|
+
|
332
|
+
# TODO: Maybe return a FileReturn (?)
|
333
|
+
return narrate_tetyys(text, voice, output_filename = output_filename)
|
334
|
+
|
335
|
+
@staticmethod
|
336
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
337
|
+
return TETYYS_LANGUAGE_OPTIONS
|
338
|
+
|
339
|
+
@staticmethod
|
340
|
+
def get_available_narrator_names(
|
341
|
+
language: NarrationLanguage
|
342
|
+
) -> list[str]:
|
343
|
+
language = NarrationLanguage.to_enum(language)
|
344
|
+
|
345
|
+
return get_tetyys_narrator_names_by_language(language)
|
346
|
+
|
347
|
+
@staticmethod
|
348
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
349
|
+
return TETYYS_EMOTION_OPTIONS
|
350
|
+
|
351
|
+
@staticmethod
|
352
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
353
|
+
return TETYYS_SPEED_OPTIONS
|
354
|
+
|
355
|
+
@staticmethod
|
356
|
+
def get_available_pitches() -> list[VoicePitch]:
|
357
|
+
return TETYYS_PITCH_OPTIONS
|
358
|
+
|
359
|
+
class TiktokVoiceNarrator(VoiceNarrator):
|
360
|
+
|
361
|
+
@staticmethod
|
362
|
+
def narrate(
|
363
|
+
text: str,
|
364
|
+
name: TiktokVoiceName = TiktokVoiceName.DEFAULT,
|
365
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
366
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
367
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
368
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
369
|
+
output_filename: Union[str, None] = None
|
370
|
+
):
|
371
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
372
|
+
name = TiktokVoiceName.to_enum(name)
|
373
|
+
|
374
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
375
|
+
|
376
|
+
voice = TiktokNarrationVoice(
|
377
|
+
name = name.value,
|
378
|
+
emotion = emotion,
|
379
|
+
speed = speed,
|
380
|
+
pitch = pitch,
|
381
|
+
language = language
|
382
|
+
)
|
383
|
+
|
384
|
+
# TODO: Maybe return a FileReturn (?)
|
385
|
+
return narrate_tiktok(text, voice, output_filename = output_filename)
|
386
|
+
|
387
|
+
@staticmethod
|
388
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
389
|
+
return TIKTOK_LANGUAGE_OPTIONS
|
390
|
+
|
391
|
+
@staticmethod
|
392
|
+
def get_available_narrator_names(
|
393
|
+
language: NarrationLanguage
|
394
|
+
) -> list[str]:
|
395
|
+
language = NarrationLanguage.to_enum(language)
|
396
|
+
|
397
|
+
return get_tiktok_narrator_names_by_language(language)
|
398
|
+
|
399
|
+
@staticmethod
|
400
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
401
|
+
return TIKTOK_EMOTION_OPTIONS
|
402
|
+
|
403
|
+
@staticmethod
|
404
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
405
|
+
return TIKTOK_SPEED_OPTIONS
|
406
|
+
|
407
|
+
@staticmethod
|
408
|
+
def get_available_pitches() -> list[VoicePitch]:
|
409
|
+
return TIKTOK_PITCH_OPTIONS
|
410
|
+
|
411
|
+
class TortoiseVoiceNarrator(VoiceNarrator):
|
412
|
+
|
413
|
+
@staticmethod
|
414
|
+
def narrate(
|
415
|
+
text: str,
|
416
|
+
name: TortoiseVoiceName = TortoiseVoiceName.DEFAULT,
|
417
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
418
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
419
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
420
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
421
|
+
output_filename: Union[str, None] = None
|
422
|
+
):
|
423
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
424
|
+
name = TortoiseVoiceName.to_enum(name)
|
425
|
+
|
426
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
427
|
+
|
428
|
+
voice = TortoiseNarrationVoice(
|
429
|
+
name = name.value,
|
430
|
+
emotion = emotion,
|
431
|
+
speed = speed,
|
432
|
+
pitch = pitch,
|
433
|
+
language = language
|
434
|
+
)
|
435
|
+
|
436
|
+
# TODO: Maybe return a FileReturn (?)
|
437
|
+
return narrate_tortoise(text, voice, output_filename = output_filename)
|
438
|
+
|
439
|
+
@staticmethod
|
440
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
441
|
+
return TORTOISE_LANGUAGE_OPTIONS
|
442
|
+
|
443
|
+
@staticmethod
|
444
|
+
def get_available_narrator_names(
|
445
|
+
language: NarrationLanguage
|
446
|
+
) -> list[str]:
|
447
|
+
language = NarrationLanguage.to_enum(language)
|
448
|
+
|
449
|
+
return get_tortoise_narrator_names_by_language(language)
|
450
|
+
|
451
|
+
@staticmethod
|
452
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
453
|
+
return TORTOISE_EMOTION_OPTIONS
|
454
|
+
|
455
|
+
@staticmethod
|
456
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
457
|
+
return TORTOISE_SPEED_OPTIONS
|
458
|
+
|
459
|
+
@staticmethod
|
460
|
+
def get_available_pitches() -> list[VoicePitch]:
|
461
|
+
return TORTOISE_PITCH_OPTIONS
|
462
|
+
|
463
|
+
class Ttsmp3VoiceNarrator(VoiceNarrator):
|
464
|
+
|
465
|
+
@staticmethod
|
466
|
+
def narrate(
|
467
|
+
text: str,
|
468
|
+
name: Ttsmp3VoiceName = Ttsmp3VoiceName.DEFAULT,
|
469
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
470
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
471
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
472
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT,
|
473
|
+
output_filename: Union[str, None] = None
|
474
|
+
):
|
475
|
+
ParameterValidator.validate_mandatory_string('text', text, do_accept_empty = False)
|
476
|
+
name = Ttsmp3VoiceName.to_enum(name)
|
477
|
+
|
478
|
+
output_filename = Output.get_filename(output_filename, FileType.AUDIO)
|
479
|
+
|
480
|
+
voice = Ttsmp3NarrationVoice(
|
481
|
+
name = name.value,
|
482
|
+
emotion = emotion,
|
483
|
+
speed = speed,
|
484
|
+
pitch = pitch,
|
485
|
+
language = language
|
486
|
+
)
|
487
|
+
|
488
|
+
# TODO: Maybe return a FileReturn (?)
|
489
|
+
return narrate_tts3(text, voice, output_filename = output_filename)
|
490
|
+
|
491
|
+
@staticmethod
|
492
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
493
|
+
return TTSMP3_LANGUAGE_OPTIONS
|
494
|
+
|
495
|
+
@staticmethod
|
496
|
+
def get_available_narrator_names(
|
497
|
+
language: NarrationLanguage
|
498
|
+
) -> list[str]:
|
499
|
+
language = NarrationLanguage.to_enum(language)
|
500
|
+
|
501
|
+
return get_ttsmp3_narrator_names_by_language(language)
|
502
|
+
|
503
|
+
@staticmethod
|
504
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
505
|
+
return TTSMP3_EMOTION_OPTIONS
|
506
|
+
|
507
|
+
@staticmethod
|
508
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
509
|
+
return TTSMP3_SPEED_OPTIONS
|
510
|
+
|
511
|
+
@staticmethod
|
512
|
+
def get_available_pitches() -> list[VoicePitch]:
|
513
|
+
return TTSMP3_PITCH_OPTIONS
|
514
|
+
|
515
|
+
class DefaultVoiceNarrator(VoiceNarrator):
|
516
|
+
"""
|
517
|
+
The voice narrator that would be used by
|
518
|
+
default when no specific narrator is requested.
|
519
|
+
"""
|
520
|
+
|
521
|
+
@staticmethod
|
522
|
+
def narrate(
|
523
|
+
text: str,
|
524
|
+
output_filename: Union[str, None] = None
|
525
|
+
):
|
526
|
+
return GoogleVoiceNarrator.narrate(
|
527
|
+
text = text,
|
528
|
+
output_filename = output_filename
|
529
|
+
)
|
530
|
+
|
531
|
+
@staticmethod
|
532
|
+
def get_available_languages() -> list[NarrationLanguage]:
|
533
|
+
return GoogleVoiceNarrator.get_available_languages()
|
534
|
+
|
535
|
+
@staticmethod
|
536
|
+
def get_available_narrator_names(
|
537
|
+
language: NarrationLanguage
|
538
|
+
) -> list[str]:
|
539
|
+
return GoogleVoiceNarrator.get_available_narrator_names(language)
|
540
|
+
|
541
|
+
@staticmethod
|
542
|
+
def get_available_emotions() -> list[VoiceEmotion]:
|
543
|
+
return GoogleVoiceNarrator.get_available_emotions()
|
544
|
+
|
545
|
+
@staticmethod
|
546
|
+
def get_available_speeds() -> list[VoiceSpeed]:
|
547
|
+
return GoogleVoiceNarrator.get_available_speeds()
|
548
|
+
|
549
|
+
@staticmethod
|
550
|
+
def get_available_pitches() -> list[VoicePitch]:
|
551
|
+
return GoogleVoiceNarrator.get_available_pitches()
|
552
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
from yta_audio_narration.enums import NarrationLanguage, VoiceSpeed, VoiceEmotion, VoicePitch
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from abc import abstractmethod
|
4
|
+
|
5
|
+
|
6
|
+
@dataclass
|
7
|
+
class NarrationVoice:
|
8
|
+
"""
|
9
|
+
Dataclass to be implemented by other custom
|
10
|
+
dataclasses that will determine the narration
|
11
|
+
voice parameters of our voice narration
|
12
|
+
engines.
|
13
|
+
"""
|
14
|
+
|
15
|
+
name: str
|
16
|
+
"""
|
17
|
+
The voice narration name.
|
18
|
+
"""
|
19
|
+
emotion: VoiceEmotion
|
20
|
+
"""
|
21
|
+
The voice narration emotion.
|
22
|
+
"""
|
23
|
+
speed: VoiceSpeed
|
24
|
+
"""
|
25
|
+
The voice narration desired speed.
|
26
|
+
"""
|
27
|
+
pitch : VoicePitch
|
28
|
+
"""
|
29
|
+
The voice narration desired pitch.
|
30
|
+
"""
|
31
|
+
language: NarrationLanguage
|
32
|
+
"""
|
33
|
+
The language to be used with the voice narration.
|
34
|
+
"""
|
35
|
+
# TODO: Maybe add something more like
|
36
|
+
# pitch or something
|
37
|
+
|
38
|
+
def __init__(
|
39
|
+
self,
|
40
|
+
name: str = '',
|
41
|
+
emotion: VoiceEmotion = VoiceEmotion.DEFAULT,
|
42
|
+
speed: VoiceSpeed = VoiceSpeed.DEFAULT,
|
43
|
+
pitch: VoicePitch = VoicePitch.DEFAULT,
|
44
|
+
language: NarrationLanguage = NarrationLanguage.DEFAULT
|
45
|
+
):
|
46
|
+
self.validate(name, emotion, speed, pitch, language)
|
47
|
+
|
48
|
+
# TODO: Maybe we could receive an Enum name
|
49
|
+
# and we need to parse it
|
50
|
+
self.name = name
|
51
|
+
self.emotion = VoiceEmotion.to_enum(emotion)
|
52
|
+
self.speed = VoiceSpeed.to_enum(speed)
|
53
|
+
self.pitch = VoicePitch.to_enum(pitch)
|
54
|
+
self.language = NarrationLanguage.to_enum(language)
|
55
|
+
|
56
|
+
@abstractmethod
|
57
|
+
def validate(
|
58
|
+
self,
|
59
|
+
name: str,
|
60
|
+
emotion: VoiceEmotion,
|
61
|
+
speed: VoiceSpeed,
|
62
|
+
pitch: VoicePitch,
|
63
|
+
language: NarrationLanguage
|
64
|
+
):
|
65
|
+
"""
|
66
|
+
Check if the parameters provided are valid or not
|
67
|
+
and raise an Exception if not.
|
68
|
+
|
69
|
+
This method can also process the attributes to make
|
70
|
+
some modifications and return them to be stored
|
71
|
+
once they have been modified.
|
72
|
+
|
73
|
+
This method must be overwritten.
|
74
|
+
"""
|
75
|
+
pass
|
76
|
+
|
77
|
+
@staticmethod
|
78
|
+
@abstractmethod
|
79
|
+
def default():
|
80
|
+
"""
|
81
|
+
Return an instance of your Narration Voice custom
|
82
|
+
class with the default values for that type of
|
83
|
+
class.
|
84
|
+
|
85
|
+
This method must be overwritten.
|
86
|
+
"""
|
87
|
+
pass
|
88
|
+
|
File without changes
|