yta-audio-narration-ttsmp3 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,269 @@
1
+ """
2
+ Welcome to Youtube Autonomous Audio Narration
3
+ Ttsmp3 Voice Module.
4
+
5
+ This engine has been extracted from here:
6
+ - https://ttsmp3.com/
7
+
8
+ This voice engine has just a limit of
9
+ 3.000 characters of input when generating
10
+ with normal voices, and 1.000 daily
11
+ characters when using AI. AI is disabled
12
+ by now as the limit makes it not
13
+ interesting for our purpose.
14
+ """
15
+ from yta_audio_narration_common.consts import DEFAULT_VOICE
16
+ from yta_audio_narration_common.enums import NarrationLanguage, VoiceEmotion, VoiceSpeed, VoicePitch
17
+ from yta_audio_narration_common.voice import NarrationVoice
18
+ from yta_file_downloader import Downloader
19
+ from yta_constants.file import FileType
20
+ from yta_constants.enum import YTAEnum as Enum
21
+ from yta_programming.output import Output
22
+ from typing import Union
23
+
24
+ import requests
25
+
26
+
27
+ """
28
+ The options below are specified even if we
29
+ don't use them later when processing the
30
+ voice narration. This is to keep the same
31
+ structure for any voice narration and to
32
+ simplify the way we offer the options in
33
+ an API that is able to make requests.
34
+ """
35
+
36
+ # 1. The voices we accept, as Enums
37
+ class Ttsmp3VoiceName(Enum):
38
+ # Normal voices below:
39
+ DEFAULT = DEFAULT_VOICE
40
+ LUPE = 'Lupe' # US Spanish
41
+ PENELOPE = 'Penelope' # US Spanish
42
+ MIGUEL = 'Miguel' # US Spanish
43
+ # TODO: There are more voices for the different
44
+ # languages, so jus copy the names here and you
45
+ # will be able to use them
46
+ # AI voices below:
47
+ # ALLOY = 'alloy' # female
48
+ # ECHO = 'echo' # male
49
+ # FABLE = 'fable' # male
50
+ # ONYX = 'onyx' # male (deeper voice)
51
+ # NOVA = 'nova' # female (soft)
52
+ # SHIMMER = 'shimmer' # female
53
+
54
+ # 2. The languages we accept
55
+ LANGUAGE_OPTIONS = [
56
+ NarrationLanguage.DEFAULT
57
+ ]
58
+
59
+ # 3. The emotions we accept
60
+ EMOTION_OPTIONS = [
61
+ VoiceEmotion.DEFAULT,
62
+ VoiceEmotion.NORMAL,
63
+ ]
64
+
65
+ # 4. The speeds we accept
66
+ SPEED_OPTIONS = [
67
+ VoiceSpeed.DEFAULT,
68
+ VoiceSpeed.NORMAL,
69
+ ]
70
+
71
+ # 5. The pitches we accept
72
+ PITCH_OPTIONS = [
73
+ VoicePitch.DEFAULT,
74
+ VoicePitch.NORMAL,
75
+ ]
76
+
77
+ class Ttsmp3NarrationVoice(NarrationVoice):
78
+ """
79
+ Voice instance to be used when narrating with
80
+ Ttsmp3 engine.
81
+ """
82
+
83
+ @property
84
+ def processed_name(
85
+ self
86
+ ) -> str:
87
+ """
88
+ Get the usable name value from the one that has
89
+ been set when instantiating the instance.
90
+ """
91
+ return (
92
+ Ttsmp3VoiceName.MIGUEL.value
93
+ if Ttsmp3VoiceName.to_enum(self.name) == Ttsmp3VoiceName.DEFAULT else
94
+ Ttsmp3VoiceName.to_enum(self.name).value
95
+ )
96
+
97
+ @property
98
+ def processed_emotion(
99
+ self
100
+ ) -> str:
101
+ """
102
+ Get the usable emotion value from the one that
103
+ has been set when instantiating the instance.
104
+ """
105
+ # This narration is not able to handle any
106
+ # emotion (at least by now)
107
+ return None
108
+
109
+ @property
110
+ def processed_speed(
111
+ self
112
+ ) -> int:
113
+ """
114
+ Get the usable speed value from the one that
115
+ has been set when instantiating the instance.
116
+ """
117
+ # This is not used here
118
+ return None
119
+
120
+ @property
121
+ def processed_pitch(
122
+ self
123
+ ) -> int:
124
+ """
125
+ Get the usable pitch value from the one that
126
+ has been set when instantiating the instance.
127
+ """
128
+ # This is not used here
129
+ return None
130
+
131
+ @property
132
+ def processed_language(
133
+ self
134
+ ) -> str:
135
+ """
136
+ Get the usable language value from the one that
137
+ has been set when instantiating the instance.
138
+ """
139
+ # This engine has the language set in the voice
140
+ # names so you should select a voice name that
141
+ # is specific of the language you need
142
+ return None
143
+
144
+ def validate_and_process(
145
+ self,
146
+ name: str,
147
+ emotion: VoiceEmotion,
148
+ speed: VoiceSpeed,
149
+ pitch: VoicePitch,
150
+ language: NarrationLanguage
151
+ ):
152
+ Ttsmp3VoiceName.to_enum(name)
153
+ if VoiceEmotion.to_enum(emotion) not in EMOTION_OPTIONS:
154
+ raise Exception(f'The provided {emotion} is not valid for this narration voice.')
155
+ if VoiceSpeed.to_enum(speed) not in SPEED_OPTIONS:
156
+ raise Exception(f'The provided {speed} is not valid for this narration voice.')
157
+ if VoicePitch.to_enum(pitch) not in PITCH_OPTIONS:
158
+ raise Exception(f'The provided {pitch} is not valid for this narration voice.')
159
+ if NarrationLanguage.to_enum(language) not in LANGUAGE_OPTIONS:
160
+ raise Exception(f'The provided {language} is not valid for this narration voice.')
161
+
162
+ @staticmethod
163
+ def default():
164
+ return Ttsmp3NarrationVoice(
165
+ name = Ttsmp3VoiceName.DEFAULT.value,
166
+ emotion = VoiceEmotion.DEFAULT,
167
+ speed = VoiceSpeed.DEFAULT,
168
+ pitch = VoicePitch.DEFAULT,
169
+ language = NarrationLanguage.DEFAULT
170
+ )
171
+
172
+ # The voices but for a specific language, to be able to
173
+ # choose one when this is requested from the outside
174
+ def get_narrator_names_by_language(
175
+ language: NarrationLanguage
176
+ ) -> list[str]:
177
+ language = NarrationLanguage.to_enum(language)
178
+ language = (
179
+ NarrationLanguage.SPANISH
180
+ if language is NarrationLanguage.DEFAULT else
181
+ language
182
+ )
183
+
184
+ return {
185
+ NarrationLanguage.SPANISH: [
186
+ Ttsmp3VoiceName.DEFAULT.value,
187
+ Ttsmp3VoiceName.LUPE.value,
188
+ Ttsmp3VoiceName.MIGUEL.value,
189
+ Ttsmp3VoiceName.PENELOPE.value
190
+ ]
191
+ }[language]
192
+
193
+ # All the remaining functionality we need to make it
194
+ # work properly
195
+ # TODO: Check this because I don't know if this webpage is using the tts (coqui)
196
+ # library as the generator engine. If that, I have this engine in 'coqui.py' file
197
+ # so I don't need this (that is not stable because is based in http requests)
198
+ def narrate_tts3(
199
+ text: str,
200
+ voice: Ttsmp3NarrationVoice = Ttsmp3NarrationVoice.default(),
201
+ output_filename: Union[str, None] = None
202
+ ) -> str:
203
+ """
204
+ This makes a narration based on an external platform. You
205
+ can change some voice configuration in code to make the
206
+ voice different.
207
+
208
+ Aparrently not limited. Check, because it has time breaks
209
+ and that stuff to enhance the narration.
210
+ """
211
+ # From here: https://ttsmp3.com/
212
+ headers = {
213
+ 'accept': '*/*',
214
+ 'accept-language': 'es-ES,es;q=0.9',
215
+ 'content-type': 'application/x-www-form-urlencoded',
216
+ 'origin': 'https://ttsmp3.com',
217
+ 'referer': 'https://ttsmp3.com/',
218
+ 'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"',
219
+ 'sec-ch-ua-mobile': '?0',
220
+ 'sec-ch-ua-platform': '"Windows"',
221
+ 'sec-fetch-dest': 'empty',
222
+ 'sec-fetch-mode': 'cors',
223
+ 'sec-fetch-site': 'same-origin',
224
+ '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',
225
+ }
226
+
227
+ data = {
228
+ 'msg': text,
229
+ 'lang': voice.processed_name,
230
+ 'source': 'ttsmp3',
231
+ }
232
+
233
+ """
234
+ There is an AI voices version but it has a
235
+ daily limit of only 1.000 characters so it
236
+ is not interesting, that is why I leave the
237
+ code but commented.
238
+
239
+ The way to request AI voice narrations is
240
+ the same, but using the AI url and the AI
241
+ voices names instead of the normal ones.
242
+ """
243
+ # AI_VERSION_HEADERS = {
244
+ # 'accept': '*/*',
245
+ # 'accept-language': 'es-ES,es;q=0.9',
246
+ # 'content-type': 'application/x-www-form-urlencoded',
247
+ # 'origin': 'https://ttsmp3.com',
248
+ # 'priority': 'u=1, i',
249
+ # 'referer': 'https://ttsmp3.com/ai',
250
+ # 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
251
+ # 'sec-ch-ua-mobile': '?0',
252
+ # 'sec-ch-ua-platform': '"Windows"',
253
+ # 'sec-fetch-dest': 'empty',
254
+ # 'sec-fetch-mode': 'cors',
255
+ # 'sec-fetch-site': 'same-origin',
256
+ # 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
257
+ # }
258
+ # AI_VERSION_URL = 'https:ttsmp3.com/makemp3_ai.php'
259
+
260
+ response = requests.post('https://ttsmp3.com/makemp3_new.php', headers = headers, data = data)
261
+ response = response.json()
262
+ url = response['URL']
263
+
264
+ output_filename = Output.get_filename(output_filename, FileType.AUDIO)
265
+
266
+ # This is one example of a valid url we receive
267
+ # as response:
268
+ # https://ttsmp3.com/created_mp3/8b38a5f2d4664e98c9757eb6db93b914.mp3
269
+ return Downloader.download_audio(url, output_filename).filename
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.3
2
+ Name: yta-audio-narration-ttsmp3
3
+ Version: 0.0.1
4
+ Summary: Youtube Autonomous Audio Narration Ttsmp3 Voice Module.
5
+ Author: danialcala94
6
+ Author-email: danielalcalavalera@gmail.com
7
+ Requires-Python: ==3.9
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Requires-Dist: yta_audio_narration_common (>=0.0.1,<1.0.0)
11
+ Requires-Dist: yta_constants (>=0.0.1,<1.0.0)
12
+ Requires-Dist: yta_file (>=0.0.1,<1.0.0)
13
+ Requires-Dist: yta_programming (>=0.0.1,<1.0.0)
14
+ Description-Content-Type: text/markdown
15
+
16
+ # Youtube Autonomous Audio Narration Ttsmp3 Voice Module
17
+
18
+ The Audio narration Ttsmp3 voice module.
19
+
20
+ Please, check the 'pyproject.toml' file to see the dependencies.
21
+
22
+
@@ -0,0 +1,5 @@
1
+ yta_audio_narration_ttsmp3/__init__.py,sha256=IBCUF9fGiT9DjvV14JzcewD-1pke9WJRV102V-y97Zw,8870
2
+ yta_audio_narration_ttsmp3-0.0.1.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
3
+ yta_audio_narration_ttsmp3-0.0.1.dist-info/METADATA,sha256=El5HojhD4hu-13sWQOsoRbd3YqZlKNYRbSu7DCVIxrE,722
4
+ yta_audio_narration_ttsmp3-0.0.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
5
+ yta_audio_narration_ttsmp3-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any