詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

PCを離れたらマイク音量を下げるmacOSアプリを作った

この記事は、はてなエンジニア Advent Calendar 2020の21日目です。昨日は id:tarao による Scalaの依存ライブラリ更新はRenovateでもけっこうイケる でした。明日は id:Krouton です。


みなさん在宅勤務してますか? 私もしています。

仕事も雑談も、とにかくオンラインで話すことが多いので在宅勤務中は AfterShokz という骨伝導ヘッドホンを使っている。ずっと装着してても疲れにくいので、大変いい買い物です。

いちいち外すのも面倒なのでほとんど一日中付けっぱなしにしているんだけど、これが事故を呼ぶこともある。マイクをオフにすることを忘れて離席してしまうと、オフのときの会話が筒抜けになってしまうので、同僚の前ではおとなしいのに家族の前では豹変するとか……。あとおしっこしてる音が聞こえちゃってないとか。気になりますよね。油断できない。

そういうわけで、現実のメンタルモデルにあわせて「パソコンからの距離が遠くなったらマイクの音量を下げる」ってアプリを作ってみることにした。ちょうど macOS アプリを作ってみたかったというのもある。そうだったかな。かもしれない。距離は Bluetooth の信号強度(RSSI とかいうやつ)を使えば十分だろう。

できたもの

GitHub - motemen/macos-BluetoothAudioDistancer

初めてだったけど、SwiftUI のおかげでわりと簡単に作ることができた。

f:id:motemen:20201221210613p:plain
現在値が最大値を超えてますがあまり気にしないでください

設定をどんな風にさせるかが悩ましく、信号強度の時系列グラフを描画して、インタラクティブに閾値を選択できるといいかと考えていたが、何も知らん状態からだと難しそうだし、さっさと完成させたいので楽をすることにした。Calibration mode のチェックをオンにすると信号強度を記録するモードになるので、その間に家の中をうろついて最高強度と最低強度を覚えさせておく。あとは現在の信号強度が最低~最高のレンジのどこにいるかを見て、ボリュームに反映させる。こんな感じの式にした。

これで、コーヒーを飲んだりトイレに行ったりしているときには入力ボリュームが小さくなり、なんならゼロになり、Meet や Discord のマイクをオフにしたかどうかを気にせず独り言が言えるようになったわけです。

わかったこと・わからなかったこと

  • 数日間使ってみて思ったけど、別に音量を小さくする必要はあまりなくて、一定距離離れたらオフになってくれたらいい。
  • macOS で、Bluetooth デバイスとオーディオデバイスを突き合わせる方法がわからない。今はとりあえず AudioObjectGetPropertyDatakAudioDevicePropertyDeviceUID を使用した際に取れる UID が IOBluetoothDeviceaddressString に対応するらしいと想定しているけど、UID は本来ブラックボックスなので、正しいやり方ではなさそう。というか自分の環境でしか試してないので、偶然に頼ってるかもしれない。
  • メンタルモデルができてないからか、Apple Developer Documentation がどうも読みづらかった。API の使用例とかあんま載せてくれないのかな。Stack Overflow が役に立った。
  • 最初 Swift Playground で試して、よさそうだったのでプロジェクトを作ったんだけど、権限の関係で挙動が変わって難儀した(エラーになるとかではなく、0 が取得される、というぐあい)。
  • SwiftUI で作ったウィンドウの最大化や最小化を禁止する方法は、SwiftUI の世界にはなさそうな気がする。NSApplicationDelegateAdaptor というのを使うと NSWindow とか触れる感じ。でたよデリゲート! って気持ちになった。
    • ホントは Dock から隠してメニューバーに常駐させるなどできればカッコイイと思っていたのだった。
  • プロジェクトの設定で Team を設定しないと PreviewProvider による Xcode でのプレビューが失敗する? 気がする。最初設定してなかったので困った。
  • GitHub にソースコード push してるけど、これみんなビルドできるの?

Big Sur の見た目はちょっと気に入ってるので、小さなアプリでも作れると楽しいですね。もしビルドできそうだったら、どうぞご利用ください。

Google Meet のミュートをツールバーから切り替える拡張を作った

Google Meet Mute Toggler - Chrome ウェブストア

こんなやつです。

Google Meet で仕事をすることが多くなった昨今、咳払いや生活音といったよんどころない事情によりマイクをミュートにしたいこともあるわけですが、ミュートボタンは普段隠れていて急に出てこないし、切断ボタンの隣りにあってちょっと怖い。正確なエイムが求められるのは小さなストレスになってるわけですね。この切り替えボタンをツールバーの常に同じ位置に置くことで、それを軽減させようとするものです。

Chrome 拡張のストアって決まった大きさの画像をアップロードしないといけないので面倒だったんだけど、画面の録画を YouTube に上げたらいいってことがわかりました。

Google Meet Mute Toggler Demo - YouTube

ソースコードはこれ。

GitHub - motemen/chrome-meet-mute-toggler: Easily toggle your microphone mutes on Google Meet meetings, by clicking toolbar button.

最近のウェブアプリは外部からいじりやすいクラスがついてなくて困るので、aria-label 属性へのマッチで要素を探してるのだが、これがまた言語によってスペースが入ってたり入ってなかったり大文字小文字だったりで大変だ……。

  document.querySelector<HTMLElement>(
    [
      '[role=button][aria-label*="⌘+D" i]',
      '[role=button][aria-label*="⌘ + D" i]',
      '[role=button][aria-label*="Ctrl+D" i]',
      '[role=button][aria-label*="Ctrl + D" i]',
    ].join(",")
  );

Chromebookを買った

iPad が使えなくなってしまったので電子書籍を読むときにちょっと困っていて、8インチくらいの安い Android タブレットでもないかなーと社内で相談したところ、「Chromebook はどうか」と薦められた。えー10インチだし予算オーバーだし……と思っていたけど、魂が否応なく惹かれてしまう衝動があって Lenovo Chromebook Duet を買ってしまったのだった。運命だったのかもしれない。

結論から言うと大変満足している。ふだん Android 使ってる人にはオススメしたい!

ハードウェア

まず充電が USB-C で行えるのはすばらしいですね。

キーボードがついてるので普通のパソコンにもなるし、外せばタブレットにもなる。まあキーボード使うのはキーボードを使うってことを目的にした遊びだけで、基本的にタブレットとして使ってるけど。トラックパッドが付いてるけど、MacBook と比べるとこれの滑りがわるくて最初面食らった。

試しにこのエントリも Chromebook で書いてみていたけど、まあ書けないことはない。ふだんは AZIK を使ってるんだけど、Chrome OS の IME ではそのようにカスタマイズできないので、ちょっとつらい。Play ストアからアプリを入れられるので Gboard を試してみたけど、なんか安定しない感じがある。

あと指紋アンロックみたいな高度なことはできなくて、当初はオイ~と思ったけど後述するスマートアンロックで割と用を足せるのでそんなに不満はないかな~。

基本的にWebアプリを使う世界観

というか、Google Chrome を使う。2020年ともなると人間の活動の多くはウェブで済んでしまうので、ほぼ困らないのであった。

スマートフォン向けではなく、PC で使ってるいつもの Chrome がタブレット上で使えるのはちょっと不思議な感覚がある。拡張も普通に使えるので、タブレットでブラウジングしてるときに AutoPagerize が効いて大変快適。

ただ、PC とプロファイルを共有していると、インストールしている拡張やアドレスバーに置くボタンの設定まで同じになってしまうのでちょっと困る。タブレットでは使わない拡張(開発用ツールとか)もあるし、狭い画面であまり拡張ボタン増やしたくないんだよな……。デバイスごとに使い分けられるといいんだけど、致命的ではないのであきらめてボタンの数を減らして使ってる。

ウェブアプリは Chrome のメニューからショートカットをホーム画面に作るか、対応している場合はアプリとしてインストールできる。

タブレットモードで Scrapbox を使うときは、長押しが Chrome の右クリックメニューを呼び出してしまうのでやや使いづらい。さいわい、貼り付けなどは Chrome のメニューから行えるのでそれでまかなっている。こまかい範囲選択とかは難しそう。ただしアプリとしてインストールするとメニューが呼び出せないので、タブとして開くのがオススメ。

Androidアプリも使える

Google Play ストアから Android アプリをインストールできる。もともと Kindle と Google Play ブックが使いたかったのでこれは必須条件だ! 多くのことがウェブで可能だとはいえ、アプリで行いたいことも多い。たとえば YouTube はアプリで観たほうがスムーズな気がするな。けどそれくらい。音楽や絵をやる人はまた違うのだと思うが。

Chrome からインテントで URL を共有する、というようなことができないので、インテント目的で利用していたアプリは拡張に置き換わる感じ。

そしてブラウザではできない体験と言えば、カスタムキャストである。でかいデバイスを買ったらぜひインストールしたいところだ。 Android であれば .maid ファイルを Android/data/jp.customcast.cc2/files/Maid に Android File Transfer で送り込めばスマホで作成したキャラクターをインポートできたのだけど、Chromebook の場合はこれが使えないので、ひと手間必要だった。

……と思いきや、ファイラーの設定メニューから Android 領域を表示して(ファイルを開く、保存する、削除する - Chromebook ヘルプ)ファイルをコピペすればよさそう。かんたんじゃん。

一応メモっておくと自分は 開発環境 | Android デベロッパー | Android Developers にしたがって ADB デバッグを有効を使えるようにして、Linux コンソールから adb push でファイルを置いた。

f:id:motemen:20201022135514p:plain

やったね!(わざとらしいスクショ)

ただしパフォーマンスはよくない。でかい画面で見られるだけで僥倖ですが。あと、カメラがアクティブになってるランプが常時つきっぱなしになって、怖い。

Linuxでも遊べる

上に書いたように Linux コンソールが使える! のでとりあえず Homebrew を入れてみようとしたのだけど、Ruby のビルドから始めないといけなかった。Linuxbrew on IdeaPad Duet - pn11 に書いてあるような感じ。

ghq くらい入れておくかと思ったけど、アーキテクチャが arm64 な関係で Go も含めていろいろ自前でビルドしてやる必要があって、Homebrew をつかううまみはなかった……。

Androidとの連携が便利

指紋アンロックなどはない、と上に書いたが、Smart Lock というやつで、Android スマホをアンロックすれば Chrombook にログインできる、という連携が可能。スマホは指紋アンロックできるわけなので、これで割とまかなえる。ときどき連携がうまく働かないときもあるけど。 ただスマホの画面がずっとオンになってると常時アンロック可能になってしまうのでそこは気をつける必要がある。仕事には使ってません。

あと、スマホを連携しておくとインスタントテザリングというのも使えて、Chromebook の側からスマホのテザリングを有効にして接続していくことができる。電車で使うときに便利。

……という Chromebook がいまなら Amazon で10%オフクーポンつきですよ! 今年いっぱいなので Chromebook 仲間になっていいこと教えてください。

はてなで一緒に働きませんか?