NEWS
Rhasspy Offline Sprachsteuerung
-
@tobetobe
Hi,
ich habe mich nach Deinen Erläuterungen auch mal an Rasspy gewagt.
Habe es auch soweit hinbekommen, daß ich die Installation auf einem Rasp3B unter Raspbian Buster light im Docker mit deutschem Profil hinbekommen habe.
Ich habe dazu diese Anleitung verwendet: Rhasspy-Installation (Docker)., allerdings das Rhasspy-Docker-Image auf de geändert ( -- profile de ) :docker run -d -p 12101:12101 \ --restart unless-stopped \ -v "$HOME/.config/rhasspy/profiles:/profiles" \ --device /dev/snd:/dev/snd \ synesthesiam/rhasspy-server:latest \ --user-profiles /profiles \ --profile de
Ich muß gestehen, daß ich mich noch nie mit Docker beschäftigt habe und auch jetzt nicht so recht weiß, wozu ich das brauche?
Als Micro verwende ich das ReSpeaker 4-Mic Array:
War etwas kompliziert, die Treiber dafür zu installieren, aber jetzt läuft es, allerdings ohne die farbigen LEDs (damit kann ich aber leben).Nach Aufruf der entspr. <IP>:12101 im Browser war dann auch die Benutzeroberfläche von Rhasspy zu sehen.
Dann habe ich einige Wörter im Reiter Words angelegt:wohnzimmerlampe V OOH N TS IH M EX L AH M P AX wandspots V AH N CH P AO TS an Q AH N aus Q AW S esstischlampe Q EH S TS IH SH L AH M P EHH palme P AH L M AX hydro HH YYH D RR OOH regal RR EEH G AAH L regallicht RR EEH G AAH L L IH CC T fernsehbeleuchtung F EH EX N Z EEH B AX L OO OH CC T UU NG couchbalkon K AH UH CH B AH L K OOH N ledwürfel L EH D V YY RR F AX L
Habe auch versucht, die Aussprache (Pronounciation)zu testen, aber das hört sich m.E. doch recht "hölzern" an.
Die Aussprache hört sich allerdings nur halbwegs verständlich an, wenn die Ausgabe ich "Phonemes" stelle, und nicht wie von Dir vorgeschlagen auf "Words"?Dann habe ich im Reiter "Sentences" unter [ChangeLightState] diese Wörter entspr. eingtragen, weil ich damit einige Lampen, bzw. 433 MHZ Steckdosen steuern will:
[ChangeLightState] light_name = (fernsehbeleuchtung | esstischlampe | wandspots | regallicht | palme | hydro | ledwürfel ) {name} light_state = (ein | aus) {state} schalte (die | das) <light_name> <light_state>
Im Reiter "Slots" habe ich gar nichts eingtragen.
In den "Settings" habe ich MQTT mit enstpr. IP-Adresse des ioBroker enabled.
Im ioBroker-Datenpunkt mqtt.0.rhasspy.intent.ChangeLightState kommt dann auch der entspr. JSON-String an, wie z.B: {"name": "fernsehbeleuchtung", "state": "aus"}
Diesen Datenpunkt werte ich dann mit einem JavaScript aus://##################################################################### // Rhasspy empfangen und entspr.Datenpunkte setzen //##################################################################### const empfangen = 'mqtt.0.rhasspy.intent.ChangeLightState' // Infrarot empfangen on({id: empfangen, change: "any"},function(obj) { let empf_code = getState(empfangen).val ; //log ("EMPF-CODE: " + empf_code); let empf_json = JSON.parse(empf_code); //log ("EMPF_JSON: " + empf_json); let name = empf_json.name; let state = empf_json.state; log ("name: " + name + " state: " + state); if (name == "wandspots" && state == "ein") { setState ('hm-rpc.2.CUX4000001.7.PRESS_LONG', true); log ("wandspots ein"); } else if(name == "wandspots" && state == "aus") { setState ('hm-rpc.2.CUX4000001.7.PRESS_SHORT', true); log ("wandspots aus"); } else if(name == "regal" && state == "ein") { setState ('hm-rpc.2.CUX4000001.1.PRESS_LONG', true); log ("regallicht ein"); } else if(name == "regal" && state == "aus") { setState ('hm-rpc.2.CUX4000001.1.PRESS_SHORT', true); log ("regallicht aus"); } else if(name == "palme" && state == "ein") { setState ('hm-rpc.2.CUX4000001.3.PRESS_LONG', true); log ("palme ein"); } else if(name == "palme" && state == "aus") { setState ('hm-rpc.2.CUX4000001.3.PRESS_SHORT', true); log ("palme aus"); } else if(name == "hydro" && state == "ein") { setState ('hm-rpc.2.CUX4000001.8.PRESS_LONG', true); log ("hydro ein"); } else if(name == "hydro" && state == "aus") { setState ('hm-rpc.2.CUX4000001.8.PRESS_SHORT', true); log ("hydro aus"); } else if(name == "ledquub" && state == "ein") { setState ('hm-rpc.2.CUX4000001.5.PRESS_LONG', true); log ("ledcube ein"); } else if(name == "ledquub" && state == "aus") { setState ('hm-rpc.2.CUX4000001.5.PRESS_SHORT', true); log ("ledcube aus"); } else if(name == "fernsehbeleuchtung" && state == "ein") { setState ('hm-rega.0.10074', true); log ("fernsehlicht ein"); } else if(name == "fernsehbeleuchtung" && state == "aus") { setState ('hm-rega.0.10074', false); log ("fernsehlicht aus"); } }); // Ende on(id)
Das funktioniert auch soweit und die entspr. Steckdosen werden geschaltet, allerdings nur wenn ich vor dem Absetzen des Sprachbefehls den gelben "WAKE-Button" drücke.
Soweit, so gut - evtl. kannst Du mir noch ein paar Tipps zu folgenden Fragen geben?:
1.) Ich bin mir nicht sicher, ob ich wirklich das deutsche Profil verwende.
In der Oberfläche von Rhasspy wird zwar "de" angezeigt, die Aussprache hört sich m.E. trotzdem recht Englsch an.
(Ich habe auch im Reiter "Advanced" alle Begriffe des Profils von "en" auf "de" geändert.)2.) Wozu ist der "Train-Button" (trainieren)?
Wenn ich den Anklicke und ein paar mal ein Wort, oder Satz spreche, kommt nur eine Meldung, wie z.B.: Training completed in 4.32 second(s)
Was und wozu soll da trainiert werden? ( ein Wort, ein Satz ? ), bzw. wo wirkt sich das aus?3.) Ich bekomme es um's Verrecken nicht hin, das Rhasspy auf ein Wake-Word reagiert.
Ich habe in den Settings bei "Wake Word": Use Pocketsphinx on this device angehakt, aber wenn ich dann "okay rhasspy" sage, tut sich nichts.
Ich habe es auch mit Snowboy und Porcupine versucht, aber da sind dann wohl Zusatzinstallationen notwendig?
Bei Porcupine steht als Hinweis: "Put keyword files in the porcupine directory in your profile", aber ich weiß leider nicht, wo mein profile-Verzeichnis liegt
Wahrscheinlich liegt das irgendwo in den Tiefen des Docker-Containers, aber wie schon erwähnt, kenne ich mich mit Docker nicht aus.Es wäre nett, wenn Du mir bei meinen Fragen helfen könntest, wobei mir primär das Problem mit dem Wake-Word am wichtigsten ist, denn wenn ich jedes Mal erst den Wake-Button drücken muss, ist Rhasspy ja eigentlich nutzlos.
Gruß und Danke im Voraus
Jörg -
@joergeli
Hallo Jörg,
da bist du ja schon ganz gut unterwegs.Ich gehe mal kurz auf deine Fragen ein. Vorab: Docker ist eine Methode, um eigenständige Prozesse/Installationen in einer virtuellen Umgebung (venv) zu verpacken. Alternativ wäre ja auch die Installation von Rhasspy in einer virtuellen Python-Umgebung möglich (die bei mir aber nicht lief). Da deine Installation lauffähig ist, brauchst du dich zunächst mal nicht weiter um Docker zu kümmern, und kannst dich weiter mit der Konfiguration von Rhasspy befassen.So nun zu deinen Fragen (soweit ich sie beantworten kann, bin selbst noch Rhasspy-Anfänger):
-
Du hast das de-Profil installiert und es funktioniert. Somit ist dies in Ordnung. Die Qualität der Aussprache hat mit der verwendeten text2speech-Engine zu tun, und ist bei nicht Cloud-basierten Systeme nunmal deutlich schlechter. Das ganze ist immer ein Kompromiss zwischen Qualität, Rechenleistung und Reaktionszeit. Antworten aus der Cloud sind qualitativ besser, dauern aber länger. Bei den Settings für Text2Speech werden Alternativen zum einfachsten System (espek) angeboten. Getestet habe ich diese noch nicht. Da ich momentan nur Befehle an Geräte senden möchte, ist das für mich auch zunächst noch nicht relevant.
-
Training: Das Ändern von Settings, auch das Editieren zB der Custom Words, führt noch nicht dazu, dass Rhasspy mit diesen geänderten Einstellungen arbeiten kann. Rhasspy muss damit erst vertraut gemacht werden. Dazu dient der Train Button. Trainiert werden also neue Wörter, Sätze, Einstellungen etc
-
Danke für den Hinweis. Ich habe beim Testen immer brav den gelben Knopf gedrückt und das Kommando anschließend mit Okay Rhasspy eingeleitet. Tatsächlich wurde das Wake Word "OK Rhasspy" jedoch gar nicht erkannt. Zum Testen von Befehlssequenzen reicht es also vollkommen aus, den gelben Knopf zu drücken und das Kommando ohne "OK Rhasspy" zu sprechen. Es ist also auch bei mir so, dass das wake Word in der Einstellung "Pocketsphinx" gar nicht erkannt wird. Nach allem, was ich der Dokumentation (https://rhasspy.readthedocs.io/), im Rhasspy Forum (https://community.rhasspy.org/) und im Home Assistant Forum (https://community.home-assistant.io/t/rhasspy-offline-voice-assistant-toolkit/) gelesen habe, hat dies mit der Einstellung der Sensitivität zu tun. Hier hilft nur Ändern, Trainieren, Testen, ... Damit wollte ich mich nicht aufhalten und habe kurzerhand Snowboy installiert. Egal, ob Porcupine oder Snowboy: Du hast recht, es müssen weitere Installationen voregenommen werden. Dies geht jedoch völlig unkompliziert: Einfach den im Pop up Fenster angebotenen Download annehmen, Rhasspy neustarten und nochmals trainieren. Snowboy hat so bei mir auf Anhieb funktioniert. Falls dir Porcupine lieber istmusst du die Keyword Files in diesem Verzeichnis ablegen: ./home/pi/.config/rhasspy/profiles/de/ Ggf. heißt dein User nicht "pi", dann musst du den Pfad anpassen. Jedenfalls ist deine Befürchtung hinfällig, dass Rhasspy von der gelben Taste abhängig ist.
Good Luck weiterhin.
Beste Grüße
Thomas -
-
@tobetobe
Hallo Thomas,
Heureka, ich habe Rhasspy soweit am Laufen
Ich habe für das WakeWord jetzt ebenfalls Snowboy installiert.
Es war allerdings etwas kompliziert, ein eigenes WakeWord zu erstellen, da das via Browser auf https://snowboy.kitt.ai generiert wird.
Auf dem Raspi ist aber Buster light installiert, also Headless ohne Browser, also habe ich das von einem WIndows-Rechner mit Firefox gemacht.
Ich mich unter dem o.a. Link angemeldet und ein eigenes Hotword namens "Hiwi" erstellt.
Dort wird nach 3maligem Sprechen des Hotwords eine Datei namens <Hotword>.pmdl, bei mir also Hiwi.pmdl, erstellt und zum Download angeboten.
Die Datei habe ich habe ich anschließend in den Raspi-Ordner ~/.config/rhasspy/profiles/de/snowboy übertragen.
Im gleichen Ordner liegt übrigens auch die Datei snowboy.umdl.Anschließend im Web-Frontend von Rhasspy unter Settings -> Wake Word -> "Use snowboy on this device " aktiviert und unter "Model Names" dann "snowboy/Hiwi.pmdl" eingetragen.
E voila, Rhasspy reagiert jetzt einwandfrei auf das Wake Word "Hiwi".Zum Steuern meiner Lampen, Geräte, etc. mit ioBroker, verwende ich aber anstatt NodeRed lieber JavaScript.
Zur Erläuterung:
Im Rhasspy-Frontend lege ich unter Sentences die entspr. Sätze an:[ChangeLightState] light_name = (fernsehbeleuchtung | esstischlampe| essecke | wandspots | regal | couchjoerg | couchrenate | palme | hydro | | regal | ledcube ) {name} light_state = (ein | aus) {state} schalte (die | das | den) <light_name> <light_state> [Scenes] scene_name = (schlafen | fernsehen ) {name} scene_state = (ein | aus) {state} Ich moechte <scene_name> <scene_state> [Rolladen] rolladen_name = (rolladen ) {name} rolladen_state = (hoch | runter | stop ) {state} Fahre <rolladen_name> <rolladen_state>
Es werden also 3 intents: ChangeLightState, Scenes und Rolladen erzeugt.
Diese werden automatisch via MQTT als ioBroker-Objekte unter mqtt.0.rhasspy.intent angelegt.
Das Objekt mqtt.0.rhasspy.intent.ChangeLightState bekommt dann z.B. den Wert {"name": "regal", "state": "aus"}, also ein JSON.
Mit einem JavaSript prüfe ich fortwährend, ob sich ein intent geändert hat und filtere dann mit ein paar if-Abfragen den Namen und den State aus dem JSON.
Mit diesen beiden Bedingungen kann ich dann den gwünschten Datenpunkt setzen und somit die gewünschte Reaktion, wie z.B. das Schalten eines Shellys auslösen.
Anbei nochmals das JavaScript.
Evtl. kannst Du das ja (natürlich mir Deinen eigenen Datenpunkten) anstelle des von Dir verwendetem NodeRed gebrauchen? Das ist m.E einfacher/übersichtlicher als NodeRed.//########################################################################## // Rhasspy-intents via MQTT empfangen und entspr.Datenpunkte setzen/schalten //########################################################################## const empfangen = 'mqtt.0.rhasspy.intent.ChangeLightState' // Lampen, bzw. Funksteckdosen const szenen = 'mqtt.0.rhasspy.intent.Scenes' // Broadlink-Szenen const rolladen = 'mqtt.0.rhasspy.intent.Rolladen' // Rolladen //______________________________________________ // Lampen, bzw. Funksteckdosen on({id: empfangen, change: "any"},function(obj) { let empf_code = getState(empfangen).val ; //log ("EMPF-CODE: " + empf_code); let empf_json = JSON.parse(empf_code); //log ("EMPF_JSON: " + empf_json); let name = empf_json.name; let state = empf_json.state; //log ("name: " + name + " state: " + state); if (name == "wandspots" && state == "ein") { setState ('hm-rpc.2.CUX4000001.7.PRESS_LONG', true); log ("wandspots ein"); } else if(name == "wandspots" && state == "aus") { setState ('hm-rpc.2.CUX4000001.7.PRESS_SHORT', true); log ("wandspots aus"); } else if(name == "regal" && state == "ein") { setState ('hm-rpc.2.CUX4000001.1.PRESS_LONG', true); log ("regal ein"); } else if(name == "regal" && state == "aus") { setState ('hm-rpc.2.CUX4000001.1.PRESS_SHORT', true); log ("regal aus"); } else if(name == "couchjoerg" && state == "ein") { setState ('hm-rpc.2.CUX4000001.10.PRESS_LONG', true); log ("couchjoerg ein"); } else if(name == "couchjoerg" && state == "aus") { setState ('hm-rpc.2.CUX4000001.10.PRESS_SHORT', true); log ("couchjoerg aus"); } else if(name == "couchrenate" && state == "ein") { setState ('hm-rpc.2.CUX4000001.3.PRESS_LONG', true); log ("couchrenate ein"); } else if(name == "couchrenate" && state == "aus") { setState ('hm-rpc.2.CUX4000001.3.PRESS_SHORT', true); log ("couchrenate aus"); } else if(name == "hydro" && state == "ein") { setState ('hm-rpc.2.CUX4000001.8.PRESS_LONG', true); log ("hydro ein"); } else if(name == "hydro" && state == "aus") { setState ('hm-rpc.2.CUX4000001.8.PRESS_SHORT', true); log ("hydro aus"); } else if(name == "ledcube" && state == "ein") { setState ('hm-rpc.2.CUX4000001.5.PRESS_LONG', true); log ("ledcube ein"); } else if(name == "ledcube" && state == "aus") { setState ('hm-rpc.2.CUX4000001.5.PRESS_SHORT', true); log ("ledcube aus"); } else if(name == "fernsehbeleuchtung" && state == "ein") { setState ('hm-rega.0.10074', true); log ("fernsehlicht ein"); } else if(name == "fernsehbeleuchtung" && state == "aus") { setState ('hm-rega.0.10074', false); log ("fernsehlicht aus"); } else if(name == "esstischlampe" && state == "ein") { setState ('shelly.0.SHSW-1#2C7AEF#1.Relay0.Switch', true); log ("esstischlampe ein"); } else if(name == "esstischlampe" && state == "aus") { setState ('shelly.0.SHSW-1#2C7AEF#1.Relay0.Switch', false); log ("esstischlampe aus"); } else if(name == "essecke" && state == "ein") { setState ('hm-rpc.2.CUX4000001.2.PRESS_LONG', true); log ("essecke ein"); } else if(name == "essecke" && state == "aus") { setState ('hm-rpc.2.CUX4000001.2.PRESS_SHORT', true); log ("essecke aus"); } }); //______________________________________________ // Broadlink-Szenen on({id: szenen, change: "any"},function(obj) { let empf_code = getState(szenen).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.name; let state = empf_json.state; //log ("name: " + name + " state: " + state); if (name == "schlafen" && state == "ein") { setState ('broadlink2.0.Scenes.Schlafen', true); log ("scene schlafen"); } else if(name == "fernsehen" && state == "ein") { setState ('broadlink2.0.Scenes.Fernsehabend', true); log ("scene fernsehabend"); } }); //______________________________________________ // Rolladen on({id: rolladen, change: "any"},function(obj) { let empf_code = getState(rolladen).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.name; let state = empf_json.state; //log ("name: " + name + " state: " + state); if (name == "rolladen" && state == "hoch") { setState ('hm-rpc.0.PEQ0505813.1.STATE', true); log ("rolladen hoch"); } else if(name == "rolladen" && state == "runter"){ setState ('hm-rpc.0.PEQ0505813.3.STATE', true); log ("rolladen runter"); } else if(name == "rolladen" && state == "stop") { setState ('hm-rpc.0.PEQ0505813.2.STATE', true); log ("rolladen stop"); } }); //______________________________________________
Soweit, so gut, allerdings gibt es bei mir noch einen Wermutstropfen bzgl. Rhasspy:
Beim Testen im Bastelzimmer hat die Spracherkennung gut funktioniert.
Dann habe ich den Rhasspy-Raspi ( ) im Wohnzimmer platziert und den TV eingeschaltet.
Da war es größtenteils unmöglich, einen Sprachbefehl abzusetzen, weil die fortwährende Geräuschkulisse vom TV das ver-, bzw. behindert.
Mit anderen Worten: das im Rhasspy-Frontend unter Settings -> Voice Detection -> "Use webrtcvad and listen for silence" hat dann wohl Probleme mit "listen for silence", also auf Ruhe warten.Natürlich habe ich auch wieder Fragen an Dich :
1.) Hast Du Deinen Rhasspy schon mal in einer Umgebung mit Geräuschkulisse getestet?
Kann Dein Matrix Voice dort die Sprachbefehle besser erkennen, oder gibt es ähnliche Probleme wie bei mir?2.) Reagieren die RGB-LEDs auf dem Matrix Voice, wenn Du das Wake Word, oder einen Sprachbefehl absetzt?
Wenn ja, wie sieht das aus (alle an in einer Farbe, Bewegung, unterschiedliche Farben)?
Das ist zwar nur ein Gimmick, aber eine optische Rückmeldung wäre schon nicht schlecht.Ich habe momentan nur einen Kopfhörer am 3,5 mm Audio.Ausgang angeschlossen, was natürlich keine Dauerlösung ist.
Wenn ich aber z.B. eine USB-Soundkarte anschließen würde, um die Beeps zu hören, würde das den WAF vollends in den Keller ziehen, weil ich sowieso schon Probleme mit meiner besseren Hälfte habe, weil von ioBroker bestimmte Events via PAW akustisch ausgegeben werden ( z.B. ... das Badezimmer ist besetzt, Traritrara die Post ist da).
Ich "darf" so ziemlich alles basteln, Hauptsache ist aber, daß es anschließend keinen "Krach" machtGruß
Jörg -
Hi zusammen,
so, heute hab ich mal Zeit auch was hierzu zu schreiben. Ich hatte mich auch vor kurzem mit dem Thema beschäftigt und bin dann ebenfalls (dank Snips-Abschaltung seitens Sonos) auf Rhasspy gestoßen und fand deinen Beitrag sehr hilfreich als ersten Anlauf, @tobetobe. Danke dafür!
Ich hab in der vergangenen Woche auch immer mal wieder damit gespielt und die Installation und die Einrichtung verlief eigentlich relativ einfach.
Meine Erfahrung mit dem Snowboy Wake-Word ist im Moment eigentlich relativ gut, dafür, dass ich aktuell nur ein sehr schlechtes Mikro habe. Ich habe drei Wake-Words eingerichtet ("Yukiko", "Hey Yukiko" und "Ähm, Yukiko"), wobei die beiden mit jeweils zwei Wörter eine deutlich höhere Erkennungsrate haben, als das Einzelne. Ab morgen habe ich wieder ein besseres Mikro zur Verfügung, dann werd ich das nochmal ausführlich testen.
Die Anbindung an ioBroker hab ich ebenfalls über mqtt gemacht und glaube einen ganz guten Ansatz für die Steuerung gefunden zu haben.
Hier ein Ausschnitt meiner Rhasspy Einstellungen:
{ "device_change_command_synonyms": [ "schalte", "schalt" ], "device_name": [ "((licht [im] spielzimmer) | spielzimmer licht):zigbee.0.d0cf5efffe2342c" ], "device_state": [ "ein:true", "an:true", "aus:false" ] }
[ChangeDeviceState] $device_change_command_synonyms [(die | das)] $device_name{device} $device_state{value} (:){state:.state}
Und mein Intent-Handler wie folgt:
var intentResult = $('mqtt.0.rhasspy.intent.*'); var intentArray = []; for(var i = 0; i < intentResult.length; i++) { log(intentResult[i]); intentArray.push(intentResult[i]); } on({id: intentArray, change: "any"}, function (obj) { log(obj.newState.val); let intentObject = JSON.parse(obj.newState.val); if(intentObject.hasOwnProperty('device')) { var deviceID = intentObject.device; var state = intentObject.state; var value = intentObject.value; log(deviceID + state + value); setState(deviceID + state, JSON.parse(value)); } });
Um meinen Intent-Handler möglichst Variable zu machen, frage ich alle Intents die per mqtt ankommen in der selben Funktion ab. Die Idee dahinter ist, dass ich möglichst viele Fälle mit wenig Code abdecken möchte.
Im ersten Anlauf habe ich mich einfach mal an einer An-Aus-Schaltung versucht - mit Erfolg. Dadurch, dass Rhasspy die Werte hinter den Begriffen kennt, lässt sich im Intent-Handler recht einfach der gewünschte Befehl zusammensetzen. In meinem Sentense von ChangeDeviceState geben ich dann einfach das Device, den gewünschten State und den Value mit in das JSON-Objekt. Würde man jetzt statt {state:.state} einfach {state:.brightness} und statt {value:true/false} einfach {value:50} mitgeben, würde er mit dem selben Code einen anderen State verändern. So sollte sich das im Fall von Lichtern auch einfach auf Farben usw übertragen lassen.
Eine weitere Idee das ganze möglichst flexibel zu machen ist mit Räumen und Funktionen zu arbeiten. In meinem Testcode haben die ersten Ansätze schon funktioniert. Durch die Prüfung, ob ein intentObject eine bestimmte Eigenschaft besitzt, kann man das ganze recht leicht handlen. Letztlich muss man dann für sich nur entscheiden, wie man damit umgehen mag, wenn es mehr als ein Gerät einer Funktion im selben Raum gibt.
edit:
Hab mich eben nochmal drangesetzt und ein wenig programmiert, um das mit dem Enums hinzubekommen.
if(intentObject.hasOwnProperty('enum_rooms') && intentObject.hasOwnProperty('enum_functions')) { var enumRoom = intentObject.enum_rooms; var enumFunction = intentObject.enum_functions; var state = intentObject.state; var value = intentObject.value; var tmpSelector = 'channel[state.id=*' + state + '](rooms=' + enumRoom.replace("enum.rooms.", "") + ')(functions=' + enumFunction.replace("enum.functions.", "") + ')'; var tmpObj = $(tmpSelector); if(tmpObj.length == 1) { setState(tmpObj[0], JSON.parse(value)); } }
Als abschließende Idee kam mir dann noch in den Sinn, dass es doch auch recht sinnvoll wäre, wenn der ioBroker die Geräte, Räume und Funktionen selbst mit dem Rhasspy bekannt machen würde. Mein Ansatz dafür wäre, dass der ioBroker per Automation eine vorgefertigte Liste an ein mqtt-Topic schickt, dass die Raspberrys mit Rhasspy abonniert haben. Wird eine Nachricht empfangen (zum Beispiel jede Nacht um 3 Uhr oder so), wandelt ein Skript die empfangene Liste um und schreibt sie in das entsprechende File im Slots-Order im Profil von Rhasspy. Dann muss nur das Training nochmal laufen und man spart sich viel Arbeit damit, die Gerätenamen usw bekannt zu machen.
So, nach viel Gerede freue ich mich jetzt auf euer Feedback!
-
Hallo zusammen,
ich antworte mal auf beide Posts.1. Wake Word: Danke für eure Tips hierzu. Ich habe mir ebenfalls zwei eigene Wake Words für Snowboy generiert (Hey Oskar und Hallo Butler). Mit Hey Oskar habe ich auch gleich schlechte Erfahrung gemacht: Als meine Frau nach Hause kam, in der Küche den Fernseher einschaltete und sich dann auch noch mit mir unterhielt (Distanz ca. 7m), begann ein Rollo ständig auf- und abzufahren. Rhasspy hat also irgendwie ein Wake Word sowie ein intent erkannt, obwohl kein Wake Word gesprochen wurde. (WAF war natürlich gleich auf Gefrierschranktemperatur) Ich folge dem Tip von @Tictactoo und generiere ein neues, längeres Wake Word.
Diesmal werde ich jedoch anders vorgehen. Hier folge ich einem weiteren Tipp, auf den ich bei meinen Recherchen gestoßen bin. Es wird empfohlen, nicht ein externes Mic (bei mir CamMic) zu verwenden, sondern genau das Mikrophon, mit dem Rhasspy verbunden ist (bei mir ein MatrixVoice Array). Das Wakeword muss man dann auf dem Rhasspy mit "arecord" aufzeichnen und die erzeugte wav-Datei bei snowboy.kitt.ai hochladen. In dem Fall braucht man das Wake Word nicht durch Spracheingabe anzulernen.
2. Intent Handling: Eure Ansätze mit JS finde ich klasse. Ich habe bereits eine Vielzahl von Abläufen mit Blockly und Node-Red implementiert. Dabei habe auch ich erkannt, dass sauber geschriebenes JS einfach schlanker und effizienter ist. Dennoch: Über mehr als das Anpassen vorhandenen Codes bin ich bei JS noch nicht hinausgekommen. Das werde ich wohl auch nicht mehr richtig lernen...
Dennoch: Deine Ansätze @Tictactoo finde ich sehr elegant, insbesondere, weil dadurch auch die gesamte Rhasspy-Konfiguration minimal bleibt. Die ist bei mir deutlich aufgeblasener. Die Idee, mit demselben Code auch Werte für Dimmer oder Rollos zu übergeben, finde ich dabei besonders interessant. Mit der Frage, wie dann die Rhasspy-Konfig und das JS-Script anzupassen sind, muss ich mich allerdings noch auseinandersetzen. Kann auch sein, dass ich daran scheiter...
Steuerung von Rollos: Ich steuer diese nicht mit Auf/Ab/Stop, sondern mit %-Werten, die in einem Skript in Start und Stop umgesetzt werden. Das ganze Zeit- und Temperaturgesteuert (Beschattung im Sommer). Konfiguration über Vis. Wenn ihr Interesse habt, kann ich euch den Code und Vis-Export zur Verfügung stellen.
Die Übernahme von Devices und Räumen aus ioBroker wäre natürlich genial!
Zu den Szenen: Ich verwende für meine Mediengeräte (TV etc.) eine Harmony Fernbedienung mit Harmony Hub. Dort heißen Szenen Aktivitäten. Wisst ihr, wie man diese Aktivitäten aus ioBroker starten kann? Dann könnte ich nämlich als Szenen "Fernsehen", "Radio hören", "DVD abspielen" etc einrichten.
3. Umgebungsbedingungen und Empfindlichkeit: Zum Einfluss von Geräuschen auf das Wake Word hatte ich ja schon oben etwas gesagt. Meine bisherigen Erfahrungen mit geräuschbelegter Umgebung sind die: Das längere Wake Word "Snowboy" wurde eigentlich auch bei Geräuschen und über Distanzen von bis zu fünf Metern immer ganz gut erkannt. Die Erkennung von Intents hingegen ist auf max. ca. zwei Meter begrenzt, was ich ein wenig enttäuschend finde. Drei Meter sollten es schon sein.
Zwei wichtige Aspekte habe ich dazu bereits herausfinden können: Zum einen hängt die Empfindlichkeit sehr von den korrekten Einstellungen des Mikrophons ab. Zu hohe Eingangspegel führen zu Verzerrungen, wodurch die Verständlichkeit auf der Strecke bleibt. Hier hilft nur testen. Hilfsmittel sind die Tools alsamixer, arecord und aplay, die über CLI aufgerufen werden können. Ich werde über alsamixer den Mic-Pegel verändern und mit arecord die Kommandos bei verschiedenen Distanzen aufzeichnen. So finde ich hoffentlich die optimalen Einstellungen und erkenne die Grenzen des Systems. Eine weitere Option wäre die Echo Cancellation unter pulseaudio, einem weiteren Audio-Tool, zu verwenden. Hierzu muss ich mich jedoch noch selbst einlesen.
Zu den Mikrophon-Einstellungen bzw zu den verschiedenen Audio-Tools unter Linux habe ich mir in einem Word-Dokument alle Informationen zusammengefasst. Bei Interesse bitte melden...
Den zweiten wichtigen Aspekt will ich nicht vergessen: Ich habe festgestellt, dass die Verständlichkeit mit zunehmender Komplexität der Rhasspy-Konfiguration sinkt. Wie schon erwähnt, sind meine Listen für Word, Intents und Slots deutlich voller. Es kann auch durchaus sein, dass ich da zu viel des Guten getan habe und ich zwischen den Listen einen "Knoten" eingebaut habe. Das spricht also wieder für @Tictactoos Ansatz.
4. RGB-LEDs von MatrixVoice: @joergeli Das wird dich freuen: Selbstverständlich kann man die LEDs steuern. Man braucht dazu auf dem Rhasspy zwei Tools (Matrix HAL und Matrix Lite JS) und JS. Wie es genau geht, findet man hier:
https://www.hackster.io/matrix-labs/adding-intents-for-rhasspy-offline-voice-assistant-faa221
Du musst dich allerdings anmelden, um den vollen Beitrag lesen zu können.
5. Sonstige Intents: Ich würde gerne noch die Temperatur im Raum oder draußen, die Wetterdaten für heute, morgen, übermorgen abfragen und Timer setzen (Setze den Eierkocher auf 7 Minuten) können. Die Rückantwort müsste dann von ioBroker über MQTT wieder an den Rhasspy übergeben und dort akustisch ausgegeben werden. Habt ihr euch schon damit befasst und ggf herausgefunden, wie man das implementieren könnte?
So, das war's für den Moment.
Bis bald und viele Grüße
Thomas -
@tobetobe Ich geh auch mal der Reihe nach durch:
1. Wake Word: Ich hab tatsächlich auch das selbe Mikrofon verwendet, dass ich an den Rhasspy angeschlossen hab. Vielleicht wäre es sinnvoll für ein besseres Ergebnis die verschiedenen Samples aus unterschiedlicher Entfernung aufzunehmen? Ich meine relativ close am Mikro aufgenommen bei meinem Test.
2. Intent-Handling: Ich denke man kann da noch deutlich mehr machen. Im Idealfall würde ich gern deutlich über das Steuern von Geräten usw rausgehen und zumindest kleine Dialoge einprogrammieren.
Ich hab das mit dem Dimmen gestern mal noch probiert und das ging ziemlich problemlos. Auch das Übergeben von Zahlen als Wert hat gut geklappt.
(dimme | dimm) [(die | das)] $device_name{device} auf (0..100){value} prozent (:){state:.brightness}
3. Umgebungsbedingungen und Empfindlichkeit: Hier kann ich leider nicht viel dazu sagen, da ich über einen Schreibtischtest nicht rausgekommen bin bisher.
Zum Thema Texterkennung kann ich dann aber doch was beitragen: Ich habe mich auch an deutlich komplexeren Intents versucht, in denen alles Optional ist, außer $device_name und $device_state. Das sah dann etwa so aus:[$device_change_command_synonyms] [(die | das)] $device_name{device} $device_state{value} (:){state:.state}
Ich hab das Ganze dann auch noch für die Enums und einen eigenen Intent für die Steuerung meiner Heizung ausprobiert. Plötzlich fing er an seltsame Wortkombinationen zu erkennen wie "heizung im bad bad bad grad" oder so. Ich bin noch net ganz dahinter gestiegen, woran es liegt, aber vielleicht findet sich dafür ja noch ne Lösung. Muss man wohl etwas mit rumspielen.
5. Sonstige Intents: Das Zurückgeben von Antworten habe ich bisher nicht versucht, fände ich allerdings auch mehr als interessant. Allerdings dachte ich mir, ich konzentriere mich erstmal auf die Steuerung, da ich im Zweifelsfall keinen Schmerz damit hätte meine Echos ne Weile für die Sprachausgabe zu benutzen.^^
-
Hallo Tictactoo,
meine Sentences.ini sieht so aus:
und meine Slots so:
Nun will ich dies in deine Struktur überführen. Wie müsste ich deine Slot-Liste ergänzen? Muss ich alle Devices mit ihren individuellen Namen (zB Küchenlampe links) auflisten?Was muss ich machen, wenn ich beide Küchenlampen (unterm Schrank) oder alle Küchenlampen (inkl. Lampe über dem Fenster) mit einem Kommando steuern will? Wäre es sinnvoll, dies als eine Szene abzubilden, oder wie würdest du das lösen?
Und wie kann ich meine dimmbaren Lampen bzw. mit den gleichen Prozentwerten meine Rollos mit aufnehmen? An der Stelle hänge ich gerade total.
Deine Programmierung für die Enums: ist die bereits tauglich? Und falls ja: Kommt der Code mit in das Skript für die Steuerung?
Es wäre nett, wenn du mir hierbei weiterhelfen könntest. Vielen Dank.
-
@tobetobe Also bei meinen ersten kleinen Tests hat's funktioniert. Aber das es sich auf jeden Fall anwenden lässt, kann ich dir net versprechen. Hier ist mal das komplette Skript.
Als erstes würde ich mir überlegen, was du unbedingt in der sentense.ini brauchst und was besser in die Slots sollte. Dann solltest du das passend über führen und mit den jeweiligen IDs bestücken. Da ich leider noch kein Skript hab, dass die Devices und Enums umwandelt, müsste man das alles in Kleinstarbeit von Hand machen. Hier im folgenden ist mal ein Beispiel, wie ich es zum Testen gemacht hab:
Das ist noch alles andere als ideal, aber dann haste mal ne grobe Vorstellung davon, wie es aussehen sollte. Bei den Devices ist wichtig, immer Rufname des Geräts und dann mit : die ID aus ioBroker dahinter.
Dann wäre am sinnvollsten deine sentense.ini komplett an die Slots anzupassen, damit die Struktur mit meinem Beispielen übereinstimmt und immer die entsprechenden Sachen in der JSON mitgegeben werden.
Aktuell sieht mein Skript noch nicht vor, dass mehr als ein Gerät gesteuert wird, wobei ich im Idealfall gern hätte, dass es geht, weil es mir bei Alexa ziemlich annervt. Solange ich da noch nichts anderes geschrieben habe, würde ich es über ein virtuelles Gerät, ne Gruppe oder ne Szene lösen. Die dann einfach als eigenes Gerät in die Slots hinzufügen, wie die anderen Geräte.
Um deine Rollos mit meinem Intent-Handler zu steuern müsstest du deinen Sentense wie folgt umstellen. Das gleiche lässt sich dann auch auf das Dimmen der Lichter übertragen. Ich hab hier jetzt mal die rules dringelassen, würde generell aber auch hier die Namen in die Slots überführen, damit die sentense.ini schlank und übersichtlich bleibt.
Hoffe, dass dir das soweit mal geholfen hat.
-
@Tictactoo
Hi,
bzgl. Javascript und sentences führen wohl viele Wege nach Rom.
Dein Ansatz ist definitiv besser als meiner, aber ich bin auch nicht der JS-Crack und hab's "quick & dirty" gemacht.Bevor ich mich aber damit weiter beschäftige, muß ich erst mal Rhasspy "vernünftig" zum Laufen bekommen.
Es gibt bei mir Probleme mit der Geräuschkulisse (Fernseher, Radio).
Wenn davon ein Gerät eingeschaltet ist, kann zwar (meistens) WakeWord und Befehl erkannt werden, der Befehl wird aber erst abgesetzt, wenn einen kurzen Moment Ruhe ist.Ich habe das hier im Bastelzimmer mit einem Radio getestet:
1.) Radio aus: alles Paletti, WakeWord und Befehl werden erkannt und abgesetzt.
2.) Radio an: WakeWord wird meist erkannt, Befehl (glaube ich zumindest) ebenfalls.
Der Befehl wird aber erst abgesetzt, wenn ich das Radio leiser drehe.
(Das erkenne ich daran, wann sich der entspr. Objekt-Status in ioBroker ändert.)
Rhasspy braucht wohl einen kurzen Moment Stille, um fortzufahren.Somit ist Rhasspy für mich wohl unbrauchbar, weil ich den Raspi im Wohnzimmer betreiben will, um damit Szenen, wie z.B. "Fernseh gucken", oder "Schlafen gehen" schalten will (div. Lampen, TV, Sat-Receiver schalten)
"Fernseh gucken" geht, aber "Schlafen gehen nicht", weil im Hintergrund der Fernseher läuft.
Srelle ich den Fernseher manuell via FB auf "mute", wird auch die Szene "Schlafen gehen" weiter abgearbeitet.
Aber das ist ja nicht Sinn der Sache, vorher händisch einzugreifen.Du hast Alexa erwähnt, wie verhält es sich denn damit?
Funktioniert die einwandfrei, wenn im Hintergrund Fernseher, oder Radio läuft?
(Wobei Alexa, Siri, etc. für mich nicht in Frage kommen, wegen Online-Erkennung)Gruß
Jörg -
Hallo Thomas,
Wake Word::
Damit habe ich eigentlich keine Probleme, seit ich Snowboy installiert habe und das WakeWord online (von einem Windows-PC mit anderem Mikrofon) generiert habe.
Sowohl das originale WakeWord "Snowboy", als auch mein eigenes "Hiwi" werden gut erkannt.@tobetobe sagte in Rhasspy Offline Sprachsteuerung:
Zu den Szenen: Ich verwende für meine Mediengeräte (TV etc.) eine Harmony Fernbedienung mit Harmony Hub. Dort heißen Szenen Aktivitäten. Wisst ihr, wie man diese Aktivitäten aus ioBroker starten kann? Dann könnte ich nämlich als Szenen "Fernsehen", "Radio hören", "DVD abspielen" etc einrichten.
Zu Harmony-Szenen kann ich leider nichts beitragen, da ich selbst einen Broadlink RM+ (der kann RF und IR senden) mit entspr. Broadlink-Adapter in ioBroker verwende. Da werden die Szenen direkt im Broadlink-Adapter eingetragen.
Es gibt ja auch einen eigenen Szenen-Adapter für ioBroker, evtl. hilft der Dir weiter?RGB-LEDs von MatrixVoice:
Ich weiß noch nicht, ob mir das hilft, da ich ja ein ReSpeaker 4-Mic Array habe.
Das Matrix Voice gibt's wohl auch nicht mehr zu kaufen ( bei den üblichen verdächtigen e..y und a.....n) ?Zumindest habe ich es schon geschafft, mit den Demo-Scripten (python) von Seed die LEDs zum Leben zu erwecken.
Mit dem DOA-Script leuchtet z.B. der LED-Ring grün auf und im Ring zeigt eine einzelne blaue LED an, aus welcher Richtung der Schall empfangen wurde.
Ich habe aber keinen Plan, wie ich den LED-Ring auf das WakWord reagieren lassen kann
Evtl. mit Python-Script, wenn ich wüsste, wo ich in Rhasspy eine Variable, Event, Prozess, o.ä abgreifen könnte, wenn das WakeWord erkannt wurde
Ist aber auch erst mal nicht so wichtig, da - wie schon geschrieben - das für mich größte Problem die Umgebungsgeräusche vom TV sind (siehe auch meine Antwort an @Tictactoo )Zur Mikrofen-Empfindlichkeit:
Das reicht bei mir aus, schätzungsweise ~4m
In meinem Fall (Umgebungsgeräusche) wäre es aber IMHO kontraproduktiv, die Empfindlichkeit höher zu drehen, weil ja dann wohl auch die Umgebungsgeräusche "lauter" empfangen werden,?
Das Matrix Voice hat - soweit ich es im Internet gelesen habe - eine extra "Noise Reduction", was auch immer darunter zu verstehen ist.Gruß
Jörg -
Hallo zusammen,
@Tictactoo: Vielen Dank für deine Unterstützung. Heute habe ich keine Zeit mehr. Ich werde mich morgen damit befassen, deine Hinweise abzubilden und zu testen. Das finde ich übrigens ein sehr starkes Feature von Rhasspy: Einfach die Konfigdateien kopieren, in einer text-Datei sichern, andere Konfig reinkopieren und das ganze ggf wieder rückgängig machen.@joergeli: Um deine LEDs am Respeaker steuern zu können, habe ich folgende schöne Anleitung gefunden: http://wiki.seeedstudio.com/ReSpeaker_4_Mic_Array_for_Raspberry_Pi/
Mangels eigener Hardware kann ich dir dabei leider nicht weiterhelfen. Ich finde die Anleitung aber sehr verständlich und glaube, dass du das hinbekommst.
Dann nochmals zur Mikrophonthematik insgesamt:
Ein gutes Mikrofon besteht immer aus einem Array (also mehreren MICs) und erfordert eine lokale und leistungsfähige Verarbeitungsinstanz, die die verschiedenen Betriebsmodi (Beamforming, AGC, etc) unterstützt. Besonders wichtig ist dabei auch der Parameter Signal/Noise. Je niedriger dieser bei fehlerfreie Erkennung ist, umso besser werden Signale auch bei Störgeräuschen verstanden. Ansonsten liegt es natürlich in der Natur der Dinge, dass die Erkennung bei zunehmendem Störgeräusch und bei zunehmender Distanz abnimmt.
Bei meinem MatrixVoice ist das leider nicht der Fall. Zwar gibt es einen entsprechenden Prozessor, es fehlt aber an der Software-Unterstützung. Dadurch wird nicht durch Auswertung der Signale aus den sieben MIC-Eingängen ein optimiertes Signal generiert. Vielmehr werden die sieben Signale, die ja alle mit unterschiedlichem Pegel, verschiedenenen Phasenlagen und mit Laufzeitunterschieden eintreffen zu einem Summensignal aufaddiert. Das gibt natürlich einen ziemlichen Brei. In der Matrix Community habe ich hierzu einen vernichtenden Beitrag von jemandem gefunden, der selbst Mikrofone für professionelle Anwendungen entwickelt. Keine Antwort von Matrix!
Das ReSpeker Array schneidet da mit nur vier MICs deutlich besser ab.
Hier habe ich einen interessanten Test von der Snips-Community gefunden:
https://medium.com/snips-ai/benchmarking-microphone-arrays-respeaker-conexant-microsemi-acuedge-matrix-creator-minidsp-950de8876fdaDas beste Mikrofon Array überhaupt ist das für Alexa, was nicht verwundert. Leider ist dieses für Amazon exklusive entwickelt worden und für Endverbraucher nicht verfügbar.
Mein Fazit momentan: Rhasspy selbst macht auf mich einen immer besseren Eindruck. Die Mikrofon-Thematik blende ich für mich momentan mal aus und verfolge lieber eine saubere Konfiguration bzw Funktionalität. Danach schaue ich nach einem alternativen Mikrofon, um die akustischen Verhältnisse zu optimieren.
Euch noch ein schönes Wochenende
Thomas -
Hallo Jörg, zum Umgang von Rhasspy mit Hintergrundgeräuschen würde ich dir raten, diese Frage direkt an das Entwicklerteam bzw an die Community zu stellen. Die müssten sich doch eigentlich schon aus eigenem Interesse heraus mit dieser Thematik befassen. Vielleicht gibt es hierzu ja schon Lösungsvorschläge, wie das Verhalten optimiert werden kann. Hier nochmals der Link zur Community: https://community.rhasspy.org/
Viele Grüße
Thomas -
Hallo zusammen,
soeben habe ich hier https://community.rhasspy.org/ gesehen, dass es eine neue Version 2.4.17 gibt. Neu ist, dass der jeweils letzte Sprachbefehl gespeichert wird und abgespielt werden kann, um Optimierungen vornehmen zu können.
Habt ihr die Beschreibung, wie ein Update korrekt ausgeführt wird?
Falls nicht, kann ich diese ja gleich noch einmal hier posten.
-
Hallo,
ich habe gerade bei mir das Update auf 2.4.17 vorgenommen. So geht es:
docker ps (zeigt CONTAINER ID an, diese kopieren)
docker stop CONTAINER ID
docker rm CONTAINER ID
docker pull synesthesiam/rhasspy-server:latestdocker run -d -p 12101:12101
–restart unless-stopped
-v “$HOME/.config/rhasspy/profiles:/profiles”
–device /dev/snd:/dev/snd
synesthesiam/rhasspy-server:latest
–user-profiles /profiles
docker run -d -p 12101:12101 --restart unless-stopped -v "$HOME/.config/rhasspy/profiles:/profiles" --device /dev/snd:/dev/snd synesthesiam/rhasspy-server:latest --user-profiles /profiles --profile deBrowser aktualisieren, ggf. Cache löschen mit F5 oder Strg F5, falls die neue Version nicht angezeigt wird.
Gutes Gelingen
-
Hallöchen,
ich war heute auch etwas tätig und hab ein Skript geschrieben, um die Device-Liste für die Slots auszulesen:
var devices = $('zigbee.0.*.available'); var devicesMessage = "\"device_name\": ["; for(var i = 0; i < devices.length; i++) { var tempObj = getObject(devices[i].replace('.available','')); devicesMessage += "\"" + tempObj.common.name + ":" + tempObj._id; if(i == devices.length-1) { devicesMessage += "\""; } else { devicesMessage += "\","; } } devicesMessage += "]" sendTo('mqtt.0', 'sendMessage2Client', {topic: '/rhasspy/slots/rooms', message: devicesMessage});
Da ich nur Zigbee-Devices hab, habe ich zum auslesen jetzt einfach mal den "zigbee.0..available" State mit *-Wildcard benutzt. Das müsstet ihr bei euch natürlich entsprechend anpassen. Leider hab ich es mit einem "zigbee.0.*"-Selektor nicht hinbekommen. Blicke bei dem ganzen Selektor-Ding noch net so ganz durch.
-
@tobetobe
Hallo Thomas,
ich habe enen Erfolg mit einem Workaround zu vermelden
Ich hatte gestern meinen Raspi kpl. neu mit Rhasspy (V 2.7.!4) aufgesetzt, weil ich zwischenzeitlich schon so viel probiert/installiert habe, um die Onboard-LEDs zum Laufen zu bringen, daß ich mir gedacht habe, "alles neu macht der Mai"
Mir sind aber in der neuen Version - zumindest vom Web-Frontend - keine Änderungen aufgefallen.Ich wollte aber unbedingt eine optische/akustische Rückmeldung haben, wenn Rhasspy das WakeWord erkannt hat, aber mit Kophörer ist das ja nicht das "Gelbe vom Ei".
Also habe ich in den Objekten der MQTT-Instanz auf dem iobroker gesucht und bin auch fündig geworden:
Es gibt dort zwei Objekte ( mqtt.0.rhasspy.de.transition.SnowboyWakeListener und mqtt.0.rhasspy.de.transition.WebrtcvadCommandListener )
Das erste Objekt wechselt vom State "listening" auf "loaded", wenn das Snowboy-WakeWord erkannt wurde.
Das zweite Objekt wechselt vom State "listening" auf "loaded", wenn das Sprachkommando erkannt wurde.Diese beiden States habe ich mir mit einem JS zu Nutze gemacht, um via PAW-Adapter eine Ansage ("Ja") auf meinem Tablet zu machen, wenn das Wakeword erkannt wurde ( Längere Ansagen, wie z.B. "zu Diensten", funktionieren nicht, da Rhasspy dann schon im Erkennungsmodus ist und das "....iensten" schon zum Sprachbefehl addiert).
Wenn der Sprachbefehl erkannt wurde "sagt" das Tablet "OK".
Also: Ich sage mein WakeWord "Hiwi", Tablet antwortet mit "Ja", dann sage ich den Sprachbefehl", wie z.B. "Wie spät ist es" und das Tablet antwortet mit "OK".
Nach einem kurzem Moment sagt mir mein Tablet dann die aktuelle Uhrzeit, (die ich ebenfalls mit JS generiere).
Anbei das "WakeWord-Script", falls es jemand gebrauchen kann://############################################### // WakeWord-Erkennung const ansage = 'Ja' // Dieser Text wird gesprochent, wenn wakeword erkannt wurde // Hinweis: - Ansagetext text muss mögl. kurz sein, damit er nicht als befehl erkannt wird! const empf_ok = "OK" // Dieser Text wird gesprochen, wenn befehl erkannt wurde const wake = 'mqtt.0.rhasspy.de.transition.SnowboyWakeListener' // Datenpunkt aendert sich von listening auf loaded, wenn wakeword erkannt wurde const befehl = 'mqtt.0.rhasspy.de.transition.WebrtcvadCommandListener' // Datenpunkt aendert sich von listening auf loaded, wenn befehl erkannt erkannt wurde on({id: wake, change: "any"},function(obj) { let empf_code = getState(wake).val ; if (empf_code== "loaded"){ wakeword(); } }); on({id: befehl, change: "any"},function(obj) { let empf_code = getState(befehl).val ; if (empf_code== "loaded"){ befehl_empf(); } }); function wakeword(){ lautstaerke(); // Lautstaerke auf Max setzen sendTo("paw.0",'Tablet_Jörg',{tts: ansage }); // Sprachausgabe "Ja" mittels PAW-Adapter auf Tablet/Smartphone //sendTo("paw.0",'Tablet_Jörg',{play: true}); // optional default sound anstatt sprachausgabe mittels mittels PAW-Adapter auf Tablet/Smartphone abspielen } function befehl_empf(){ lautstaerke(); // Lautstaerke auf Max setzen sendTo("paw.0",'Tablet_Jörg',{tts: empf_ok }); // Sprachausgabe "OK" mittels PAW-Adapter auf Tablet/Smartphone //sendTo("paw.0",'Tablet_Jörg',{play: true}); // optional default sound anstatt sprachausgabe mittels PAW-Adapter auf Tablet/Smartphone abspielen } // Lautstaerke von Tablet/Smartphone auf Maximum setzen function lautstaerke(){ sendTo("paw.0",'all',{volume: 15}); } // Ende WakeWord-ErkennungsScript //###############################################
Mein zweites Problem mit der Geräuschunterdrückung habe ich (vor ca. 1 Std. ) endlich ebenfalls ganz gut in den Griff bekommen:
Ich hatte/habe in den Settings bei Voice Detection die Einstellung Use webrtcvad and listen for silence gewählt, bzw. diese ist per Default vorgegeben.
Dann habe ich in der Rhaspy-Docu im Abschnitt "Command Listener" diesen Hinweis gefunden:WebRTCVAD
Listens for a voice commands using webrtcvad to detect speech and silence.
Add to your profile:"command": { "system": "webrtcvad", "webrtcvad": { "chunk_size": 960, "min_sec": 2, "sample_rate": 16000, "silence_sec": 0.5, "speech_buffers": 5, "throwaway_buffers": 10, "timeout_sec": 30, "vad_mode": 0 } }
Das habe ich über den Advanced-Tab von Rhasspy in mein Profil eingefügt, aber den Parameter "timeout_sec": 30 auf "timeout_sec": 1 geändert.
Was soll ich sagen, momentan dudelt im Hintergrund das Radio und Rhasspy versteht mich jetzt trotzdem ... da kommt Freude auf !!!Vielen Dank auch für Deine Mühe, mir bei den LEDs zu helfen, den Link zu den Seed-Python-Scripten hatte ich auch bereits vorher gefunden, habe es aber trotzdem "nur" halb zum Laufen bekommen.
"Halb" heißt, wenn ich den Docker-Container mit Rasspy gelöscht habe, liefen die Scripte und die LEDs drehten sich bunt im Kreis. Sowie ich den Docker-Container aber neu gestartet habe, liefen sie nicht mehr, weil die Seed 4 Mic-Karte bereits von Rhasspy belegt war.
Egal, mit meiner jetzigen Lösung mit der akustischen WakeWord-Signalisierung per Tablet/Smartphone kann ich leben.Deinen Link zum Mikrofon-Vergleich finde ich sehr interessant.
Bei Hintergrundmusik schneidet das PlayStation Eye-Micro bei der Wakeword-Erkennung am Besten ab, wobei das Respeaker-Mic bei Ruhe und weßem Rauschen die besten Ergebnisse bring, aber bei Hintergrundmusik "in den Keller" geht - wie ich ja selbst erfahren musste.Danke nochmals
Jörg -
Moin moin zusammen,
@joergeli Das mit dem Timeout werd ich mir auf jeden Fall merken und auch mal testen. Wenn das des Rätsels Lösung ist, wäre das ja klasse! Ich denke, dass ich mich diese Woche mal mit der Rückführung von Antworttexten an den Rhasspy beschäftige. Ich halte euch gern auf dem Laufenden!
Ich habe das Skript zum generieren der Slots für meinen Intent-Handler inzwischen erweitert, so dass auch Rooms und Functions generiert werden:
Wenn man das entsprechende Topic mit einem MQTT Programm abonniert, kann man zumindest mal die Slots per CP in Rhasspy einfügen, bis ich ein Skript für das automatische Schreiben geschrieben habe. Bei mir hat es im Test mit den vielen Geräten ziemlich gut funktioniert. Falls ihr die Muse habe es mal zu testen, wäre ich für euer Feedback dankbar. Solltet ihr btw noch Ideen haben, wie man den Intent-Handler sinnvoll erweitern kann, schreibt es mir gern, dann schreibe ich da mal was zusammen.
-
Hallo zusammen,
vielen Dank für eure super Beiträge. Berufsbedingt werde ich in dieser und der nächsten Woche eure Beiträge nur lesen, aber nicht testen können. Daher kurz mein aktueller Stand der Dinge.@Tictactoo: Deine Slots und Sentences habe ich wie vorgeschlagen umgesetzt. Dabei bin ich sogar noch einen Schritt weiter gegangen, und habe die Sentences für Dimmer und Blinds von der Syntax her exakt so aufgebaut, wie du es für die Zustände der Lampen, die man nue ein/aussschalten kann, beschriebene hast. Allerdings mit dem Level (0..100).
Das funktioniert im Prinzip, außer dass der Zustand "0 Prozent" nicht angenommen wird. Hier müstte ich dein Skript dahingehend anpassen, dass ich auch einfach ein/an/aus sagen könnte. Das muss ich mir noch anschauen.
Dein Script für den Import der Devices finde ich extrem interessant. Leider keine Zeit bzw, nur ganz wenig Zeit zum Testen...
@joergeli : Deinen Hinweis zu WebRTCVAD habe ich noch versucht zu implementieren. Leider ist diese Ergänzung im Profil bei mir immer wieder verschwunden. Ich musste auf dem Rhasspy-Raspi runter ins Directory ~/.config/rhasspy/profiles/de $ und die Datei profile.json direkt editieren. Nun habe ich keine Zeit mehr zum Testen...
Dein Wake Word Script finde ich super cool. Auch hier gilt leider: keine Zeit bzw. ganz wenig Zeit zum Testen...
Von daher wünsche ich weiter gutes Gelingen. Ich werde eure Beiträge verfolgen und mich, sofern ich Zeit habe, mal einklinken.
-
Nochmals hallo,
falls ihr eure LEDs vom Mikro ansteuern wollt, gibt es hier die entsprechenden Anweisungen - und zwar passend zu Rhasspy, nichts allgemeines. Liest sich interessant, denn sowohl das ReSpeaker, wie auch mein MatrixVoic Mic werden unterstützt.
https://community.rhasspy.org/t/hermesledcontrol/285
https://github.com/project-alice-assistant/HermesLedControl/wiki/Intro -
@tobetobe und andere Interessierte:
ich habe mich gleich auf den HermesLedControl-Link gestürzt
und die Installation von Hermes LED Control gestartet. Während der Installation wurde nach der gewünschten engine gefragt, die ich mit "rhasspy" angegeben habe - wurde aber bemängelt, es ging aber trotzdem weiter mit der Frage, welche Hardware verwendet wird. Habe ich mit "respeaker4" beantwortet. Danach wurde gefragt, ob die Hardware konfiguriert werden soll -> mit "Ja" beantwortet, weil es "strongly recommended", also empfohlen wurde.
War m.E, nicht unbedingt notwendig, weil ich die Treiber ja vorher schon direkt von Seed installiert hatte.
Aber egal, hat dann ein Weilchen gedauert, bis die Treiber (und sonstiges?) für das ReSpeaker4-Mic installiert waren.Nach Fertigstellung der Installation habe ich - wie beschrieben - den pathToConfig angepasst:
sudo systemctl stop hermesledcontrol sudo nano /etc/systemd/system/hermesledcontrol.service sudo systemctl daemon-reload sudo systemctl start hermesledcontrol
Die hermesledcontrol.service sah dann so aus:
[Unit] Description=Hermes Led Control [Service] WorkingDirectory=/home/pi/hermesLedControl_v2.0.3 ExecStart=/home/pi/hermesLedControl_v2.0.3/venv/bin/python3 main.py --engine=rhasspy --pathToConfig=/home/pi/.config/rhasspy/profiles/de/profile.json --hardware=respeaker4 --pattern=kiboost --mqttServer=192.168.192.29 --mqttPort=1891 Restart=always RestartSec=5 User=pi [Install] WantedBy=multi-user.target
Ich habe dort zusätzlich die IP des ioBroker-Raspi, bzw. des MQTT-Brokers und den Port eingetragen (den Port hatte ich geändert, weil auf dem ioBroker-Raspi noch ein Mosquitto-Broker läuft, der den Standardport 1883 belegt)
Nach daemon-reload und start hermesledcontrol leuchtete dann der LED-Ring mit dem kiboost-Pattern auf.
Habe das dann auch mal den anderen Pattern (google, alexa, etc.) probiert - geht auch.Jetzt kommt aber das "aaaaber":
Ich habe mit./venv/bin/python3 main.py --debug=True
versucht den Debug-Modus zu aktieren, was mit Fehlermeldung quittiert wurde, Screenshot:
Dann habe ich mir noch unter /home/pi/hermesLedControl_v2.0.3 das logs.log angesehen, was m.E. "ganz gut" ausgesehen hat:
2020-01-29 22:16:26,867 [MainThread] - [INFO] - Starting Hermes Led Control v. 2.0.3 2020-01-29 22:16:26,878 [MainThread] - [INFO] - Initializing HermesLedControl 2020-01-29 22:16:26,907 [MainThread] - [INFO] - Initializing Rhasspy settings 2020-01-29 22:16:26,908 [MainThread] - [INFO] - Loading configurations 2020-01-29 22:16:26,910 [MainThread] - [INFO] - Loaded 12 hardware references 2020-01-29 22:16:26,910 [MainThread] - [INFO] - - Mqtt server set to 192.168.192.29 2020-01-29 22:16:26,911 [MainThread] - [INFO] - - Mqtt port set to 1891 2020-01-29 22:16:26,912 [MainThread] - [INFO] - - Client id set to default 2020-01-29 22:16:26,912 [MainThread] - [INFO] - - Hardware set to ReSpeaker 4 2020-01-29 22:16:26,913 [MainThread] - [INFO] - - Using alexa as pattern with 12 leds 2020-01-29 22:16:26,913 [MainThread] - [INFO] - Initializing leds controller 2020-01-29 22:16:27,053 [MainThread] - [INFO] - Hermes Led Control started
Anschließend habe ich mir noch in der iobroker mqtt-Instanz die Objekte/Topics bzgl. Hermes angesehen, die ja von Hermes LED Control genutzt werden sollen. Die wurden auch alle wie beschrieben angelegt, siehe Screenshots;
Jetzt stehe ich aber auf dem Schlauch, wie ich damit die LEDs steuern kann.
Ich habe ein wenig in den Settings von Rhasspy rumgespielt, z.B. unter VoiceDetection
Use MQTT (Hermes protocol)
Rhasspy will listen for hermes/asr/startListening und hermes/asr/stopListening
aktiviert und anschl. in den Datenpunkten/Topics Fantasie-Werte eingetragen, in der Hoffnung, daß dann irgendwelche LEDs leuchten, aber es tut sich nichts (habe anschl. wieder auf Use webrtcvad and listen for silence zurückgestellt, weil ja sonst das Micro tot ist.)
Nachdem ich jetzt damit 1,5 Tage herumgedoktort habe, weiß ich nicht mehr weiter.Falls jemand trotzdem Zeit und Muße hat, das auszuprobieren, könnt ihr ja mal berichten, wie es bei euch gelaufen ist.
Evtl. sehe ich ja den Wald vor lauter Bäumen nicht.Gruß
JörgP.S.
@tobetobe
Das mit dem WebRTCVAD habe ich auch direkt im profile.json editiert.
Muß aber wohl etwas zurückrudern, der Timeout bewirkt m.E nur, daß die Erkennungszeit verkürzt wird, die sonst mit Hintergrundmusik/Geräuschen ziemlich lang war.
Meine Sprachbefehle / Intents werden meistens auch gut erkannt, aber manchmal wird auch ein kpl. anderes Intent geschaltet. Habe auch schon versucht, das mit wiederholtem trainieren der Sentences zu verbessern, es kommen aber doch noch "Fehl-Intents" rein. Bei Totenstille funktioniert das rel. gut, aber bei Hintergrundgeräuschen häufen sich die Fehler.