— Слушай, она меня на кухне не слышит.

— Ну да, далековато. Давай дополнительный микрофон протянем.

<покупается 5 метров кабеля>

— О, классно!

— ...

— Теперь в комнате не работает.

Это продолжение статьи Ирина — опенсорс русский голосовой помощник. Offline-ready. Расскажу, что поменялось за два месяца с момента прошлой статьи.

  • Отлажена работа в режиме клиент-сервер с несколькими микрофонами/машинами

  • Сделан Телеграм-клиент для удаленного управления

  • Прикручено несколько новых голосов (TTS)

  • Добавлена возможность обрабатывать голос в контексте (можно делать голосовые игры)

  • Мне прислали плагин, позволяющий запускать сценарии Home Assistant :)

  • Новые плагины и улучшенная документация

Клиент-сервер, или как командовать с нескольких микрофонов

В комментариях к прошлой статье спрашивали, можно ли сделать распознавание команд с нескольких микрофонов. Чуть позднее мне пришлось самому столкнуться с этой проблемой - очень хотелось, чтобы можно было командовать Ириной как с кухни (ставить кухонный таймер), так и рядом с сервером.

Кабель купили, микрофон поставили, на кухне всё заработало... но оказалось, что теперь не идет аудиопоток с микрофона в сервере.

В общем возникла проблемка.

  1. Я оптимистично предположил, что в Windows есть функция сведения микрофонов... но оказалось, что её НЕТ. Во всяком случае, быстро найти мне её не удалось.

  2. Писать оригинальную функцию в Питоне для сведения потока с двух микрофонов мне не захотелось - не мой профиль, и быстро бы не получилось.

Так что был выбран третий путь - довести до ума клиент-серверную инсталляцию, где два отдельных клиента слушали бы микрофоны, распознавали с них ввод, и отсылали на сервер для обработки. Заодно возникла бы возможность командовать Ириной с других машин, или вообще через Телеграм-клиент.

...

Долго ли коротко ли, клиент-серверная модель была отлажена. (Кто её пробовал в 3.0 - извиняюсь, я там немного накосячил с многопоточностью; попробуйте самую свежую версию, она устойчива).

Обычная работа Ирины выглядит так:

Speech-To-Text (распознавание голоса) -> vacore (ядро) -> plugin -> Text-To-Speech (генерация голосового ответа)

В то время, как клиент-серверный вариант - так:

[клиент] Speech-To-Text (распознавание голоса) ----> [сервер] webapi (vacore) -> plugin -> Text-To-Speech (генерация голосового ответа)

На клиент возлагается ответственность передавать текстовый поток. Можно это делать через распознавание голоса, или просто посылать команды через командный интерфейс.

Сейчас сделаны примеры нескольких клиентов:

  • run_remoteva_vosk.py - запускает распознавание с определенного микрофона с помощью VOSK, и отсылает результат на сервер. Кроме того, я собрал этот клиент в EXE-файл c помощью Auto-py-to-exe, что позволяет запускать его на машинах без установленного Питона. В предельном варианте у меня работало 4 таких клиента - по клиенту на 2 микрофонах на сервере + еще по клиенту на двух ноутбуках.

  • run_remoteva_cmdline.py - компактный демо-вариант клиента, позволяющий работать с Ириной через командную строку.

  • run_remoteva_cmdline_min.py - Абсолютно минимальный вариант для удаленного управления Ириной через командную строку (около 50 строк кода). Сделан только на нативных функциях Python, без установок пакетов (что может быть полезно, если захотите реализовать вариант для чего-то компактного без pip).

  • run_remote_telegrambot.py - Телеграм-клиент, о котором чуть позже

Про проблему голосового ответа в клиент-сервере

Вот сижу я за ноутбуком, и говорю "Ирина, прогноз погоды".

Вопрос - как должен осуществляться вывод? На сервере Ирины, через колонки? Или же на моем компьютере, звуком? Или, если я сижу в клиенте командной строки, возможно, я ожидаю ответ в текстовом виде?

Я решил, что однозначного ответа на этот вопрос нет, и для каждого клиента должны быть свои настройки. Для этого при вызове REST API предусмотрен параметр ttsFormat, который может принимать следующие значения:

  • "none" (TTS реакции будут на сервере)

  • "saytxt" (сервер вернет текст, возможно, TTS будет на клиенте. Или же клиент просто покажет сообщение текстом)

  • "saywav" (TTS на сервере, сервер создаст WAV согласно установленному голосу и вернет клиенту, клиент его проиграет) (звук на клиенте) 

Более того, поддерживаются комбинации параметров. Например, можно задать "none,saywav" - как что вызовет озвучку на сервере, так и передаст WAV-файл на клиент. 

Подробнее о клиент-серверных инсталляциях можно почитать в документации.

В общем, можно сделать как вам удобно.

Телеграм-клиент

Поскольку клиент-серверная модель была отлажена, возникла интересная идея - почему бы не сделать опцию управления Ириной через Телеграм-бота?

Долго ли коротко ли, он был сделан. Инструкция по установке здесь.

Из интересного - мне адски захотелось сделать фичу обработки голосовых сообщений в Телеграме, чтобы опыт команд был приближен к голосовому. Можно, конечно, и просто текстом команды посылать, но это не так весело.

В общем, сейчас можно:

  • отправить голосовое сообщение в бот

  • бот его распознает (с помощью VOSK)

  • далее вы можете либо запустить распознанную команду, либо проиграть исходное голосовое сообщение там, где запущен Телеграм-клиент(!). Этакая широковещательная штучка - возможность озвучить своё сообщение прямо через колонки.

Новые TTS (Text-to-Speech) движки

С момента запуска были добавлено несколько новых движков и голосов. Хочу отметить следующие:

  • RHVoice - для маломощных машин и Linux (стандартный Linux espeak не очень хорош, а вот RHVoice вполне)

  • silero_v3 - вчера был анонс на Хабре, голоса там очень качественные. Мне удалось быстро добавить их поддержку в Ирину; однако они предназначены для относительно мощных машин

Впрочем, я по-прежнему использую стандартный pyttsx, он мне нравится - в том числе и тем, что явно ощущается, что это робот. Предпочитаю об этом не забывать.

Поддержка контекста при общении

Изначально планировалось, что все обращения к Ирине будут начинаться с имени помощника - так предполагалось отсеивать команды от обычного разговора в комнате.

Но на практике оказалось, что это не всегда удобно. Иногда хочется, чтобы помощник просто переспросил - например, после фразы, "Ирина, мультик пыагьа", чтобы переспросил "Какой мультик?". Или, после фразы "Ирина, таймер ыывашел", был вопрос "Что после таймер?".

Сейчас это сделано. Плагины в определенных ситуациях могут задавать "контекст" - и если контекст задан, то голосовые обращения будут идти прямо в него, минуя остальные стадии распознавания команд. При этом контекст сбрасывается через 10 секунд (настраиваемо) - это позволяет Ирине возвращаться в обычное состояние даже если пользователь не ответил, или куда-то ушел.

Это может быть полезно в реализации голосовых игр, или, например, арифметических тестов для ребенка.

Как примера была сделана плагин-игра "Больше-меньше". В ней загадывается число от 1 до 30; задача отгадать его не более чем за 5 попыток.

Попробовал - вполне играбельно.

Интеграция с Home Assistant

Несмотря на несколько запросов на интеграцию Ирины с Home Assistant, я не хотел этим заниматься. У меня правило - стараться не программировать то, чем не пользуешься сам, а то сделаешь неудобно почти наверняка.

Однако юзер timhok буквально на днях выложил плагин, который позволяет запускать сценарии Home Assistant через команды Ирины (через REST API HA). Там есть красивое решение - если в описании сценарии есть строка типа ttsreply(Приятных снов), то именно этот ответ будет озвучен, если сценарий выполнен.

Если вы до этого командовали HA только через Алису, то теперь это вполне можно сделать и через Ирину.

Новые плагины и документация

Из новых интересных плагинов могу выделить:

plugin_finstockmoex.py - курс акций на Московской бирже (ох, намучался я с его получением!). В конфиге можно задать:

  • список акций для озвучки, несколько наборов при желании

  • собрать портфель из акций - тогда будет озвучиваться стоимость портфеля

Примеры команд: "ирина акции", "ирина акции сбер", ирина портфель тест"

plugin_urlopener.py - полезный плагин, если вы планируете открывать ссылки в браузере по голосовым командам.

Позволяет задать в конфиге набор команд, и URL, которые будут по ним открываться.

Конфиг настраивается в options/plugin_urlopener.json

Пример:

"cmds": {
    "главная яндекс": "https://yandex.ru/",
    "ютуб|юту": "https://www.youtube.com/results?search_query={}",
    "яндекс": "https://yandex.ru/search/?text={}"
},

Если в URL содержится {}, то он будет заменен на оставшуюся часть произнесенной фразы. Так, фраза "яндекс погода" запустит поиск в Яндексе по слову "погода".

Про документацию

Документация сильно обновилась. Сделаны примеры разработки плагинов, процедура настройки клиент-серверной модели. Ещё несколько важных документов по решению проблем при установке на Mac и Linux на основе отзывов пользователей.

В общем, это наконец-то не одна страничка. Вот например, оглавление документа "Разработка плагинов":

Типовые задачи

  1. Простейший плагин

  2. Плагин с пользовательскими настройками

  3. Плагин с кастомной обработкой пользовательских фраз

  4. Плагин с деревом команд

  5. Плагин с непрерывным взаимодействием (установлением контекста), или переспрашивающий

  6. Плагин, устанавливающий голосовые команды в зависимости от пользовательских настроек

В общем, документация правда стала сильно более полной.

В заключение - немного о поддержке проекта

Я немного поработал в западном опенсорсе. Впечатлило меня следующее - я понял, что живучесть проекта почти не определяется идеей, в него заложенной.

Живучесть определяется тем, сколько времени проект поддерживают.

Потому что писать код относительно весело.

А вот писать документацию, отвечать на вопросы, разбирать пулл-реквесты, договариваться с контрибьюторами, отлаживать баги в не самых обычных конфигурациях, обновлять проект под новые зависимости - уже не очень. Но проект в реальности во многом живет именно этим - небольшими проблемами и вопросами абсолютно реальных любдей.

Опенсорс-разработчик вынужден быть не только разработчиком, но и немного менеджером, техническим писателем, просто писателем и т.д. Но найти соавторов, которые взяли бы на себя часть функций непросто.

Так или иначе, у меня есть ощущение, что будущее "Ирины" - кастомизируемого голосового помощника, не завязанного на крупные корпорации - сейчас в значительной степени зависит от моего интереса. Скорее всего, именно от него зависит, сколько проект будет жить в публичном поле и получать апдейты.

Если Ирина вас порадовала, и вы хотите, чтобы проект жил подольше, то можно:

  • Написать плагин для Ирины. Это то, что меня очень сильно мотивирует - когда видишь, что кому-то проект настолько небезразличен :)

  • Поддержать материально подпиской на Boosty.to. Это тоже форма внимания. Видя подписчиков я понимаю, что кто-то действительно заинтересован в проекте.

  • Выразить благодарность в комментариях или личном сообщении. Это меня всегда радует :)

Спасибо за внимание!

Буду работать дальше.

Github проекта

Комментарии (15)


  1. ebt
    13.04.2022 21:39
    +2

    Слежу за похожим проектом self-hosted голосового ассистента, может быть, вам придутся кстати какие-то идеи оттуда.


    1. jekyll2017
      14.04.2022 01:31
      +3

      Проект Leon выглядит классно - нейросети и всё такое... Только я, возможно, не уловил чего-то, но набор навыков там довольно своеобразный. Скачивание видео из плейлиста YouTube, замер скорости канала, перечисление трендовых репозиториев на GitHub... Как будто инопланетянин писал. На какого потребителя расчитано? Возможно, Вы, как следящий за проектом, объясните мне? Мне действительно интересно - я сам пишу похожее и по-другому представлял себе типовые потребности пользователя такой системы.


      1. ebt
        14.04.2022 03:08

        Ну это скорее фреймворк, нежели готовый код. Насколько я понимаю, все допиливают его под какие-то свои конкретные нужды.


        1. janvarev Автор
          14.04.2022 09:01

          Спасибо за информацию, но я в предыдущей статье делал небольшой обзор помощников по материалам юзера putnik. Леон там был; насколько понял, там большая проблема с русским языком.

          Помощников russian-first-language вообще как-то нет.


  1. AigizK
    14.04.2022 07:30

    А вы всё распознаете или есть отдельная сетка, которая должна искать слово ИРИНА и потом запускать распознавание?


    1. janvarev Автор
      14.04.2022 08:58

      Нет, все делается через VOSK, специальной сетки нет.
      Имя помощника можно сменить.


  1. mwc-lord
    14.04.2022 09:01
    +2

    О, только на днях поставил, после видео Чёрного Треугольника.

    Пытаюсь-вот пользоваться... получается так себе.

    Очень много зависимостей, в основном достаточно устаревших. С моим никудышим опытом Linux на актуальной Манжаре, разрешить их не непросто.

    Громоздко в установке. Каждая смена tts-движка заставляет искать необходимые библиотеки (которые еще и в разных дистрибутивах называются по-разному ). Нужна автоматизация.

    НуженUI. Хотя бы в виде крохотного окошка с текущим статусом. Или плазмоида.

    На мой взляд не хватает самого главного плагина - ввод текста в активное приложение.

    Без всяких "Ирина привет/Ирина пока". Нажал кнопку (Ctrl|Meta) - наговорил (слов 10) - отпустил кнопку. Если бы еще распознанный текст вводился не после отпускания клавиши, было бы отлично. А если бы еще и в процессе отлавливать текстовые алиасы - было бы просто замечательно.

    Голосовой ввод (с хорошим распознаванием) сильно ускоряет работу с большим объемом текста, даже в сравнении со "слепым" методом. (Заодно развивая коммуникабельность). И просто незаменим в дороге/на небольших устройствах (https://store.steampowered.com/steamdeck) .

    До недавних пор пользовался Mspeech, затем Laitis под windows 10. Они хоть и завязаны на облачные сервисы, но более-менее работают.


  1. Andrey_OM
    14.04.2022 09:01
    +1

    Спасибо! Вам воспользовался вашим проектом очень Удобный голосовой помощник


  1. Jury_78
    14.04.2022 09:55
    +2

    Тоже занимаюсь чем то похожим, как хобби... Увидел у вас, что сделали перевод чисел в слова, на самом деле есть уже готовые библиотеки, например num2words


    1. janvarev Автор
      14.04.2022 10:01

      За библиотеку спасибо, гляну.
      В той, что сейчас используется, есть один бонус — возможность согласования с последующим существительным (формы слова задаются как параметр при вызове). Например, «один градус», «десять градусов».


      1. Jury_78
        14.04.2022 11:51
        +1

        Единиц измерений там конечно нет. Но так может:

        num2words(1, lang='ru') => 'один'

        num2words(1, lang='ru', to="ordinal") => 'первый'

        или так:

        num2words(1.3, lang='ru') => 'один запятая три'


  1. Tontu
    14.04.2022 12:15

    Не так давно попробовал на ассистента накатить NeMo от Nvidia. В первую очередь попробовал добавить TTS, но оказалось что предобученных моделей на русском просто нет. По-английски зато на предобученной модели FastSpeech2 говорит прекрасно. Но вот только один этот TTS модуль у меня на ноутбучной 3060 едва ли может обработать предложение из 25 слов. Памяти не хватает. Зато качество отличное. Пробую ещё обучить на датасете Ruslan модель GlowTTS, по идее она даже легче чем FastSpeech2. Если получится, оформлю подключаемый модуль с ним.


    1. janvarev Автор
      14.04.2022 12:47

      О, буду рад добавлениям!
      Вообще довольно круто по качеству работает анонсированный позавчера TTS Silero v3.


      1. Tontu
        14.04.2022 13:20
        +1

        Я из их статьи ссылку на датасет и нашёл. Посмотрим. В принципе для голосового ассистента все подобные модели дают хорошее качество. Ещё надо STT прикрутить, но там предобученная модель на русском есть, так что проблем не должно быть. Ну кроме размера, не факт что TTS и STT смогут одновременно крутиться в памяти. STT можно прямо сейчас подключать и пробовать, но это легко и не спортивно :) так что я начал с TTS.


  1. Vorobeyrr
    15.04.2022 09:14
    +1

    Буквально вчера до 3 ночи просидел в интернете с идеей сделать голосового управления умным домом. И совсем забыл, что недавно читал твою первую статью. Хорошо, что хром сейчас предложил мне эту статью.

    В первую очередь хочу сказать, что это колоссальный труд и я постараюсь любым возможным способом его поддержать!

    Думаю такой ассистент действительно найдёт применение в связке с Home Assistant, так как русскоязычных ассистентов с возможностью кастомизации под себя ну просто нет. Ту же Алису полноценно под себя не запилишь (хотя бы переименовать, чтобы отзывалась на другое имя), в Raspberry PI не запихнёшь, да и у нас к ней доступ только через VPN.

    Поэтому желаю успехов в начинаниях и неугасающего интереса!

    С нетерпением жду следующего поста!