Наверняка, каждый мечтает о своем голосовом ассистенте, под катом еще одна реализация «Джарвиса» из известного фильма.

Давно не покидала мысль о своем «Jarvis» и управлении техникой в доме голосом. И вот, наконец, руки дошли до создания сего чуда. Над «мозгами» долго думать не пришлось, Raspberry Pi подходит идеально.
Итак, железо:
Работать наш ассистент будет по принципу Alexa/Hub:
Т.к. моя камера поддерживается из коробки, с драйверами возиться не пришлось, поэтому сразу переходим к программной части.
Активация будет происходить с помощью CMU Sphinx, и все бы хорошо, но из коробки распознание происходит очень медленно, больше 10 сек, что абсолютно не подходит, для решения проблемы нужно очистить словарь от ненужных слов.
Устанавливаем все необходимое:
далее
удаляем все кроме нужного нам Джарвиса:
Теперь pocketsphinx распознает довольно быстро.
Сначала была идея воспользоваться сервисом гугла, к тому же его поддержка есть в SpeechRecognition. Но как оказалось гугл берет за это деньги и не работает с физ. лицами.
Благо Яндекс тоже предоставляет такую возможность, бесплатно и предельно просто.
Регистрируемся, получаем API KEY. Все работу можно производить curl’om.
Тут нам опять поможет Яндекс. Посылаем текст в ответ получаем файл с синтезированным текстом
Собираем все вместе и получаем такой скрипт.
Что тут происходит. Запускаем бесконечный цикл, arecord’om записываем три секунды и отправляем sphinx на распознание, если в файле встречается слово «jarvis»
проигрываем заранее записанный фаил оповещения об активации.
Опять записываем 3 секунды и отправляем Яндексу, в ответ получаем нашу команду. Далее выполняем действия исходя из команды.
На этом собственно все. Сценариев выполнения можно придумать великое множество.
Теперь немного примеров реального моего использования
Устанавливаем
В приложении Hue устанавливаем статический IP:

Запускаем:
Выписываем ID нужных схем, вида «470d4c3c8-on-0»
Конечный вариант скрипта:
В джарвиса добавляем:
Берем скрипт отсюда. После первого запуска и ввода кода сопряжения, сам код не меняется, поэтому можно выпилить эту часть из скрипта и оставить только управляющую.
В джарвиса добавляем:
В джарвиса д��бавляем:
Еще можно поставить homebridge и управлять всем через Siri, в случае если до джарвиса не докричаться.
Что касается качества распознавания речи, не Alexa конечно, но на расстоянии до 5 метров процент верного попадания приличный. Главная проблема — речь из телевизора\колонок записывается вместе с командами и мешает распознаванию.
На этом все, спасибо.

Давно не покидала мысль о своем «Jarvis» и управлении техникой в доме голосом. И вот, наконец, руки дошли до создания сего чуда. Над «мозгами» долго думать не пришлось, Raspberry Pi подходит идеально.
Итак, железо:
- Raspberry pi 3 model b
- USB камера logitech
Реализация
Работать наш ассистент будет по принципу Alexa/Hub:
- Активироваться оффлайн по определенному слову
- Распознать команду в облаке
- Выполнить команду
- Отчитаться о проделай работе либо сообщить запрашиваем информацию
Т.к. моя камера поддерживается из коробки, с драйверами возиться не пришлось, поэтому сразу переходим к программной части.
Оффлайн активация
Активация будет происходить с помощью CMU Sphinx, и все бы хорошо, но из коробки распознание происходит очень медленно, больше 10 сек, что абсолютно не подходит, для решения проблемы нужно очистить словарь от ненужных слов.
Устанавливаем все необходимое:
pip3 install SpeechRecognition pip3 install pocketsphinx
далее
sudo nano /usr/local/lib/python3.4/dist-packages/speech_recognition/pocketsphinx-data/en-US /pronounciation-dictionary.dict
удаляем все кроме нужного нам Джарвиса:
jarvis JH AA R V AH S
Теперь pocketsphinx распознает довольно быстро.
Распознавание речи
Сначала была идея воспользоваться сервисом гугла, к тому же его поддержка есть в SpeechRecognition. Но как оказалось гугл берет за это деньги и не работает с физ. лицами.
Благо Яндекс тоже предоставляет такую возможность, бесплатно и предельно просто.
Регистрируемся, получаем API KEY. Все работу можно производить curl’om.
curl -X POST -H "Content-Type: audio/x-wav" --data-binary "@file" «https://asr.yandex.net/asr_xml?uuid=ya_uid&key=yf_api_key&topic=queries»
Синтез речи
Тут нам опять поможет Яндекс. Посылаем текст в ответ получаем файл с синтезированным текстом
curl «https://tts.voicetech.yandex.net/generate?format=wav&lang=ru-RU&speaker=zahar&emotion=good&key=ya_api_key» -G --data-urlencode "text=text" > file
Jarvis
Собираем все вместе и получаем такой скрипт.
#! /usr/bin/env python # -*-coding:utf-8-*- import os import speech_recognition as sr from xml.dom import minidom import sys import random r = sr.Recognizer() ya_uuid = '' ya_api_key = '' # os.system('echo "Ассист+ент зап+ущен" |festival --tts --language russian') def convert_ya_asr_to_key(): xmldoc = minidom.parse('./asr_answer.xml') itemlist = xmldoc.getElementsByTagName('variant') if len(itemlist) > 0: return itemlist[0].firstChild.nodeValue else: return False def jarvis_on(): with sr.WavFile("send.wav") as source: audio = r.record(source) try: t = r.recognize_sphinx(audio) print(t) except LookupError: print("Could not understand audio") return t == ("jarvis") def jarvis_say(phrase): os.system( 'curl "https://tts.voicetech.yandex.net/generate?format=wav&lang=ru-RU&speaker=zahar&emotion=good&key='+ya_api_key+'" -G --data-urlencode "text=' + phrase + '" > jarvis_speech.wav') os.system('aplay jarvis_speech.wav') def jarvis_say_good(): phrases = ["Готово", "Сделано", "Слушаюсь", "Есть", "Что-то еще?", ] randitem = random.choice(phrases) jarvis_say(randitem) try: while True: os.system('arecord -B --buffer-time=1000000 -f dat -r 16000 -d 3 -D plughw:1,0 send.wav') if jarvis_on(): os.system('aplay jarvis_on.wav') os.system('arecord -B --buffer-time=1000000 -f dat -r 16000 -d 3 -D plughw:1,0 send.wav') os.system( 'curl -X POST -H "Content-Type: audio/x-wav" --data-binary "@send.wav" "https://asr.yandex.net/asr_xml?uuid='+ya_uuid+'&key='+ya_api_key+'&topic=queries" > asr_answer.xml') command_key = convert_ya_asr_to_key() if (command_key): if (command_key in [‘key_word', ‘key_word1’, ‘key_word2']): os.system(‘’) jarvis_say_good() continue except Exception: jarvis_say('Что-то пошло не так')
Что тут происходит. Запускаем бесконечный цикл, arecord’om записываем три секунды и отправляем sphinx на распознание, если в файле встречается слово «jarvis»
if jarvis_on():
проигрываем заранее записанный фаил оповещения об активации.
Опять записываем 3 секунды и отправляем Яндексу, в ответ получаем нашу команду. Далее выполняем действия исходя из команды.
На этом собственно все. Сценариев выполнения можно придумать великое множество.
Use-case
Теперь немного примеров реального моего использования
Philips Hue
Устанавливаем
pip install phue
В приложении Hue устанавливаем статический IP:

Запускаем:
#!/usr/bin/python import sys from phue import Bridge b = Bridge('192.168.0.100') # Enter bridge IP here. #If running for the first time, press button on bridge and run with b.connect() uncommented #b.connect() print (b.get_scene())
Выписываем ID нужных схем, вида «470d4c3c8-on-0»
Конечный вариант скрипта:
#!/usr/bin/python import sys from phue import Bridge b = Bridge('192.168.0.100') # Enter bridge IP here. #If running for the first time, press button on bridge and run with b.connect() uncommented #b.connect() if (sys.argv[1] == 'off'): b.set_light([1,2,3],'on', False) else: b.activate_scene(1,sys.argv[1])
В джарвиса добавляем:
if (command_key in ['включи свет', 'включить свет', 'свет']): os.system('python3 /home/pi/smarthome/hue/hue.py a1167aa91-on-0') jarvis_say_good() continue if (command_key in ['приглуши свет', 'приглушить свет']): os.system('python3 /home/pi/smarthome/hue/hue.py ac637e2f0-on-0') jarvis_say_good() continue if (command_key in ['выключи свет', 'выключить свет']): os.system('python3 /home/pi/smarthome/hue/hue.py "off"') jarvis_say_good() continue
LG TV
Берем скрипт отсюда. После первого запуска и ввода кода сопряжения, сам код не меняется, поэтому можно выпилить эту часть из скрипта и оставить только управляющую.
В джарвиса добавляем:
#1 - POWER #24 - VOLUNE_UP #25 - VOLUME_DOWN #400 - 3D_VIDEO if (command_key in ['выключи телевизор', 'выключить телевизор']): os.system('python3 /home/pi/smarthome/TV/tv2.py 1') jarvis_say_good() continue if (command_key in [‘прибавь громкость', 'громче']): os.system('python3 /home/pi/smarthome/TV/tv2.py 24') jarvis_say_good() continue
Радио
sudo apt-get install mpg123
В джарвиса д��бавляем:
if (command_key in ['новости', ‘выключи новости’,’что происходит’]): os.system(‘mpg123 URL') continue
Еще можно поставить homebridge и управлять всем через Siri, в случае если до джарвиса не докричаться.
Что касается качества распознавания речи, не Alexa конечно, но на расстоянии до 5 метров процент верного попадания приличный. Главная проблема — речь из телевизора\колонок записывается вместе с командами и мешает распознаванию.
На этом все, спасибо.
