NEWS

Rhasspy Offline Sprachsteuerung


  • Moin
    Hat schon jemand Erfahrungen mit Rhasspy gemacht? Von den Beschreibungen auf der Homepage her sieht es ja ganz gut aus, Offline Spracherkennung, Node-Red kompatibel, wäre ein Schritt in die richtige Richtung um Alexa und andere cloudbasierte Voice Assistenten loszuwerden.
    Freue mich auf evtl Erfahrungsberichte
    😊
    https://rhasspy.readthedocs.io/en/latest/


  • Hi,
    ich begann mit snips um dann festzustellen, dass snips nach dem Verkauf an Sonos als community Lösung nicht mehr zur Verfügung stehen wird. Als Alternative habe ich mir zunächst Mycroft/picroft angeschaut, dies trotz sehr einfacher und zuverlässiger Installation dann aber wegen der Cloud-Anbindung nicht weiter verfolgt. Eine echte standalone-Lösung ist in der Tat nur Rhasspy. Eine erste Installation auf einem Pi3B auf Basis von Stretch bekam ich weder mit Python noch mit Docker zum Laufen. Die Neu-Installation mit Buster verlief erfolgreich. Als Mikro verwende ich Matrix Voice. Hinweise zur Installation der Treiber unter Matrix aber auch bei Mycroft. Wie ich bereits erkennen konnte, ist der Pi3B mit Rhasspy an seiner Leistungsgrenze angekommen. Die durchaus mögliche Client-Server-Konfiguration habe ich bislang noch nicht in Betracht gezogen, weil ich die Kompelxität zunächst gering halten wollte. Nun zu Rhasspy: Die englischsprachige Dokumentation zur Konfiguration ist im Prinzip nicht schlecht. im Detail tun sich jedoch immer wieder Fragen auf, nämlich wie es denn nun konkret geht... Hier muss man sich durchwühlen. Im ebenfalls englischsprachigen Forum gibt es zahlreiche Hinweise. Anders als bei ioBroker scheint hinter Rhasspy jedoch nur eine Person zu stehen. Das Projekt ist auf HASS.IO bzw Home Automation fokussiert, ioBroker wird nicht erwähnt. Momentan hänge ich noch an der Konfiguration der Befehle, sodass ich mich mit der prinzipiell möglichen Node-Red-Anbindung an ioBroker noch gar nicht befassen konnte. Mein Fazit: Ein seeeehr zähes Projekt, das sich ohne Zuarbeit aus der ioBroker-community ggf. auch im Sande verlaufen könnte, was schade wäre...

    Vielleicht finden sich ja hier einige versierte Unterstützer/Mitstreiter.

    Gruß in die Runde


  • Moin

    Ich hab bisher leider noch keine Zeit gehabt mir das noch genauer anzuschauen, wird auf jeden Fall wieder unendliche Bastelei 🙂 Wenn man es vernünftig in Node-Red bekommt, sollte dem Glück ja eigentlich nichts mehr im Wege stehen.

    HassIo in 'ner virtuellen Maschine wäre notfalls auch denkbar, für HassIo gibts ja glaub ich auch einen Adapter bei ioBroker...


  • @Hhjung16
    Moin,
    mittlerweile bin ich deutlich weiter. Status:

    • Rhasspy (neueste Version 2.4.16) läuft auf Raspberry PI3 mit Buster im Docker mit deutschem Profil und einem Matrix Voice als Mikrofon
    • die gesamte Installation lief problemlos, Konfiguration von Rhasspy zunächst so wie standardmäßig vorgesehen
    • wichtig: Mikro und Ausgabe richtig konfigurieren
    • Übergabe an ioBroker über MQTT. Auf ioBroker muss hierzu ein MQTT-Adapter als Server eingerichtet werden (ohne User). In Rhasspy die Konfiguration für MQTT entsprechend anpassen und die IP des MQTT-Servers eintragen
    • Trainieren von Rhasspy: Hier muss man sich von vorne herein eine saubere Arbeitsweise angewöhnen
    1. Im Reiter "Words" die Worte für die Devices/Slots (zB Esszimmerlampe) anlegen und die Aussprache (Pronounciation) testen und ggf anpassen. Die Ausgabe muss auf "Word" nicht auf "Phonemes" stehen. Wort übernehmen und speichern. Achtung: Zwischen dem neuen Eintrag und der bisherigen Wortliste darf sich keine Leerzeile befinden.
    2. Im Reiter "Slots" für genau diese angelegten Worte die Slots anlegen. Ich habe zB im Slot "lights" hinter der Esszimmelampe den Datenpunkt von ioBroker eingetragen (hm-rpc.0.ABC1234567.1.STATE) eingetragen. Ob dies so richtig und überhaupt relevant ist, weiß ich noch nicht. Auf die weitere Funktion hat es jedoch bislang keinen Einfluss.
      Speichern nicht vergessen!
    3. Im Reiter "Sentences" kann nun die Datei sentences.ini editiert werden. Es gibt dort unter [ChangeLightState] bereits ein Template für Sätze zum Schalten von Lampe. Unter "light_name" müssen vollständig alle Worte/Devices, die angelegt wurden, aufgeführt werden. Fehlt eines, funktioniert für dies fehlende Device die Sprachsteuerung nicht.
      Speichern nicht vergessen!
    4. Nun kann Rhasspy durch Betätigen des grünen Knopfes "Train" trainiert werden. Je nach Umfang der Konfiguration kann das N x 10 sec. dauern. "Train" kann man auch ruhig jeweils nach Schritt 1 bis 3 ausführen, so dass immer nur die Differenz aktualisiert wird.
    5. Testen: Im Reiter "Speech" kann die Konfiguration nun getestet werden. Hierzu den blauen Button "Hold to Record" betätigen, ein konfiguriertes Kommando sprechen (zB schalte die Esszimmerlampe ein) und loslassen. (Der gelbe Wake-Button braucht hierzu zuvor nicht betätigt zu werden Auch braucht das Wake-Word "Okay Rhasspy" nicht gesprochen zu werden). Ist alles korrekt, sieht man anschließend die vollständige Raw Intent JSON. Bei unvollständiger Konfiguration erscheint hier nur Unsinniges.
      Wenn das bis hierher alles klappt, kann man nun mit Mikro und Lautsprecher testen. Hierzu vor Eingabe des Sprachkommandos einfach den gelben Wake-Button betätigen und unmittelbar nach dem hellen Quittungston das vollständige Sprachkommando mit Wake-Word eingeben. Ist alles OK, hört man einen etwas niedrigeren Quittungston, its etwas falsch einen tiefen Quittungston.

    Soweit Rhasspy. Nun zurück zu ioBroker. Sofern der MQTT-Adapter während der Testerei bereits lief, wurde unter den Objekten unter mqtt.0 das Verzeichnis rhasspy, darunter das Verzeichnis intent und dort die intents selbst (zB ChangeLightState) angelegt. Am besten nun in zwei Fenstern arbeiten und in dem einen (Rhasspy) erneut ein Sprachkommando mit Wake-Word eingeben. In dem anderen (ioBroker) die Ausgabe des Objekts "ChangeLightState" beobachten. Dies müsste sich in Abhängigkeit von dem eingegebenen Sprachkommando jeweils ändern.

    Der weiteren Verarbeitung dieses Objektes mit ioBroker steht also nun nichts mehr im Wege. Ich selbst habe mir hierzu den node-red Adapter installiert und einen kleinen Flow zum Testen angelegt. Die Übernahme der daten aus dem Objekt "ChangeLightState" kann man mit dem Eingabe-Node "ioBroker in" vornehmen. Erste per Sprachkommando eingegebene Schaltbefehle habe ich bereits bis zu einer Lampe durchgebracht. Die Lampe kehrt jedoch nach einem Sekundenbruchteil wieder in den Aus-Zustand zurück. Hier weiß ich noch nicht, woran das liegen könnte. Vielleicht hat ja jemand eine Idee? Vielleicht Rechte zwischen Rhasspy und ioBroker?

    Fazit: Einfache und bislang zuverlässige Installation, relativ aufwändige Konfiguration, die aber beherrschbar ist, wenn man sich an das von mir vorgeschlagene Vorgehen hält. Gute Spracherkennung mit dem Matrix Voice Mikro. Für jeden, der wirklich vollständig autonom bleiben will, also eine wirklich gute Lösung - auch als Ersatz für das abgemeldete Snips. Vielleicht kann sich ja jemand aus der Snips-Gruppe dem Thema mal zuwenden und seine Erfahrung mit einfließen lassen.

    Und sonst: Wer Details wissen möchte, kann auf mich zukommen.

    Gruß in die Runde


  • @tobetobe

    Das nenne ich mal ausführlich 👍 👍 👍

    Komme leider momentan nicht dazu, das alles mal auszuprobieren, das frisst ja auch wieder so viel Zeit 😞

    Was hast du denn insgesamt für die Hardware bezahlt? Also, was kostet eine "Sprechstelle"?


  • @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:
    ReSpeaker 4-Mic Array.jpg
    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):

    1. 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.

    2. 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

    3. 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" macht 🙄

    Gruß
    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-950de8876fda

    Das 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


  • @joergeli

    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:latest

    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
    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

    Browser 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.

Suggested Topics

1.7k
Online

36.6k
Users

42.4k
Topics

586.3k
Posts