mirror of
https://github.com/MuRuLOSE/limoka.git
synced 2026-06-16 14:34:17 +02:00
124 lines
3.6 KiB
Python
124 lines
3.6 KiB
Python
# requires: pydub requests gtts hachoir
|
|
import io
|
|
import os
|
|
|
|
import requests
|
|
from gtts import gTTS
|
|
from pydub import AudioSegment
|
|
|
|
from .. import loader, utils
|
|
|
|
|
|
def register(cb):
|
|
cb(DttsMod())
|
|
|
|
|
|
class DttsMod(loader.Module):
|
|
"""Text to speech module"""
|
|
|
|
strings = {
|
|
"name": "DTTS",
|
|
"no_text": "I can't say nothing",
|
|
"tts_lang_cfg": "Set your language code for the TTS here.",
|
|
}
|
|
|
|
def __init__(self):
|
|
self.config = loader.ModuleConfig(
|
|
"TTS_LANG", "en", lambda m: self.strings("tts_lang_cfg", m)
|
|
)
|
|
self.is_ffmpeg = os.system("ffmpeg -version") == 0
|
|
|
|
async def say(self, message, speaker, text, file=".dtts.mp3"):
|
|
reply = await message.get_reply_message()
|
|
if not text:
|
|
if not reply:
|
|
return await utils.answer(message, self.strings["no_text"])
|
|
text = reply.raw_text # use text from reply
|
|
if not text:
|
|
return await utils.answer(message, self.strings["no_text"])
|
|
if message.out:
|
|
await message.delete() # Delete message only one is user's
|
|
data = {"text": text}
|
|
if speaker:
|
|
data["speaker"] = speaker
|
|
|
|
# creating file in memory
|
|
f = io.BytesIO(
|
|
requests.get("https://station.aimylogic.com/generate", data=data).content
|
|
)
|
|
f.name = file
|
|
|
|
if self.is_ffmpeg:
|
|
f, duration = to_voice(f)
|
|
else:
|
|
duration = None
|
|
|
|
await message.client.send_file(
|
|
message.chat_id, f, voice_note=True, reply_to=reply, duration=duration
|
|
)
|
|
|
|
@loader.unrestricted
|
|
@loader.ratelimit
|
|
async def levitancmd(self, message):
|
|
"""Convert text to speech with levitan voice"""
|
|
await self.say(message, "levitan", utils.get_args_raw(message))
|
|
|
|
@loader.unrestricted
|
|
@loader.ratelimit
|
|
async def oksanacmd(self, message):
|
|
"""Convert text to speech with oksana voice"""
|
|
await self.say(message, "oksana", utils.get_args_raw(message))
|
|
|
|
@loader.unrestricted
|
|
@loader.ratelimit
|
|
async def yandexcmd(self, message):
|
|
"""Convert text to speech with yandex voice"""
|
|
await self.say(message, None, utils.get_args_raw(message))
|
|
|
|
@loader.unrestricted
|
|
@loader.ratelimit
|
|
async def ttscmd(self, message):
|
|
"""Convert text to speech with Google APIs"""
|
|
reply = await message.get_reply_message()
|
|
text = utils.get_args_raw(message.message)
|
|
|
|
if not text:
|
|
if message.is_reply:
|
|
text = (await message.get_reply_message()).message
|
|
else:
|
|
return await utils.answer(message, self.strings("no_text", message))
|
|
|
|
if message.out:
|
|
await message.delete()
|
|
|
|
tts = await utils.run_sync(gTTS, text, lang=self.config["TTS_LANG"])
|
|
voice = io.BytesIO()
|
|
await utils.run_sync(tts.write_to_fp, voice)
|
|
voice.seek(0)
|
|
voice.name = "voice.mp3"
|
|
|
|
if self.is_ffmpeg:
|
|
voice, duration = to_voice(voice)
|
|
else:
|
|
duration = None
|
|
|
|
await message.client.send_file(
|
|
message.chat_id, voice, voice_note=True, reply_to=reply, duration=duration
|
|
)
|
|
|
|
|
|
def to_voice(item):
|
|
"""Returns audio in opus format and it's duration"""
|
|
item.seek(0)
|
|
item = AudioSegment.from_file(item)
|
|
m = io.BytesIO()
|
|
m.name = "voice.ogg"
|
|
item.split_to_mono()
|
|
dur = len(item) / 1000
|
|
item.export(m, format="ogg", bitrate="64k", codec="libopus")
|
|
m.seek(0)
|
|
return m, dur
|
|
|
|
|
|
# By @vreply @pernel_kanic @nim1love @db0mb3r and add @tshipenchko some geyporn
|