SIRI like Spracherkennung unter MacOS Mountain Lion

Geht momentan nicht? Aber hallo wie gut das mit einem kleinen Umweg geht!

Seit kurzem ist Mountain Lion mit der Diktierfunktion raus (für mich genauso unbrauchbar wie am iPad 3). Auch wenn ich es nie zum Diktieren benutzen wollte ist es für eine Steuerung der Hausautomation prinzipiell prädestiniert, da die Erkennungsquote sehr gut ist und die Spracherkennung einen String zurückliefert den man sehr leicht in Skripten auswerten kann. So habe ich mal ein wenig getestet und war begeistert!

1. Feststellung: die Diktierfunktion ist relativ zügig
2. Feststellung: die Diktierfunktion erkennt ein Terminal Fenster als „Textbox“

Der schnellste Weg führte natürlich in Richtung AppleScript, da ich das schon ganz gut drauf habe.

Bevor wir zum Scripting kommen, die Vorbereitungen, damit das prinzipiell jeder umsetzen kann, was ich hier erkläre:

1. Diktierfunktion in den Systemeinstellungen aktivieren

Und den Kurzbefehl zum Aktivieren der Diktierfunktion auf:

2. Sprachausgabe auf Deutsch Stimme „Steffi“ einstellen
einfach im Fenster der Diktierfunktion den Reiter auf „Sprachausgabe“ wechseln

3. In den Bedienungshilfen die „speakable items“ aktivieren

Darauf hin erscheint der Controller

Nun können wir zu den beiden Scripten kommen. Das erste ist ein Hilfsscript welches durch die „speakable item“ ausgelöst wird. Dieses wird später in den Pfad der verfügbaren Sprachbefehle kopiert, wo sich die leider alle in Englisch gesprochenen rudimentären Sprachbefehle von MacOS befinden.

Nun das Script voicehelper.scpt

tell application "Terminal" to activate
delay 1
tell application "Terminal" to activate
tell application "System Events"
    tell process "Terminal"
        -- Bitte den Pfad auf den eigenen Benutzerordner anpassen!
        keystroke "cd /Users/max/Desktop/ac_voice/" & return
        keystroke "osascript voice.scpt "
        keystroke (ASCII character 34)
        delay 1
        keystroke "d" using command down
        delay 5
        keystroke "d" using command down
        delay 1
        keystroke (ASCII character 34)
        key code 76 -- Enter auf Nummernblock
        delay 5
        --keystroke "q" using command down -- beendet TextEdit per Apfel-Q
    end tell
end tell
tell application "Terminal" to quit

Das Script manipuliert schlicht das Terminalfenster und übergibt so das Gesprochene an das eigentliche „intelligente“ Script voice.scpt weiter, welches die Worte in Befehle umsetzt.

voicehelper.scpt muss z.B. in home.scpt umbenannt werden (vorzugsweise als Duplikat) und dann in den „speakable items“ Ordner in der Benutzerlibrary kopiert werden, damit es dort als neuer Sprachbefehl erkannt wird.

Nun das Script voice.scpt :

Der Aufruf aus dem Terminal sieht quasi so aus: osascript voice.scpt „Schalte das Licht in der Küche ein“

-- URL für Homematic XMLAPI Request
property XMLAPI : "http://192.168.1.10:90/xmlapi/statechange.cgi"

on run this_file
    set voicecommand to " "
    set goodcommand to 0
    --say (this_file)
    set voicecommand to (this_file) as text
    --say voicecommand

    if voicecommand contains "Kaffee" then
        set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=15961&new_value=true'"
        set goodcommand to 1
    end if

    if voicecommand contains "Abend" then
        set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=7765&new_value=false'"
        set goodcommand to 1
    end if

    if voicecommand contains "Alles aus" then
        set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=7773&new_value=false'"
        set goodcommand to 1
    end if

    if voicecommand contains "Siri" then
        say "Verdammt hör auf mich so zu nennen! Ich bin 10 mal besser als Siri."
        set goodcommand to 1
    end if

    if voicecommand contains "hass" then
        say "Das beruht ganz auf Gegenseitigkeit. Wenn du mich so hasst dann schalte ich halt keine Lichter mehr für dich!"
        set goodcommand to 1
    end if

    if voicecommand contains "versteh" then
        say "Dann sprich deutlicher."
        set goodcommand to 1
    end if

    if voicecommand contains "Jalousien" then
        if voicecommand contains "runter" then
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=36931&new_value=0.0'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33590&new_value=0.0'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33565&new_value=0.0'"
            set goodcommand to 1
        end if

        if voicecommand contains "hoch" then
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=36931&new_value=1.0'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33590&new_value=1.0'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33565&new_value=1.0'"
            set goodcommand to 1
        end if

        if voicecommand contains "stop" then
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=36932&new_value=true'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33591&new_value=true'"
            set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=33566&new_value=true'"
            set goodcommand to 1
        end if
    end if

    if voicecommand contains "Licht" then
        if voicecommand contains "Küche" then
            if voicecommand contains "ein" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1465&new_value=true'"
                set goodcommand to 1
            end if
            if voicecommand contains "aus" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1465&new_value=false'"
                set goodcommand to 1
            end if

        end if
        if voicecommand contains "Vitrine" then
            if voicecommand contains "ein" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1494&new_value=true'"
                set goodcommand to 1
            end if
            if voicecommand contains "aus" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1494&new_value=false'"
                set goodcommand to 1
            end if

        end if
        if voicecommand contains "Wandlampe" then
            if voicecommand contains "ein" or "ein" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1623&new_value=true'"
                set goodcommand to 1
            end if
            if voicecommand contains "aus" or "aus" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of (XMLAPI & "?") & "' -d 'ise_id=1623&new_value=false'"
                set goodcommand to 1
            end if

        end if
    end if

    if voicecommand contains "led" then
        if voicecommand contains "Wohnzimmer" then
            if voicecommand contains "orange" then
                -- Ansteuerung LED Controller
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Za255a72a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "blau" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Za21a0a255a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "rot" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Za255a0a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "grün" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Za0a255a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "aus" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Za0a0a0a5'"
                set goodcommand to 1
            end if

        end if
        if voicecommand contains "Kugel" then
            if voicecommand contains "orange" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Ya255a72a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "blau" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Ya21a0a255a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "rot" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Ya255a0a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "grün" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Ya0a255a0a5'"
                set goodcommand to 1
            end if

            if voicecommand contains "aus" then
                set ReturnValue to do shell script "curl  -s '" & quoted form of ("http://192.168.1.20:8080/ledcontr/contr.php?" & "?") & "' -d 'com=Ya0a0a0a5'"
                set goodcommand to 1
            end if

        end if

    end if

    if goodcommand = 0 then
        say "Entschuldigung. Ich verstehe den Befehl, " & voicecommand & ", nicht."
    end if

end run

Durch die Verschachtelung wird ohne weiteres zutun ein Satz wie: „Schalte das Licht in der Küche aus“ ausgewertet nach den Kriterien „Licht“ & „Küche“ & „aus„. Vom Sinn kann also auch ohne Probleme „Licht Küche aus“ oder „Bitte das Licht in der Küche ausschalten“ gesagt werden 🙂

Das voice-Script kann so nach eigenen Bedürfnisses quasi grenzenlos erweitert werden…

Build your own Siri !

Ich war echt erstaunt, wie gut das mit den verschachtelten IF-Bedingungen geklappt hat 🙂 Geht mit Sicherheit eleganter, ist vielleicht ein guter Denkanstoß für Andere…

Das komplette Paket mit den Scripten gibts hier zum Download…

click

Hier noch ein Video vom Einsatz der Scripte:

Fragen und Anmerkungen willkommen! Bitte zeigt dann euere Projekte, falls Ihr meinen Quellcode verwendet oder ihn als Denkanstoß nutzt.

Nachtrag „Tips & Trick“ Ansteuerbare Geräte und Haussteuerungen:

Ich verwende, wie an vielen Stellen erwähnt, die Homematic Steuerung (CCU-1) von ELV. Die Zentrale hat ein AddOn „XMLAPI“ installiert welche auf einem 2. Webserver über (wie im Skript) CURL angesprochen wird. Stellvertretend kann man also über einfache HTTP Request so ziemlich alle anderen Systeme ansteuern. (Beispiele wo es sofort ohne Weiteres möglich ist: Dreambox, IR-Trans, Homematic mit XMLAPI). Bei der Dreambox kann man über das Webinterface alle Tasten der Fernbdienung „drücken“ und somit das Fernsehen per Sprache kontrollieren. Beim IR-Trans in Verbindung mit der Gerätedatenbank selbiges für alle angelernten IR Befehle.

VN:F [1.9.22_1171]
Rating: 4.3/5 (9 votes cast)

Mountain Lion bringt mir den Ruhezustand (nach Timer) zurück

Endlich geht dieser nun wieder, nach einem Jahr MacOS Lion. Bei mir sowie den meisten meiner Mac Kunden funktionierte damals nach dem Lion Update der automatische Ruhezustand nach dem Timer in den Systemeinstellungen nicht mehr – ließ sich nur noch manuell aktivieren oder durch „Gewalt-Tools“ wie Please Sleep…

Eine Sorge weniger 😉

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)