Macでオンラインミーティング中に電球を点ける
MacでオンラインMTG中に電球を点ける仕組みを構築した pic.twitter.com/qhpXTbv4cY
— songmu (@songmu) August 15, 2024
夏休みに入って、子供たちが仕事部屋に乱入してくることが増えた。何番煎じかわからないが、オンラインミーティングが始まったら電気を点ける仕組みを作って投入した。カメラがついている時にミーティング中だという判定をしてライトを点灯する。概要は以下。
- カメラ(及びマイク)のon/offを検知する
- OverSight を使う
- 検知をトリガーにプログラムを実行
- mtglight というのを作った
- プログラムからIoTライトを操作する
- Yeelight の製品を使った
- 一応多重実行を防ぐ排他制御をしこむ
- setlock を使う
私以外にこの仕組みを使う人がいるとは思わないが、以下の手順で導入できる。
- Yeelightを調達してきて設定する
- 私が買ったのは YLDP13YL というやつだがもう売ってなさそう。後継モデルでも多分動く
- (実はこの仕組みを作ったのが2年くらい前なのでその時に買ったものだったりする)
- 同じネットワークに繋がっている作業PCにOverSightとmtglightをインストールしてこのあとの解説を見て設定する
カメラのon/off検知
yoshioriさんがLinuxで同じようなことをやっているが、カメラの利用検知はMacだと案外難しい。そこで、カメラやマイクのon/offを検知してくれるOverSightというソフトウェアをインストールして利用する。これ自体危険性を孕むソフトウェアだが、そういう不正なカメラやマイク利用を検知するためのソフトウェアであり、ソースもGitHub上で公開されている。
検知をトリガーにプログラムを実行する
このOverSight、カメラやマイクのon/offのイベントを通知してくれるだけではなく、そのイベントをトリガーにしてプログラムを実行できる。
今回、その仕組みに乗っかってライトを制御するためにGoで作ったのが github.com/Songmu/mtglight 。これを適当なところに配置して、OverSightの設定画面から以下のようにしていする。ここでは直接していせずに .sh
を指定しているが、これはシェルスクリプトでラップしているため。排他制御が気にならなければ別に直接しても良い。
この画面に示されているように、プログラムにはいくつかのコマンドライン引数が渡される。このコマンドライン引数を見ることで、イベントの種類やデバイスの状態を判断できる。
-device
に cameraかmicrophone、-event
に onかoff、-activeCount
にアクティブなデバイス利用数の合算値が渡される。合算値というのはカメラとマイクの合計で、複数のオンラインミーティングを開いているときなどに複数プロセスからデバイスが利用されている場合には、その延べカウントになる。カメラとマイクの合算値になるのは少し使い勝手が悪い。
ちなみに、この -process
という引数はデバイス呼び出し元のPIDが取れるので、そのプロセスの死活監視をすればミーティング開催中判定ができるのではないかと期待したが、その用途には使えなかった。このプロセスはオンラインMTG自体のプロセスではなく、デバイス管理プロセスかなにか別のプロセスであり、ミーティング終了後も基本的には生存し続けていたからだ。
今回、一番気になるのがカメラなので、cameraのonイベントが送られてきた時に点灯するようにした。また、ライトを消灯するのは、cameraのoffイベントが送られてきたときではなく、activeCountが0になった時に消灯するようにした。これは、cameraのoffイベントが通知されたとしても、別のウィンドウではまだカメラが使われている可能性があるからである。activeCountが0であればマイクも含めてすべてのデバイスがoffになったということなので、消灯してもよかろうという判断。また、これによって、MTG中に一時的にカメラをoffにしても消灯されてしまうこともない。
プログラムからIoTライトを操作する
プログラムからは Yeelight の電球を操作している。前項の mtglight
のソースコードを読むとわかるが、同一ネットワークにつながったYeelightの電球を探し、黄色を最大輝度で決め打ちで点灯するようにしている。なので、自宅の外のネットワークに繋いだ時に、そこでYeelightが使われていたら勝手に操作してしまうかもしれない😎
操作するのは何でも良くて、yoshioriさんがやっているようにスマートプラグを使うのは自由度が高くて良いと思う。 mtglight
でそのあたり抽象化しても良いかと思ったが、別にそこまでするまでもないと思ったのでやっていない。
多重実行を防ぐ排他制御をしこむ
mtglight
はOverSightからイベントドリブンで呼び出されるため、多重起動される可能性がある。そこをちゃんと排他に直列で実行されるようにしたい。そこで setlock
を使う。
setlock
はバッチの多重起動を防ぐための古式ゆかしいコマンド。daemontoolsに同梱されており、MacでもHomebrewをお使いであれば、 brew install daemontools
でインストールできる。Homebrewを使っていない場合、頑張って自分でビルドするか、moznionさんが作ったGo製の go-setlock があるのでそれを使っても良いかもしれない。
このsetlock
を使って以下のようなシェルスクリプトをmtglight
が配置されたディレクトリに配置する。これでこのスクリプトが多重で呼び出された場合であっても、mtglight
は多重起動されず、別プロセスの終了を待って、直列で実行されるようになる。便利。
#!/bin/sh
cd $(dirname $0)
exec /opt/homebrew/bin/setlock ./mtglight.lock ./mtglight "$@"
まとめ
Yeelightはともかく、OverSightを使ってデバイスのon/offを検知するのと、それによってプログラムをトリガーして、排他制御にsetlockを使う、というのは応用が効くと思うので、他の方も是非試してみてほしい。