Werbung
Hinweis: Diese Seite enthält Werbelinks

Raspberry Pi Sprachsteuerung mit Node-RED, voice2json und openHAB 2

In diesem Beitrag erstellen wir eine Raspberry Pi Sprachsteuerung mit Node-RED. Ihr erfahrt welche Hardware und Software benötigt wird. Viel Spaß mit dieser Schritt für Schritt Anleitung.

Solltet ihr mit einer bestehenden Node-RED Installation arbeiten, macht vorher ein Backup. Im Anschluss auf den neusten Stand aktualisieren. Ich gebe dennoch keine Gewähr. Startet sonst erstmal mit einer Neuinstallation wie in diesem Beitrag. Bei mir läuft dies seit Monaten stabil.

Raspberry Pi Sprachsteuerung mit Node-RED – Hardware

Als Hardware für die Steuerung empfehle ich ein Raspberry Pi 4 und ein Respeaker Mic 2.0 Mirkofon.

Raspberry Pi Sprachsteuerung mit Node-RED – Software

Software – Node-RED installieren

Als erstes müsst ihr Node-RED auf dem Raspberry Pi installieren. Folgt hierzu einfach dem Beitrag Node-RED auf Raspberry Pi installieren.

Ich gehe davon aus, dass ihr weiterhin per ssh auf dem Raspberry Pi eingeloggt seid. Falls nicht loggt euch bitte ein.

Plant ihr den Raspberry Pi mittels WLAN einzubinden. Hierfür über den Befehl sudo raspi-config das Menü aufrufen und Network Options, Wireless LAN wählen. Dort durchläuft einfach die einzelnen Schritte. Ist im Grunde selbsterklärend.

Im nächsten Schritt stellt die Sprache ein. Wir benötigen dies für eine deutsche Sprachsteuerung.

  1. Wählt Punkt 4. „Localisation Options Set up language …“
  2. Nun den Unterpunkt I1 „Change Locale Set up language …“
  3. Hier müsst ihr eine ganze weile Pfeil nach unten drücken bis ihr den Eintrag „de_DE.UTF-8 UTF-8“ findet. Dies mit der Leertaste markieren, Tab drücken, Enter und einfach weiter durch navigieren.

Software – Voice2JSON installieren

Als weitere Komponeten benötigen wir Voice2JSON. Ruft die folgende Seite auf.

http://voice2json.org/install.html#debian-package

Hier wählt das entsprechende Paket und macht einen Rechtsklick (1) auf den Link. Im Kontextmenü (2) „Adresse des Links kopieren“ wählen. Und ja, armhf ist richtig, auch wenn arm64 den PI 3+,4 listet.

Nun auf dem Pi wget gefolgt von der kopierten Adresse eingeben. In unserem Fall (Pi4) sieht dies wie folgt aus.

wget https://github.com/synesthesiam/voice2json/releases/download/v2.0/voice2json_2.0_armhf.deb

Nun entpacken wir das Paket mit folgendem Befehl und beantwortet alle Fragen mit „Y“.

sudo apt install ./voice2json_2.0_armhf.deb

Sprache herunterladen unter folgendem Link. Da Kaldi aktuell die beste Kombination aus Erkennung und Performance bietet, laden wir das Paket de_kaldi-zamia-2.0.tar.gz herunter.

http://voice2json.org/#supported-languages
wget https://github.com/synesthesiam/de_kaldi-zamia/archive/v2.0.tar.gz

Entpacken der Sprachdateien.

tar -xzvf v2.0.tar.gz

Software – SoX installieren

Um mit Sound zu arbeiten benötigen wir noch Sox (Sound-Exchange). Dies könnt ihr bei Debian einfach über folgenden Befehl installieren.

sudo apt-get install sox

Software – Node-RED Raspberry Pi Sprachsteuerung Nodes

Nun benötigen wir noch die Nodes der für die Sprachsteuerung. Installiert als erstes GIT

sudo apt-get install git

Zur Installation der Nodes wechselt in das Node-RED Verzeichnis

cd $HOME/.node-red

Im Anschluss installiert ihr die folgenden beiden nodes. Diese Nodes hat übrigens unser Mitglied Johannes von myfreelife e.V. erstellt. Danke Johannes für diese schlanke, hervorragende Lösung!

npm install johanneskropf/node-red-contrib-sox-utils
npm install johanneskropf/node-red-contrib-voice2json

Startet node-RED per node-red-start und als bestes per Service.

sudo systemctl enable nodered.service 

Node-RED Sprachsteuerung Nodes

Verbindet nun das Respeaker USB Mirko per Kabel mit dem USB Port des Raspberry Pi. Alle LEDs sollten direkte anfangen zu leuchten und bereits auf Sprache reagieren.

Hinweis: Die folgenden Sprachsteuerung beruht auf openHAB 2 als Smarthome Server. Falls ihr andere Lösungen wie ioBroker, FHEM, Home Assistant und weiteres nutzt, müsst ihr den Flow entsprechend anpassen.

Bei der Erstellung des Flows hat mich Johannes unterstützt. Damit ihr es einfacher habt, kopiert euch einfach den Flow in den Zwischenspeicher.

[
    {
        "id": "db234a3a.20fea8",
        "type": "subflow",
        "name": "RestItemOutBlank",
        "info": "",
        "category": "Openhab",
        "in": [
            {
                "x": 80,
                "y": 60,
                "wires": [
                    {
                        "id": "ea72e050.af37c"
                    }
                ]
            }
        ],
        "out": [
            {
                "x": 520,
                "y": 60,
                "wires": [
                    {
                        "id": "11d6666a.4dbdaa",
                        "port": 0
                    }
                ]
            }
        ],
        "env": [
            {
                "name": "Url",
                "type": "str",
                "value": "http://localhost:8080",
                "ui": {
                    "label": {
                        "en-US": "Openhab Url"
                    },
                    "type": "input",
                    "opts": {
                        "types": [
                            "str"
                        ]
                    }
                }
            }
        ],
        "color": "#C0DEED",
        "icon": "font-awesome/fa-sign-out",
        "status": {
            "x": 840,
            "y": 120,
            "wires": [
                {
                    "id": "4740b8d8.517638",
                    "port": 0
                },
                {
                    "id": "8fc663ec.2924f",
                    "port": 0
                }
            ]
        }
    },
    {
        "id": "ea72e050.af37c",
        "type": "function",
        "z": "db234a3a.20fea8",
        "name": "RequestVars",
        "func": "const url = env.get(\"Url\");\nmsg.url = url + \"/rest/items/\" + msg.item + \"/\";\nmsg.headers = {};\nmsg.headers['Content-Type'] = 'text/plain';\nmsg.headers['Accept'] = 'application/json';\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "x": 210,
        "y": 60,
        "wires": [
            [
                "11d6666a.4dbdaa"
            ]
        ]
    },
    {
        "id": "11d6666a.4dbdaa",
        "type": "http request",
        "z": "db234a3a.20fea8",
        "name": "",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 390,
        "y": 60,
        "wires": [
            [
                "3d5a938e.bf762c"
            ]
        ]
    },
    {
        "id": "3d5a938e.bf762c",
        "type": "switch",
        "z": "db234a3a.20fea8",
        "name": "",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "200",
                "vt": "num"
            },
            {
                "t": "else"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 550,
        "y": 120,
        "wires": [
            [
                "4740b8d8.517638"
            ],
            [
                "8fc663ec.2924f"
            ]
        ]
    },
    {
        "id": "4740b8d8.517638",
        "type": "trigger",
        "z": "db234a3a.20fea8",
        "name": "",
        "op1": "{\"fill\":\"green\",\"shape\":\"dot\"}",
        "op2": " ",
        "op1type": "json",
        "op2type": "str",
        "duration": "1",
        "extend": true,
        "units": "s",
        "reset": "",
        "bytopic": "all",
        "outputs": 1,
        "x": 700,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "8fc663ec.2924f",
        "type": "trigger",
        "z": "db234a3a.20fea8",
        "name": "",
        "op1": "{\"fill\":\"red\",\"shape\":\"dot\"}",
        "op2": " ",
        "op1type": "json",
        "op2type": "str",
        "duration": "1",
        "extend": true,
        "units": "s",
        "reset": "",
        "bytopic": "all",
        "outputs": 1,
        "x": 700,
        "y": 180,
        "wires": [
            []
        ]
    },
    {
        "id": "9f69ee30.2ec97",
        "type": "tab",
        "label": "LocalVoice",
        "disabled": false,
        "info": ""
    },
    {
        "id": "18ca7c6e.a2e434",
        "type": "sox-record",
        "z": "9f69ee30.2ec97",
        "name": "",
        "buttonStart": "msg",
        "inputs": 1,
        "inputSource": "1,0",
        "byteOrder": "-L",
        "encoding": "signed-integer",
        "channels": 1,
        "rate": 16000,
        "bits": 16,
        "gain": "0",
        "lowpass": 8000,
        "showDuration": false,
        "durationType": "forever",
        "durationLength": 0,
        "silenceDetection": "nothing",
        "silenceDuration": "2.0",
        "silenceThreshold": "2.0",
        "outputFormat": "stream",
        "manualPath": "",
        "debugOutput": false,
        "x": 150,
        "y": 280,
        "wires": [
            [
                "47a1e6ee.4462d8"
            ],
            []
        ]
    },
    {
        "id": "47a1e6ee.4462d8",
        "type": "voice2json-wait-wake",
        "z": "9f69ee30.2ec97",
        "name": "",
        "voice2JsonConfig": "fd76f088.e4c66",
        "inputField": "payload",
        "controlField": "control",
        "outputField": "payload",
        "nonContinousListen": true,
        "x": 380,
        "y": 280,
        "wires": [
            [
                "a718728f.487f4",
                "eea2d822.4011a8"
            ],
            [
                "2f0150b9.dd289"
            ]
        ]
    },
    {
        "id": "a718728f.487f4",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 610,
        "y": 220,
        "wires": []
    },
    {
        "id": "c81bee83.d3e09",
        "type": "voice2json-training",
        "z": "9f69ee30.2ec97",
        "name": "",
        "voice2JsonConfig": "fd76f088.e4c66",
        "inputField": "payload",
        "outputField": "payload",
        "loadedProfile": "",
        "x": 370,
        "y": 500,
        "wires": [
            [
                "83dedab3.c18eb8",
                "85de8340.ac046",
                "3d6e07c7.254a78"
            ]
        ]
    },
    {
        "id": "16f0a80.dbb9d58",
        "type": "inject",
        "z": "9f69ee30.2ec97",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "train",
        "payloadType": "str",
        "x": 160,
        "y": 500,
        "wires": [
            [
                "c81bee83.d3e09",
                "38ded18a.d4105e"
            ]
        ]
    },
    {
        "id": "83dedab3.c18eb8",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 590,
        "y": 500,
        "wires": []
    },
    {
        "id": "85de8340.ac046",
        "type": "file",
        "z": "9f69ee30.2ec97",
        "name": "",
        "filename": "/home/pi/training.txt",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "true",
        "encoding": "none",
        "x": 610,
        "y": 540,
        "wires": [
            []
        ]
    },
    {
        "id": "2f0150b9.dd289",
        "type": "voice2json-transcribe-stream",
        "z": "9f69ee30.2ec97",
        "name": "",
        "voice2JsonConfig": "fd76f088.e4c66",
        "inputField": "payload",
        "outputField": "payload",
        "x": 670,
        "y": 280,
        "wires": [
            [
                "287e72ff.75511e",
                "44a220e4.28b55"
            ]
        ]
    },
    {
        "id": "4047cdae.b3f6f4",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1530,
        "y": 220,
        "wires": []
    },
    {
        "id": "287e72ff.75511e",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "control",
                "pt": "msg",
                "to": "listen",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 670,
        "y": 380,
        "wires": [
            [
                "47a1e6ee.4462d8"
            ]
        ]
    },
    {
        "id": "44a220e4.28b55",
        "type": "voice2json-tti",
        "z": "9f69ee30.2ec97",
        "name": "",
        "voice2JsonConfig": "fd76f088.e4c66",
        "inputField": "payload.text",
        "controlField": "control",
        "outputField": "payload",
        "autoStart": true,
        "x": 940,
        "y": 280,
        "wires": [
            [
                "ff198956.161b68",
                "de126189.fc94f"
            ]
        ]
    },
    {
        "id": "22ea7572.9f805a",
        "type": "inject",
        "z": "9f69ee30.2ec97",
        "name": "",
        "props": [
            {
                "p": "control",
                "v": "start",
                "vt": "str"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 900,
        "y": 380,
        "wires": [
            [
                "44a220e4.28b55"
            ]
        ]
    },
    {
        "id": "bffdb5b4.05a0c8",
        "type": "subflow:db234a3a.20fea8",
        "z": "9f69ee30.2ec97",
        "name": "openHAB",
        "env": [
            {
                "name": "Url",
                "value": "http://oh2:8080",
                "type": "str"
            }
        ],
        "x": 1560,
        "y": 280,
        "wires": [
            [
                "4e30d3e6.e58c4c",
                "2233ac63.7b7814"
            ]
        ]
    },
    {
        "id": "3a27470d.f15c48",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "original",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "original.slots.command",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "item",
                "pt": "msg",
                "to": "original.slots.item",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1360,
        "y": 280,
        "wires": [
            [
                "4047cdae.b3f6f4",
                "bffdb5b4.05a0c8"
            ]
        ]
    },
    {
        "id": "4e30d3e6.e58c4c",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1710,
        "y": 280,
        "wires": []
    },
    {
        "id": "68ab16fa.60cc78",
        "type": "inject",
        "z": "9f69ee30.2ec97",
        "name": "",
        "props": [
            {
                "p": "control",
                "v": "stop",
                "vt": "str"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payloadType": "str",
        "x": 160,
        "y": 360,
        "wires": [
            [
                "47a1e6ee.4462d8"
            ]
        ]
    },
    {
        "id": "eea2d822.4011a8",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "TonSpielen",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "bing1.wav",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 630,
        "y": 120,
        "wires": [
            [
                "5f8094bf.4bb46c"
            ]
        ]
    },
    {
        "id": "2233ac63.7b7814",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "bing2.wav",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "bing2.wav",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1720,
        "y": 140,
        "wires": [
            [
                "5f8094bf.4bb46c"
            ]
        ]
    },
    {
        "id": "b5e2e51f.eec2a8",
        "type": "comment",
        "z": "9f69ee30.2ec97",
        "name": "Local Speech",
        "info": "",
        "x": 130,
        "y": 80,
        "wires": []
    },
    {
        "id": "ff198956.161b68",
        "type": "switch",
        "z": "9f69ee30.2ec97",
        "name": "",
        "property": "payload.intent.name",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "Licht",
                "vt": "str"
            },
            {
                "t": "eq",
                "v": "beispiel",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 1150,
        "y": 280,
        "wires": [
            [
                "3a27470d.f15c48"
            ],
            [
                "de126189.fc94f"
            ]
        ]
    },
    {
        "id": "de126189.fc94f",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1350,
        "y": 360,
        "wires": []
    },
    {
        "id": "c36db8a4.723f18",
        "type": "inject",
        "z": "9f69ee30.2ec97",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "start",
        "payloadType": "str",
        "x": 110,
        "y": 140,
        "wires": [
            [
                "18ca7c6e.a2e434"
            ]
        ]
    },
    {
        "id": "5f8094bf.4bb46c",
        "type": "sox-play",
        "z": "9f69ee30.2ec97",
        "name": "",
        "outputDevice": "0,0",
        "gain": "20",
        "startNew": "queue",
        "debugOutput": true,
        "x": 1720,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "38ded18a.d4105e",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "stop",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 370,
        "y": 420,
        "wires": [
            [
                "18ca7c6e.a2e434"
            ]
        ]
    },
    {
        "id": "3d6e07c7.254a78",
        "type": "change",
        "z": "9f69ee30.2ec97",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": " sudo systemctl restart nodered.service",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 610,
        "y": 600,
        "wires": [
            [
                "ba4c88dd.cfb568"
            ]
        ]
    },
    {
        "id": "ba4c88dd.cfb568",
        "type": "exec",
        "z": "9f69ee30.2ec97",
        "command": "",
        "addpay": true,
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "oldrc": false,
        "name": "",
        "x": 800,
        "y": 600,
        "wires": [
            [],
            [
                "94d883bc.cee93"
            ],
            []
        ]
    },
    {
        "id": "94d883bc.cee93",
        "type": "debug",
        "z": "9f69ee30.2ec97",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 970,
        "y": 600,
        "wires": []
    },
    {
        "id": "fd76f088.e4c66",
        "type": "voice2json-config",
        "z": "",
        "profilePath": "/home/pi/de_kaldi-zamia-2.0",
        "name": "Kaldi_Deutsch",
        "sentences": "[Licht]\ncommands = (an:ON | ein:ON | einschalten:ON | anschalten:ON  | aus:OFF | ausschalten:OFF){command}\n($items) (<commands>)\nschalte ($items) [(an:ON | aus:OFF){command}]",
        "slots": [
            {
                "fileName": "items",
                "managedBy": "nodered",
                "fileContent": "([die] dachboden lampe){item: dg_l_lampe}\n([das] licht auf dem dachboden){item: dg_l_lampe}\n([das] dachboden licht){item: dg_l_ring}\n([den] ledring auf dem dachboden){item: dg_l_ring}\n(wohnzimmer lampe){item: dg_l_lampe}\n(schlafzimmer lampe){item: dg_l_ring}",
                "executable": false
            }
        ],
        "removeSlots": true
    }
]

Im Anschluss geht in die Node-RED Oberfläche und importiert den Flow. Klickt auf das Menü Icon (1) und wählt Import (2).

Fügt den kopierten Flow in die Box (1) ein und drückt Import (2).

Als nächstes müsst ihr einige wenige Einstellungen vornehmen.

Node-Red Sprachsteuerung Konfiguration

Nun müsst ihr die Konfiguration noch auf eure Bedürfnisse hin anpassen.

Node-Red Sprachsteuerung Konfiguration – openHAB Host

Wenn ihr wie ich openHAB nutzt, ersetzt als erstes den Hostnamen. Öffnet die Node (1), ändert den Host (2) auf euren Hostnamen und klickt Fertig (3). Im Anschluss werden die Befehle an die Rest API von openHAB 2 gesendet.

Node-Red Sprachsteuerung Konfiguration – Kaldi

Als erstes passt die Kaldi Konfiguration an. Klickt auf die Node (1) und im Anschluss auf den ändern Knopf (2).

Hier passt den Pfad zum Kaldi Verzeichnis (1) an. Hier könnt ihr weiterhin einzelne Intents anlegen und die Steuerung für die Sprachbefehle definieren (2).

Eine detaillierte Erklärung zur Syntax gibt es im voice2json whitepaper.

Nun ist es noch wichtig, dass ihr die Slots aufruft (1) und mit dem Bleistift (2) die Konfiguration aufruft und an eure Bedarfe anpasst (3). Zur Erklärung ein Beispiel anhand der Zeilen vorhanden Beispielzeilen. In den runden Klammern steht der Text wie ich das Gerät ansprechen möchte. Ich kann also dachboden lampe, licht auf dem dachboden usw. sagen. In eckigen Klarmmern steht ein optionales Wort. So ist es egal, ob ich das dachboden licht oder dachboden licht sage. In den geschweiften Klammern kommt der Item Namen rein.

Klickt nun oben rechts in der Node-RED UI auf deploy damit eure bisherigen Änderungen aktiviert werden.

Node-Red Sprachsteuerung Konfiguration – Training

Ein weitere wichtige Komponente ist das Training. Nach jeder Änderung der Kaldi Konfiguration müsst ihr ein Training durchführen und Node-RED neu starten. Ich habe den Flow daher so optimiert, dass die nötigen Schritte direkt ausgeführt werden. Klickt einfach auf train (1) und die Schritte laufen automatisiert ab.

Wartet einen Augenblick und ihr die Erkennung sollte funktionieren. Viel Spaß mit dem Ausbau eurer Konfiguration.

Es klappt was nicht? Lasst ein Kommentar da. Ich gebe die Kommentare manuell frei, daher nicht wundern, wenn es etwas dauert. 🙂

27 Comments
  1. Hallo, hab das ganze wie beschrieben installiert. Leider scheine ich was verkehrt zu machen. Also nachem ich die Nodes von Johannes Kropf installiert habe und nodered als Service gestartet ist – sehe ich leider keinen der voice-to-jason nodes. Auch nach dem importieren des Flows sehe ich als einzigen node ein OpenHab sonst nichts. Hast du irgendeine Idee, was ich verkehrt mache?

  2. Hallo, Ich hab den ganzen setup nochmal gemacht. Mit reboot. Dann gings. Vieleicht war der rebott was fehlte.

  3. Reply
    Christian-Alexander Hornburg 11. November 2020 at 17:04

    Hallo Thomas,
    erstmal vielen Dank für die Anleitung.
    Mir ist aufgefallen das der NodeRed Flow unvollständig ist.

    Könntest Du es bitte den vollständigen Flow einstellen?

    Vielen Dank.

    • Hallo Christian,

      danke für den Hinweis. Ich habe ihn nochmal exportiert und eingefügt. Hoffe es geht nun.

      Beste Grüße
      Thomas

  4. Hallo Thomas,
    ich habe mal weitergemacht. Allerdings erhalte ich beim Import des obigen flows nur ein paar wenige nodes.
    OpenHAB und Subflow RestitemOutBlank – RequestVars, HTTP ANforderung, Switch und Auslöser 1s (2 mal).

    Habs paarmal probiert. Immer geleich. Kann man da was flasch machen?

    • Hallo Uwe,

      hab leider den Flow scheinbar nicht ganz rüber kopiert. Versuche es einfach noch mal.

      Beste Grüße
      Thomas

  5. Ich will noch nachtragen:
    Bin erste zwei Tage „node red“ Benutzer und entsprechen unwissend. Hab sonst immer nur C, C++ und sowas gemacht. Das „node red“ ist ja gigantisch gut. Ich hab ne ganz andere Harware als hier beschrieben : homematic. Hab schon ein parr nodes geschrieben, die die Geräteliste lesen und parsen. Das geht soweit gut.

    Aber, bei der Sprachsteuerung wollte ich nicht gern das Rad neu erfinden.
    Hab voher SNIPS benutzt. Ging auch gut. Aber nach der Sonos Übernahme: ende.

  6. Hallo Thomas,

    sicher das der Flow nun komplett ist. Ich habe auch das Problem, dass ich nur die Node „openhab“ und den subflow sehe. Die anderen Nodes, die in den Screenshots angedeutet sind, kann ich in dem gelisteten Flow nicht finden.

    Danke für Deine Hilfe und auch diese tolle Seite.
    Burkhard

    • Hallo Burkhard,

      oh, man ich vermute den Webcache. Hab die Seite noch mal aus dem Cache genommen und den Import selbst getestet. Bitte versuche es noch mal.

      Danke und Grüße
      Thomas

  7. Jetzt sieht es besser aus; deutlich mehr als die 193 Zeilen, die es gestern noch waren. Probiere es heute Abend aus. Danke schonmal.

  8. Hallo,
    ich arbeite schon längere Zeit mit raspi + nodered für meine eigene Smarthomelösung.
    Leider funktioniert
    npm install johanneskropf/node-red-contrib-sox-utils
    nicht. Der raspi findet keine jason package.
    Und nicht nur das, jetzt startet node-red nicht mehr, weil es auch die Daten für voice2json wartet.
    Auch ein uninstall der beiden johanneskropf-nodes hat daran nichts geändert.
    Das sieht nicht so gut aus.
    War wohl nicht gut genug getestet.

    • Ich finde die Idee echt super. Könntet ihr das Setup vielleicht als Docker Image anbieten?

    • Hallo Eberhard,

      das tut mir leid. Der Beitrag war für eine Neuinstallation gedacht. Ich habe oben einen Hinweis geschrieben. Hoffe du hast noch ein Backup gehabt. Es kann leider viele Ursachen haben. Hattst du dein System vorher aktualisiert bzw. welche Versionen (node…) waren bei dir installiert?

      Grüße
      Thomas

  9. Hallo,

    gibt es irgendwo zu dem Thema (voice2json) ein deutschsprachige Diskussionsplatform?

    Ich habe z.b. festgestellt, dass viele meiner Worte unter „unkown_words.txt“ aufgeführt werden, da ich sie mit einem großen Anfangsbuchstaben geschrieben habe.

    Über solche Dinge würde ich mich gerne austauschen.

  10. Hey Thomas,

    gibt es da jetzt einen Zaubertrick wie man das alte ReSpeaker 4Mic Array zum laufen bekommt. Hatte nur deine S.E.P.I.A. Anleitung gesehen und dann das 4Mic Array gekauft… jetzt benutzt ihr hier aber ein anderes Mic.

    Gibt es einen weg wie ich das 4Mic Array auf meinem Pi4 damit auch nutzen kann.

    Danke im Voraus.

    Grüße
    Andreas

  11. Schönen guten Tag,

    ich bin ziemlich neu in dem ganzen Metier und bräuchte Hilfe. Ich hab alles komplett so erledigt wie beschrieben.

    Node-RED zeigt mir im importierten Flow an, dass voice2json unknown ist. Hab den Nachdeme ich sox (zeigte das selbe) gefixt habe, komme ich hier aber nicht weiter.
    Hatte auch die Datei mal heruntergeladen und über Click installiert. Welche Möglichkeiten hätte ich denn noch, dass es funktionert?

    LG Tina

  12. Hallo,
    vielen Dank für sie super Arbeit. Leider bin ich Anfänger und komme bei folgenden Fehler nicht weiter (Raspi 2, Buster mit ReSpeaker 4-Mic-Array ohne USB):

    Command failed: voice2json –profile /home/pi/de_kaldi-zamia-2.0 train-profile
    /usr/bin/voice2json: Zeile 14: 7265 Speicherzugriffsfehler „${prefix}/voice2json/voice2json“ „$@“

    Das Mic geht prinzipiell (Test über arecord bzw. aplay).

    Vielen Dank für einen Hinweis.

    Viele Grüße,
    Ingo

  13. Würde mich auch interessieren, ob das funktioniert, diese Anleitung mit dem 4Mic Array. Lässt sich die Hardware so nicht ansprechen?

  14. Hallo Thomas,

    vorneweg ich kenne mich so gut wie gar nicht mit node-red aus. Jedenfalls sieht es für mich so aus, als ob im Grunde alles richtig funktioniert. Allerdings sendet der Openhab Flow keinen Body mit dem POST Request zum einschalten eines Geräts mit. Es Wird also ein Request an die URL „http://ip:8080/rest/item/…“ gesendet, jedoch ohne den POST Body, der den zu setzenden Status übermittelt. Dementsprechend wird bei Openhab auch nichts geändert. So sieht es zumindest für mich aus, da die Rquest URL im Debuglog korrekt ist. Irgendeine Idee wo das Problem liegen könnte?

    Danke im Voraus
    Grüße Alex

  15. Gibt es Alternativen zu einem USB-Mikrofon? Ich würde gerne mehrere Mikrofone in unterschiedlichen Räumen verwenden.

  16. Reply
    Dominik Lindhorst 1. März 2021 at 18:13

    Hi! Vielen Dank für diese Anleitung. Was muss ich denn an dem flow anpassen, um mit iobroker arbeiten zu können? Nur die ersten Zeilen? Oder wird das umfangreicher? Danke schon Mal! BG dominik

  17. Hallo Thomas,
    nachdem ich deine Anleitung gefunden habe, bin ich jetzt als kompletter Neuling und Nicht-Programmierer in diese Welt eingetaucht. Leider ging das Wochenende dadurch ziemlich schnell rum. Ich habe den klassischen Weg eingeschlagen: Einen Tag so lange rumkonfiguriert bis nichts mehr ging. Am zweiten Tag alles neu aufgesetzt (Openhab 3 + Node-Red), die Erfahrungen vom ersten Anlauf genutzt und siehe da: Alles funktioniert hervorragend. Die größte Herausforderung ist, die Kommandos für Openhab herauszufinden. Hue funktioniert bisher sehr gut. Nur bei der Steuerung von Rollos über Shelly 2.5. haperts noch etwas. Ich würde mich auf jeden Fall über mehr Inhalte zu diesem Thema freuen! Vielen Dank für diese kleine Einleitung! Beste Grüße.

  18. Moin,
    toller Beitrag, sehr gut erklärt, auch für Laien.
    Ich würde gerne noch wissen ob ich auch mehrere Respeaker Mic 2.0 anschließen kann.
    Beispielsweise zur überachung größer Räume.
    Für die Überwachung mehrerer Räume wird es wohl sinnvoller sein seperate Einheiten (Raspberry + Respeaker) zu verbauen. Gibt es da erfahrungswerte?
    Wie sieht es aus wenn der Pi auf mehrere, verschiedene Personen soll? Ich meine Wegen des Trainings…
    Danke und Gruß
    Flo

  19. Hallo Thomas,

    vielen Dank für deine wirklich sehr gut gemacht ANleitung! konnte soweit alles nachvollziehen. Im Node Red sehe ich, dass auch bereits auf Audio Input gewartet wird. Wahrscheinlich habe ich ein Brett vor dem Kopf – aber wo steht das WakeWord bzw. wo kann ich es verändern?
    Vielen Dank
    Michael

  20. Hallo Thomas,

    Habe folgende Situation habe Raspy4 gekauft auch das Mic aber Openhab läuft auf einer anderen IP Adresse nicht auf dem Raspy4 denke ist aber egal muss ich nur anpassen was ich gemacht habe!

    Beim Kaldi Verzeichnis hab ich auch ein anderes nämlich dieses ist bei mir automatisch eingetragen : /home/pi/de_kaldi-zamia-2.0

    hab auch die Items definiert mal ganz einfach nur eines:
    (licht){item: Licht_OG_Wohn_Wand}

    Bei „Voice2Json Wakeword“ steht darunter immer „waiting for audio“

    hab auch schon zum 2. mal die Anleitung durch gemacht und beim 2. mal bei jeden Punkt einen Neustart gemacht aber ich sage „licht ein“ und es passiert nichts

    oder muss ich da irgendein aktivierungs Wort vorher sagen wie beim Amazon Echo „Alexa“

    Hoffe du kannst mir helfen!

    Vielen Danke schon mal im Voraus

  21. Hallo, ich habe alles installiert und aufgesetzt. Leider hinterlässt mich am Ende die Anleitung etwas ratlos. Also, wenn ich bei ‚train‘ was injiziere: und dann? Muss man dann irgendwas sagen? Bei mir steht dann unter dem Voice2Json training node ewig lang … training. Irgendwann stand dann mal success, aber wannn und weshalb weiss ich nicht. Ausserdem steht im Debug Fenster: not recording right now.

    Jetzt steht es schon wieder seit ner halben Stunde auf ..training. Kann ich da irgendwas machen, dass es weitergeht?

    Hinterlasse einen Kommentar

    Smarthome Training and Tutorials
    Logo