#author("2021-11-02T12:52:22+09:00","ocha","ocha")
#author("2021-11-02T12:58:30+09:00","ocha","ocha")
[[SiioLaboratory]]

*Terminal.appからのコマンドでSiriを動かす方法 [#y3cf656c]

こちらもご覧ください。

http://is.ocha.ac.jp/~siio/?How2AppleScript

** AppleScript (もしくはOSA, もしくはAppleEvent) [#s12e669c]

ターミナルからのコマンドでSiriが操作できれば、シェルスクリプトやプログラムの中からSiriを使えるようになります。
そうすれば、プログラムからスマート家電を制御する、ネットからの情報を音声で取得する、などが可能になります。

macOSのプログラムの一部は、
[[Open Script Architecture (OSA):https://ja.wikipedia.org/wiki/Open_Scripting_Architecture]]をサポートしていて、
[[AppleEvent:https://ja.wikipedia.org/wiki/Apple_event]]に対応しています。
OSAは、アプリケーション間のコントロールを行うために機構で、AppleEventはその際に交換されるメッセージです。
また、アプリケーション間でAppleEventを送受信するスクリプト言語に、AppleScriptが使われてます。

** AppleScriptの例 [#zec3b26a]

AppleScriptを使えば、対応したアプリケーションに、それを操作するメッセージが送れます。
例えばiMessageの椎尾のアカウントにメッセージを送るには、

 tell application "Messages"
 	send "Hello!" to participant "siio@mac.com"
 end tell

というAppleScriptを用意します。macOSに標準値ついているスクリプトエディタ.app (英語名 Script Editor.app)を使うと、AppleScriptのテストが楽です。

シェルスクリプトファイルで、

 #!/usr/bin/osascript
 
 tell application "Messages"
 	send "Hello!" to participant "siio@mac.com"
 end tell

という内容を用意して、実行可能にしておけば、ターミナルからも実行できます。また、ターミナルのコマンドラインから、

 osascript -e 'tell application "Messages" to send "Hello!" to participant "siio@mac.com"'

とすると同じことができます。
何かの状態をモニターするプログラムの中で、その状況をメッセージで知ろうとする場合に、役立つテクニックかと思います。
(例えば人気チケット販売サイトをモニターして、キャンセルが出たらメッセージで伝えるというような時)

これが可能なのは、Message.appアプリケーションがOSAに対応していて、sendというコマンドを提供してくれているからです。

**「Siriに頼む」アプリケーション [#te3a75df]

なので、「Siriを起動してメッセージを送るアプリケーション」がOSAに対応していれば、ターミナルからAppleScriptを起動させることで、Siriを制御できるはずです。
macOSには「Siriに頼む」機能があります。これを担当しているアプリケーションが、/Applicationsの中にあるSiri.appです。

&ref(SiriApp.jpg);

ターミナルからアプリケーションを起動するためには、open -aコマンドが使えます。Siri.appを起動するためには、

 open -a Siri.app

とタイプします。
しかしながら残念なことに、Siri.appはOSA (AppleEvent) に全く対応していません。

** System Events.appを使う [#i283fc87]

OSAに対応していないアプリを操作するチート技がSystem Eventを使う方法です。
キーボードやマウスのイベントをプログラムで作り出して、人が操作しているような状況を自動化します。
GUIを自動化しようとするときの伝統的な技法と言えます。

コマンドラインから起動して、最初の引数の文字列をSiri.appに送るスクリプトを以下に紹介しておきます。

 #!/usr/bin/osascript 
 
 on run argv
         tell application "Terminal"
                 activate
                 do script with command "open -a Siri"
 
                 delay 0.4
 
                 tell application "System Events"
                         keystroke (item 1 of argv)
                         key code 76
                 end tell
 
                 delay 0.1
                 tell application "Siri" to quit
                 delay 5
                 close window 1
         end tell
 end run

これで動くと思ったのですが、日本語が通りませんでした。「システム環境設定」「Siri」「言語」を英語に設定すると(英語で)以下のように動きます。

 % ./siri.sh 'What time is it?'
 % ./siri.sh 'Turn on the light.'

日本語だとkeystrokeがうまく動作しないようです。かな漢字変換が入るところなので当然かなと思います。
それで、コピペでコマンドを渡すバージョンを作りました。以下です。
pbcopyやpbpasteは、ペーストバッファに読み書きするコマンドで、コピーペーストに相当します。なのでこのコマンドを実行した後にペーストすると、コマンドの引数が残っています。

 #!/bin/sh
 #Shell and OSA script to send a message to Siri.
 #Works in any language, though English is recommended.
 
 if [ $# = 0 ]; then echo 'Usage:' $0 '"Message to Siri."'; exit 1; fi
 
 #copy the input text to the paste buffer
 echo $1 | pbcopy 
 #open the Siri input window
 open -a Siri #start Siri menu
 
 #send command-v key combination (paste) to Siri and quit
 osascript -e '
 	tell application "Siri"
 		delay 0.5 #required for Siri response
 	
 		tell application "System Events"
 			keystroke "v" using {command down}
 			key code 76 #return key
 		end tell
 	
 		delay 0.5 #required for Siri response
 		quit
 	end tell
 '

これを例えばsiri.shという名前で保存して実行可能にしておけば、

 % ./siri.sh 今日の天気は?
 % ./siri.sh あかりを消して      
 % ./siri.sh あかりをつけて  
 % ./siri.sh "今の時間は?"    
 % ./siri.sh "pink floydをかけて"

などの操作がターミナルから可能になります。
Siriの応答速度に合わせてdelayを設定している微妙なプログラムですので、コンピュータ環境によって修正の必要があるとは思います。

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS