Всем привет, я программист-любитель, изучающий язык python уже многие годы.
Не буду долго тянуть с приветствием и сразу перейду к делу. Этот гайд является по сути пошаговой инструкцией для создания базового кода, который можно будет потом расширять и дополнять. Голосовой ассистент - вещь весьма удобная, особенно если эту вещь можно настроить под свои нужды. Спасибо языку python, имеющему бесчисленное множество библиотек и фреймворков, позволяющих писать почти что угодно под почти любую платформу.
Для нашего же случая подойдут библиотеки silero (для tts), vosk (для stt) и sounddevice (для воспроизведения аудио)
сразу установим их: pip install silero vosk sounddevice
Преобразование текста в речь
Библиотека silero может преобразовывать текст в речь на множестве языков, нас же интересует русский язык, поэтому создадим небольшой класс на основе официальной документации:
import sounddevice as sd
import torch
import time
# константы голосов, поддерживаемых в silero
SPEAKER_AIDAR = "aidar"
SPEAKER_BAYA = "baya"
SPEAKER_KSENIYA = "kseniya"
SPEAKER_XENIA = "xenia"
SPEAKER_RANDOM = "random"
# константы девайсов для работы torch
DEVICE_CPU = "cpu"
DEVICE_CUDA = "cuda"
DEVICE_VULKAN = "vulkan"
DEVICE_OPENGL = "opengl"
DEVICE_OPENCL = "opencl"
class TTS:
def __init__(
self, speaker: str = SPEAKER_BAYA,
device: str = DEVICE_CPU,
samplerate: int = 48_000
):
# подгружаем модель
self.__MODEL__, _ = torch.hub.load(
repo_or_dir="snakers4/silero-models",
model="silero_tts",
language="ru",
speaker="ru_v3"
)
self.__MODEL__.to(torch.device(device))
self.__SPEAKER__ = speaker
self.__SAMPLERATE__ = samplerate
def text2speech(self, text: str):
# генерируем аудио из текста
audio = self.__MODEL__.apply_tts(
text=text,
speaker=self.__SPEAKER__,
sample_rate=self.__SAMPLERATE__,
put_accent=True,
put_yo=True
)
# проигрываем то что получилось
sd.play(audio, samplerate=self.__SAMPLERATE__)
time.sleep((len(audio)/self.__SAMPLERATE__))
sd.stop()
При инициализации подгружается нейронная модель, если её нет на компьютере, то она будет скачана, иначе она будет взята из кэша загрузок.
Сама же нейронная модель работает на torch, поэтому можно будет запускать её не на процессоре а на видеокарте, для лучшей скорости работы. Правда мой ноутбук с RTX 3050 Ti mobile хоть и позволяет произвести запуск на видеокарте, всё равно на процессоре модель работает быстрее, поэтому поэкспериментируйте, чтобы найти наилучший способ.
Распознавание речи
Для распознавания речи будем использовать библиотеку vosk, сначала перейдём на официальный сайт с моделями распознавания и скачаем необходимую модель распознавания речи, обратите внимание что моделей две и та модель, которая больше весит, будет соответственно лучше распознавать речь, но и при этом будет медленнее подгружаться.
Создайте папку в вашей рабочей области и распакуйте скачанный архив в эту папку.
Далее создадим ещё один небольшой класс на основе документации:
import sounddevice as sd
import vosk
import sys
import queue
import json
class STT:
def __init__(self, modelpath: str = "model", samplerate: int = 16000):
self.__REC__ = vosk.KaldiRecognizer(vosk.Model(modelpath), samplerate)
self.__Q__ = queue.Queue()
self.__SAMPLERATE__ = samplerate
def q_callback(self, indata, _, __, status):
if status:
print(status, file=sys.stderr)
self.__Q__.put(bytes(indata))
def listen(self, executor: callable):
with sd.RawInputStream(
samplerate=self.__SAMPLERATE__,
blocksize=8000,
device=1,
dtype='int16',
channels=1,
callback=self.q_callback
):
while True:
data = self.__Q__.get()
if self.__REC__.AcceptWaveform(data):
executor(json.loads(self.__REC__.Result())["text"])
При инициализации параметр modelpath
это путь к вашей скачанной модели, а параметр executor
в функции listen
это функция, которая будет что-то делать с распознанным текстом.
Главный файл
На основе двух написанных классов создадим файл main.py
со следующим кодом:
from fuzzywuzzy import fuzz
from tts import TTS
from stt import STT
commandsList = []
def equ(text, needed):
return fuzz.ratio(text, needed) >= 70
def execute(text: str):
print(f"> {text}")
if equ(text, "расскажи анекдот"):
text = "какой то анекдот!"
tts.text2speech(text)
print(f"- {text}")
elif equ(text, "что ты умеешь"):
text = "я умею всё, чему ты мен+я науч+ил!"
tts.text2speech(text)
print(f"- {text}")
elif equ(text, "выключи"):
text = "надеюсь, я не стану про+ектом, кот+орый ты забр+осишь!"
tts.text2speech(text)
print(f"- {text}")
raise SystemExit
tts = TTS()
stt = STT(modelpath="model_small")
print("listen...")
stt.listen(execute)
В коде выше используется библиотека fuzzywuzzy
, позволяющая нечётко сравнивать строки, данная библиотека необязательна, но лучше с ней чем без неё.
Также стоит отметить, что н+екоторые фр+азы для озв+учки я п+ишу вот так, плюсы в тексте позволяют указать ударение в слове
Мини-заключение
На этом костяк нашего проекта завершён, осталось лишь добавить необходимый функционал и всё готово!
Так же хотелось бы добавить, что я не считаю себя идеальным супер программистом, поэтому я жду жёсткой критики, ведь именно работа над ошибками позволяет программисту быть программистом.
Комментарии (10)
Jury_78
05.12.2024 10:50При инициализации подгружается нейронная модель
Если воспользоваться RHVoice то модель не нужна.
Advisory
05.12.2024 10:50Документация предлагает прослушать примеры голосов на странице https://data2data.ru/tts/ , однако страница недоступна. Не знаете где еще можно ознакомиться с примерами?
Jury_78
05.12.2024 10:50У меня доступна:
p.s. Еще тут есть >>>
Advisory
05.12.2024 10:50Теперь и у меня доступна. А до этого в разных браузерах происходил редирект на разные сайты.
Очень не удобно прослушивание сделано — нужно скачивать mp3-файлы. Но по сути, один и тот же голос, в котором меняют скорость и тембр. В остальном никаких отличий. Не помню как называется, но, кажется в 2003 году в Говорилке его использовали.
vkrasikov
05.12.2024 10:50Молодец!
В коде выше используется библиотека
fuzzywuzzy
, позволяющая нечётко сравнивать строки, данная библиотека необязательна, но лучше с ней чем без неё.Можешь ещё попробовать поработать с языковыми моделями, это щас модно :) Например, сравнивать строки, задавая вопрос гигачату:
from gigachat import GigaChat GIGACHAT_TOKEN = "MTQ....................................1NA==" s1 = "Что ты умеешь?" s2 = "Расскажи, что ты можешь делать?" with GigaChat(credentials=GIGACHAT_TOKEN, verify_ssl_certs=False) as giga: response = giga.chat( "На сколько процентов похожи две следующие строки? Сравни по смыслу:\n" f"1) {s1}\n" f"2) {s2}\n" "В ответе напиши только одно число.") print(response.choices[0].message.content)
PlayingPlate6667 Автор
05.12.2024 10:50Спасибо за совет!
решение интересное, но сам ассистент ориентирован на оффлайн работу, поэтому я использовал именно то, что использовал.
CyberexTech
Что-то подобное делал ранее, только в качестве самостоятельного устройства. Для синтеза речи лучше использовать модель v4_ru.pt, она быстрее.
PlayingPlate6667 Автор
Возможно, но модель v4 у меня почему-то выдаёт какой-то электронный голос.