Наверняка, каждый мечтает о своем голосовом ассистенте, под катом еще одна реализация «Джарвиса» из известного фильма.
Давно не покидала мысль о своем «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_sya_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_sya_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_sya_good()
continue
if (command_key in ['приглуши свет', 'приглушить свет']):
os.system('python3 /home/pi/smarthome/hue/hue.py ac637e2f0-on-0')
jarvis_sya_good()
continue
if (command_key in ['выключи свет', 'выключить свет']):
os.system('python3 /home/pi/smarthome/hue/hue.py "off"')
jarvis_sya_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_sya_good()
continue
if (command_key in [‘прибавь громкость', 'громче']):
os.system('python3 /home/pi/smarthome/TV/tv2.py 24')
jarvis_sya_good()
continue
Радио
sudo apt-get install mpg123
В джарвиса добавляем:
if (command_key in ['новости', ‘выключи новости’,’что происходит’]):
os.system(‘mpg123 URL')
continue
Еще можно поставить homebridge и управлять всем через Siri, в случае если до джарвиса не докричаться.
Что касается качества распознавания речи, не Alexa конечно, но на расстоянии до 5 метров процент верного попадания приличный. Главная проблема — речь из телевизораколонок записывается вместе с командами и мешает распознаванию.
На этом все, спасибо.
Автор: WSN3