This repository has been archived by the owner on Feb 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 64
/
outsource_sayer.py
executable file
·146 lines (101 loc) · 4.3 KB
/
outsource_sayer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from handler.base_plugin import CommandPlugin
from utils import upload_audio_message
from gtts import gTTS
import langdetect
from random import choice
import asyncio, aiohttp, io
class SayerPlugin(CommandPlugin):
__slots__ = ("key", "providers")
def __init__(self, *commands, key=None, use_yandex=True, prefixes=None, strict=False):
"""Answers with audio message of user's text"""
if not commands:
commands = ("скажи", "произнеси")
super().__init__(*commands, prefixes=prefixes, strict=strict)
self.key = key
self.providers = [(lambda text, lang, key=None: gTTS(text=text, lang=lang)),
(lambda text, lang, key=None: yTTS(text=text, lang=lang, key=key)),]
if use_yandex:
self.providers[0], self.providers[1] = self.providers[1], self.providers[0]
example = self.command_example()
self.description = [f"Текст в речь",
f"{example} [текст] - произнести текст (+ значит ударение перед ударной гласной)."]
def initiate(self):
if not self.key:
self.bot.logger.warning("No key specified for Yandex Speechkit Cloud. Google "
"will be used. You can get your key - https://tech.yandex.ru/speechkit/cloud/.")
@staticmethod
def get_lang(text):
resu = None
try:
langs = langdetect.detect_langs(text)
for language in langs:
if language.lang == "ru":
language.prob += 0.2
if resu is None or resu < language:
resu = language
except langdetect.lang_detect_exception.LangDetectException:
pass
if resu is None:
return "ru"
return resu.lang
async def create_audio(self, provider, text):
if len(text) > 500:
return "Слишком длинное сообщение", None
try:
lang = self.get_lang(text)
for provider in self.providers:
tts = provider(text, lang, self.key)
f = io.BytesIO()
if asyncio.iscoroutinefunction(tts.write_to_fp):
await tts.write_to_fp(f)
else:
tts.write_to_fp(f)
f.seek(0)
if f.getbuffer().nbytes < 16:
f.close()
continue
return "", f
except ValueError:
pass
return "Произошла ошибка! Попробуйте позже.", None
async def process_message(self, msg):
command, text = self.parse_message(msg, full=True)
if not text:
return await msg.answer('Введите текст для перевода его в речь!')
answer, answer_file = await self.create_audio(gTTS, text)
if answer_file is None:
return await msg.answer(answer)
audio = await upload_audio_message(self.api, answer_file, msg.user_id)
answer_file.close()
return await msg.answer("", attachment=str(audio))
class yTTS(object):
__slots__ = ("params",)
base_url = "https://tts.voicetech.yandex.net/tts"
speakers = ["jane", "oksana", "alyss", "omazh", "zahar", "ermil"]
emotion = ["good", "neutral", "evil"]
languages = {'en': 'en_US', 'ru': 'ru_RU', 'uk': 'uk_UK', 'tr': 'tr_TR'}
def __init__(self, text, lang='ru_RU', key=""):
self.params = {
"text": text,
"lang": self.languages.get(lang, "ru_RU"),
"emotion": choice(self.emotion),
"speaker": choice(self.speakers),
"speed": "0.8",
"format": 'mp3',
}
if key:
self.params[key] = key
async def write_to_fp(self, f):
try:
return await self._write_to_fp(f)
except Exception:
return False
async def _write_to_fp(self, f):
async with aiohttp.ClientSession(raise_for_status=True) as sess:
async with sess.get(self.base_url, params=self.params) as resp:
while True:
chunk = await resp.content.read(1024)
if not chunk:
break
f.write(chunk)
return True