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)
SIRI like Spracherkennung unter MacOS Mountain Lion, 4.3 out of 5 based on 9 ratings

18 Gedanken zu „SIRI like Spracherkennung unter MacOS Mountain Lion

    • Wenn es denn so „unnütz für die Welt“ ist und „es alles schon perfekt“ gibt, dann wäre es doch sicherlich intelligenter gewesen, dieses perfekte System zu benennen. Somit hätten wir alle eine Möglichkeit, dies selbst zu beurteilen.
      Ansonsten ist der Kommentar „unnütz für die Welt“ gewesen 😉

      Ich finde das super. Somit kann man sich im Endeffekt auch eigene „Befehle“ ausdenken bzw mehrere Befehle für eine Aktion definieren, damit nicht jeder das Haus steuern kann!
      „Und Gott sprach, es werde Licht“ oder sowas in der Richtung 🙂

  1. Hallo,

    Meine Geräte hängen alle an einer Homematiczentrale die mit der XMLAPI ausgerüstet ist, die ich mit den CURL HTTP Request vom Applescript aus anspreche. Die interne Spracherkennung hat mir persönlich zu schlecht funktioniert von der Erkennungszuverlässigkeit her (vergleichbar mit der Sprachwahl vom iPhone, wo man auch immer mal wieder mehrere Anläuft braucht bis der richtige Kontakt angerufen wird). Siri bzw. der Siriserver liefert mit hoher Erkennungszuverlässigkeit einen fertigen Textstring den man leicht (wie man im Skript sieht) auswerten kann. Mit den speakable items löse ich ja das Stichwort aus um meine Spracherkennung zu starten…

    Am 31.08.2012 um 13:58 schrieb Erik Freydank:

    Hallo,

    ich habe im Internet dein Projekt zu applescript und der neuen Diktierfunktion entdeckt. Gute Sache! Wie steuerst du die Geräte eig. an? Ich habe ein ähnliches Projekt mit der internen Spracherkennung + Applescript und schau mir nun die Diktierfnktion im neuen OSX an.

    was sind die entscheidenen Vorteile der Sirifunktion?

    Du könntest doch in deinem Projekt doch auch alles über die Spracherkennung / speakable Items laufen lassen, wenn man die speakable items so benennt wie der Sprachbefehle letztendlich lauten.

    Viele Grüße,
    Erik Freydank

  2. Hallo,
    Funktioniert wirklich einwandfrei. Vielen Dank!
    Bei mir läuft ein Mac Mini Server. Hast du eine Idee, wie man mehrere Mikrofone per Funk im ganzen Haus verteilen könnte?

    Danke, Sebastian

    • Moin,
      interessante Frage über die ich auch schon nachgedacht hatte – ich wäre bei mir erstmal auf dem Stand, die Mikros alle über den Dachboden zu verkabeln (parallel an einen Mikrofonvorverstärker), da ich ohnehin nur eine Etagenwohnung habe. Bei einem ganzen Haus müsste man sowas wie einen simplex Audiosender haben der durch eine Pegelerkennung immer nur das Mikro mit dem Server über Funk verbindet wo gesprochen wird. Mehrere Funksender parallel senden zu lassen wäre vermutlich durch die Modulation nicht möglich. Evtl. könnte man auch Funkmikrofone aus dem Studiobereich mit einem Mischer parallel auf den Line-In am Mac bekommen – mehr fällt mir da gerade auch nicht zu ein. Eine elegante Möglichkeit wäre auch noch mit einem Siriproxy die Kommandos abzufangen und zu nutzen, so bräuchte man nur sein Smartphone zur Hand nehmen.

  3. Hi,

    Ich habe den Video mit Spannung verfolgt. Ich bin sehr beindruckt was alles mit dieser Sprachsteuerung möglich ist. Nun zu meiner Frage ich habe jetzt die scripts runtergeladen und mir auch angeschaut und angepasst. Wenn ich nun zum Beispiel Siri sage da passiert folgendes. Es kommt immer: „Entschuldigung, ich verstehe diesen Befehl nicht.“

    Was muss ich tun? Damit es funktioniert.

    Mit freundlichen Grüßen

    John

    • Hallo,
      Ich stelle meinen Code ohne jeglichen Gewähr auf Funktion zur Verfügung – diesbezüglich kann ich hier keine Hilfestellung geben, zudem kann ich anhand einer so dürftigen Beschreibung sowieso nicht deuten was hier falsch gelaufen ist.

  4. Hey, total super!
    selbst wenn man keinen homeserver für licht etc hat, macht es richtig spaß damit rumzuspielen. so hab ich angefangen das script mit arrays zu erweitern. jetzt kann mein mac mir witze erzählen;) Auch iTunes funktioniert schon fast wie auf dem iPhone mit Siri…
    auch ist es möglich durch simples copy Paste und ein paar weitere kleine scripte eine frage antwort Funktion zu implementieren. so fragt mich mein mac jetzt wenn ich hallo sage „wer ist da?“ oder auch „Kenne ich dich?“ und dann muss man erneut antworten. meinen namen habe ich in einem array hinterlegt, so dass er mich dann anhand meines Namens wiedererkennt und mich dann entsprechend begrüßt. kennt er jemanden nicht, sagt mein mac dann „Hallo >>fremder name<<! Schön dich kennen zu lernen." danach speichert er den neuen Namen ebenfalls im Array und die Person wird beim nächsten Hallo ebenfalls wiedererkannt.

    Ich bin wirklich zutiefst Dankbar! ich finds einfach Klasse!

    • Freut mich, dass der Code so universell einsetzbar ist 🙂 Wäre schön vielleicht mal einen Auszug oder dein Script hier als weiteres Beispiel zu Veröffentlichen – natürlich gerne unter Nennung eines Links oder Verweis auf den Autor…

          • Ich habs nochmal neu hochgeladen, mir sind ein paar kleine Fehler noch aufgefallen. Außerdem habe ich ein Problem mit der namen.txt und der sitze.txt entdeckt. Da fehlen nach dem verschieben die nötigen Zugriffsrechte. Um das Problem zu beheben, einfach die zwei Dateien duplizieren, die alten löschen und die neuen wieder umbenennen. Etwas nervig, da man jedes mal das Passwort eingeben muss…

          • Jungs, ihr habt sie nicht mehr alle 😉 und das mag ich. Bitte weiter so. Bin vor 5 min über die Seite gestolpert und zwinge meinen Mac jetzt zu nem kleinen Jarvis (a lá Iron Man) zu werden. Da muss er jetzt durch. Ich wäre aber sehr daran interessiert, das Thema mal richtig auszureizen 😉 sprich, das Ganze in Richtung Tipps und Tricks (Welche Heimsteuerungsanlage empfiehlt sich hier, wie wird der Befehl über Terminal an die Anlage weiter gereicht) usw. ausweiten zu lassen.

            Beste Grüße
            Jens

  5. Hi,

    hat mich sehr inspiriert dieser Artikel und das Video! Herzlichen Dank dafür 🙂
    Ziemlich passend, da ich grade Star Trek Voyager gugge … 😀

    Leider kann ich mit den speakable items gar nicht spielen – es erkennt keine Eingangssignale meines Mikrofons (via Mischpult in USB-Soundkarte).

    Ich hoffe, dass dieser Bereich der Technologie nach Veröffentlichung des iTV auch für Mac nachgebessert wird.
    Danach melde ich mich gerne wieder hier mit meinen Code-Zeilen für bequemes Arbeiten und Multimediasteuerung via Voice 😉

    Grüße, Tobi

Schreibe einen Kommentar zu m.roth Antworten abbrechen