Skip to content

Instantly share code, notes, and snippets.

@ChrisB85
Last active January 1, 2022 21:24
Show Gist options
  • Save ChrisB85/3e3fd98493ceb2398be63e9d63271361 to your computer and use it in GitHub Desktop.
Save ChrisB85/3e3fd98493ceb2398be63e9d63271361 to your computer and use it in GitHub Desktop.
Sterowanie urządzeniami głosem w języku polskim przy użyciu Raspberry Pi, asystenta Snips i Home Assistant
Co będzie potrzebne?
- Raspberry Pi (zalecane 3B lub 3B+, ale myślę, że 2 również da radę) z zainstalowanym Raspbianem
- Głośnik i mikrofon. Można użyć zwykłego "dongla" typu https://pupilsys.com/image/cache/catalog/Product_images/PS139/USB_soundCard-600x600.jpg z wejściem na mikrofon i wyjściem na głośniki lub przystawki typu HAT. Ja użyłem Sound Blaster SBX8, czyli głośnik i mikrofon USB w jednym (http://www.benchmark.pl/mini-recenzje/creative-sound-blaster-axx-sbx8-test.html). Jedyny problem jaki napotkałem i którego nie udało mi się przeskoczyć, to "rwanie" dźwięku (zarówno nagrywanie jak odtwarzanie) w sytuacji, kiedy system jest również na nośniku podłączonym pod USB (u mnie dysk SSD). W przypadku systemu na karcie SD wszystko jest OK. Należy również zwrócić uwagę na fakt, że głośnik ten pobiera maksymalnie 1A z portu USB.
1. Instalacja
Wykonujemy instalację zgodnie z instrukcją: https://docs.snips.ai/getting-started/quick-start-raspberry-pi (kroki 1-4). Nie opisuję tutaj tego dokładniej, bo dokumentacja ulega modyfikacjom. Podczas moich zabaw kilka rzeczy się zmieniło w "międzyczasie" (konkretnie to zostało opisane dokładniej).
2. Tworzenie asystenta
Rejestrujemy się na https://console.snips.ai, tworzymy nowy model asystenta jako język wybierając angielski. Sam proces tworzenia modelu asystenta jest dokładnie opisany na stronie https://docs.snips.ai/getting-started/quick-start-console
3. Obsługa języka polskiego
Rozpoznawanie języka polskiego (ASR):
Odinstalowujemy pakiet snips-asr, a następnie instalujemy snips-asr-google
sudo apt-get remove snips-asr
sudo apt-get install snips-asr-google
sudo systemctl restart snips-*
Rejestrujemy się na https://console.cloud.google.com
Tworzymy nowy projekt, z menu bocznego wybieramy Interfejsy API i usługi. Wyszukujemy i włączamy Cloud Speech API. Przechodzimy do zakładki Dane logowania i klikamy Utwórz dane logowania -> Klucz konta usługi, jako typ wybieramy JSON. Po kliknięciu przycisku Utwórz powinniśmy otrzymać plik JSON, który zapisujemy pod nazwą googlecredentials.json i umieszczamy w katalogu /usr/share/snips
UWAGA! Do korzystania z tej usługi Google wymaga podania danych karty płatniczej. W pakiecie darmowym Cloud Speech API otrzymujemy 60 minut/miesiąc przy naliczaniu 15-sekundowym. Wszystko powyżej naliczane jest wg cennika https://cloud.google.com/speech-to-text/pricing?hl=pl
Aktualne informacje o stanie konta można znaleźć pod adresem https://console.cloud.google.com/billing
Mowa w języku polskim (TTS):
Klonujemy repozytorium https://github.com/ChrisB85/snips_custom_tts do dowolnego katalogu na naszym RPI. Nadajemy plikowi snipsGoogle.sh uprawnienia do wykonywania (755, właściciel pi). W pliku config.sh wskazujemy katalog dla plików cache pamiętając o uprawnieniach (u mnie akurat 777).
W pliku /etc/snips.toml dodajemy na końcu
provider = "customtts"
customtts = { command = ["pełna_ścieżka_do_pliku_snipsGoogle.sh", "%%OUTPUT_FILE%%", "pl", "%%TEXT%%"] }
3. Integracja z protokołem MQTT: Wyszukujemy i dodajemy w konsoli Snips do naszego modelu asystenta aplikację o nazwie UniDeviceControl, której zadaniem jest przekształcić nasze polecenia na publikacje MQTT. Aby ją dostosować do własnych potrzeb, najlepiej ją "sforkować" - będziemy mogli wtedy dodać własne polecenia i urządzenia.
Aplikacja UniDeviceControl obsługuje "na dzień dobry" następujące intencje (można to rozumieć jako rozpoznane przez asystenta polecenia, które wydajemy):
TurnOff - wyłączanie urządzenia (Hej Snips, wyłącz [urządzenie])
TurnOn - włączanie urządzenia (Hej Snips, włącz [urządzenie])
Unmute - przywracanie dźwięku (Hej Snips, przywróć dźwięk [urządzenie])
Mute - wyciszanie (Hej Snips, wycisz [urządzenie])
Pause - pauza w odtwarzaniu (Hej Snips, wstrzymaj [urządzenie])
Stop - zatrzymanie odtwarzania (Hej Snips, zatrzymaj [urządzenie])
Play - rozpoczęcie odtwarzania (Hej Snips, odtwarzaj [urządzenie])
Dodatkowo jest jeszcze intencja pomocnicza o nazwie DeviceControlAnswer używana w momencie, gdy asystent nie do końca nas zrozumie. Przykładowo powiemy:
- Hej Snips, włącz komputer.
Jeśli Snips nie zrozumie słowa komputer, zada pytanie:
- Co chcesz włączyć?
Odpowiadając "komputer" intencja zamiast TurnOn przyjmie nazwę DeviceControlAnswer.
4. Wdrażanie asystenta z konsoli na RPI:
Model asystenta instalujemy na RPI zgodnie z krokiem 5 z instrukcji z punktu 1. Podczas wdrażania asystenta na Raspberry Pi powinno zostać pobrane repozytorium https://github.com/ChrisB85/snips_mqtt
Możliwe, że pojawi się również komunikat o konieczności nadania plikowi /var/lib/snips/skills/snips_mqttaction-snips-mqtt.py uprawnień do wykonywania. U mnie jest to 755.
Na końcu instalacji kreator zapyta nas o dane dostępowe do MQTT (można je ustawić w pliku /etc/snips.toml) - domyślnie nie ma żadnego loginu i hasła, więc wystarczy wciskać ENTER.
WAŻNE! Po każdym wdrożeniu asystenta na RPI, należy w pliku /usr/share/snips/assistant/assistant.json zmienić kod języka ("language") z "en" na "pl" i zrestartować usługi Snipsa poleceniem sudo systemctl restart 'snips-*'
UWAGA! Podczas wdrażania asystenta skrypt instalacyjny "przetwarza" plik configuration.yaml m.in. wyrzucając komentarze i (przynajmniej w moim przypadku) nadpisuje linię z "intent_scripts:". Co prawda przed całą operacją robi również kopię tego pliku, ale jeśli nie chcemy aby cokolwiek w nim "mieszał", najlepiej zmienić właściciela na root, odebrać prawa do zapisu i umożliwić jedynie odczyt.
4. Integracja z Home Assistant:
Dokumentacja komponentu Snips dla HA znajduje się pod adresem https://www.home-assistant.io/components/snips/
W pliku konfiguracyjnym HA (configuration.yaml) dopisujemy "snips:" i restartujemy HA.
Domyślnie Snips integruje się z HA poprzez tzw intent scripts, natomiast aplikacja UniDeviceControl umożliwia przekształcenie intencji na publikacje MQTT o strukturze:
[satelita]/[temat]/[wartość]
gdzie:
[satelita] - inaczej site_id; domyślnie default. Snips umożliwia obsługę wielu stacji "nasłuchowych" (dla wielu pomieszczeń). Dokładniej jest to opisane na stronie https://docs.snips.ai/articles/raspberrypi/satellites
[temat] - intencja/wydane polecenie np. TurnOn
[wartość] - nazwa urządzenia wg. aplikacji UniDeviceControl.
Przykładowo wydając polecenie "Hej Snips, włącz komputer", wystawiona publikacja będzie miała postać:
default/TurnOn/computer
zatem w Home Assistant możemy ustawić następujący wyzwalacz:
Typ wyzwalacza:
MQTT
Temat:
default/TurnOn
Payload:
computer
Komunikaty zwrotne (czyli to co Snips odpowie), można wywołać poprzez usługę snips.say z poziomu HA. Przykładowo możemy wywołać usługę z danymi:
{
"site_id": "default",
"text": "Włączam komputer"
}
Dzięki temu z satelity "default" usłyszymy to, co podaliśmy jako argument "text".
Pomocne polecenia:
sam watch - podgląd zdarzeń Snips (rozpoznawanie mowy, intencji itp.)
sam status - status usług Snips; oczywiście po deinstalacji pakietu snips-asr normalnym będzie, że usługa o tej samej nazwie nie będzie działać.
sam setup audio - konfiguracja dźwięku (mikrofonu i głośników)
sam update-assistant - aktualizacja modelu asystenta (pobieranie modelu z konsoli Snips na RPI)
sudo journalctl -u snips-skill-server - podgląd dziennika akcji
@ChrisB85
Copy link
Author

ChrisB85 commented Feb 25, 2019

Po aktualizacji komponentów do wersji 0.61.1 występują problemy z Google ASR. Problem można usunąć poprzez przywrócenie poprzedniej wersji komponentu snips-asr-google:
sudo apt-get install snips-asr-google=0.60.12

@mredone
Copy link

mredone commented Sep 26, 2019

Dziękuję za tutorial.
Możesz mi powiedzieć czy dobrze rozumiem. Google zaokrągla każdy request do 15 sekund? Czyli mówimy 3-4 sekundy a on zaokrągla do 15sekund? Czy dopiero po osiągnięciu 15 sekund razem pobiera opłatę?

@ChrisB85
Copy link
Author

Tak wynika z dokumentacji https://cloud.google.com/speech-to-text/pricing
PS. Niestety obecnie komponent Snips Google ASR nie działa wcale. Google wprowadziło zmiany w API.

@ChrisB85
Copy link
Author

W dniu wczorajszym udało mi się wykonać własną implementację komponentu ASR w oparciu o Google Cloud. Działa z najnowszą wersją Snips. Można ją znaleźć pod tym adresem https://github.com/ChrisB85/snips_google_asr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment