技術解説
PausePace がマイクを使わずに通話を検知する仕組み
Mac 版 PausePace は、通話・ビデオ・プレゼンテーションが終わるまで休憩を保留します。そのために「マイク」「カメラ」「画面収録」「アクセシビリティ」へのアクセスを求めることはありません。このページでは、読み取っている macOS の信号、それに適用するルール、そしてその限界を説明します。
公開日:
信号
- マイクやカメラが使用中か(はい/いいえ)
- 最後の入力からの秒数
- 最前面のアプリ、フルスクリーン、ディスプレイのスリープ抑止
- ロック中またはスリープ中
ルール
- 通話・ビデオ・プレゼンテーションの間は保留
- 入力の手が止まる、アプリを切り替える、保留が終わるのを待つ
- 上限を超えて延期しない
休憩
- 短い事前通知
- Mac に休憩カードを表示
- ペアリングしていれば、iPhone と Apple Watch にも同じ休憩を表示
要点
- PausePace が読み取るのは、macOS がどのアプリにも提供している「はい/いいえ」や時間の信号だけです。たとえば、マイクやカメラが使用中かどうか、最後のキー入力から何秒たったか、などです。
- 入力した内容、画面の内容、ウインドウのタイトル、音声や映像を読み取ることはありません。
- 信号の確認は Mac 上で 1 秒に 1 回行い、Mac の外に出ることはありません。
- 通話で休憩が遅れることはあっても、なくなることはありません。初期設定では、保留によって延期できるのは合計 30 分までです。
読み取る信号
どの信号も、App Sandbox の中で許可を求めずに使える標準的な macOS の API またはシステム通知から得ています。信号ごとに小さな専用のコンポーネントが読み取り、どれもタイマーを直接変更することはできません。
- マイクが使用中
- API:
kAudioDevicePropertyDeviceIsRunningSomewhere(Core Audio) - 入力ストリームを持つすべてのオーディオデバイスに問い合わせます。答えは「はい」か「いいえ」だけです。スピーカーなど出力専用のデバイスは対象外なので、音楽を再生していても数えません。
- カメラが使用中
- API:
kCMIODevicePropertyDeviceIsRunningSomewhere(Core Media I/O) - カメラごとに「はい」か「いいえ」を得るだけです。映像のフレームは読み取りません。
- 最後の入力からの時間
- API:
CGEventSource.secondsSinceLastEventType - 最後のキー入力、クリック、マウス移動からの秒数です。どのキーか、どこをクリックしたかはこの呼び出しでは分かりません。
- 最前面のアプリ
- API:
NSWorkspace.frontmostApplication - アプリのバンドル ID と、Info.plist に記載された App Store のカテゴリです。アプリの切り替えやゲームに気づくために使います。ウインドウのタイトルは読み取りません。
- 通話アプリが起動中
- API:
NSWorkspace.runningApplications - 既知の通話アプリ(Zoom、Teams、FaceTime、Slack、Webex など)やウェブブラウザが起動しているかどうかです。見るのはバンドル ID だけです。
- フルスクリーン
- API:
CGWindowListCopyWindowInfoとCGDisplayBounds - 最前面のアプリのウインドウの位置と大きさを、各ディスプレイと比べます。ウインドウの名前や内容は読み取りません。
- ディスプレイのスリープ抑止
- API:
IOPMCopyAssertionsByProcess - 動画プレーヤーやスライドショーのように、ディスプレイをオンのままにするよう macOS に求めているプロセス(
PreventUserIdleDisplaySleep、NoDisplaySleepAssertion)を確認します。 - ロック、スリープ、スクリーンセーバー
- API:
com.apple.screenIsLocked、スクリーンセーバーの通知、NSWorkspaceのスリープ/スリープ解除の通知 - あなたが席を離れたことをタイマーに伝えます。ディスプレイがスリープした場合も同様です。
信号から通話を判断するまで
生の信号にはノイズがあります。音声入力でもマイクはオンになりますし、動画のプレビューでも一瞬ディスプレイのスリープが抑止されます。そのため、信号が一定時間続いて初めて保留(PausePace で「今は割り込まない」を意味する言葉)とみなします。
- ビデオ通話:カメラが 10 秒間動作している。
- 音声通話:マイクが 10 秒間動作していて、かつカメラがオンになっているか、通話アプリまたはウェブブラウザが起動している。ブラウザも対象なのは、ウェブ版の Google Meet や Teams がブラウザの中で動くためです。
- ビデオやスライドショー:最前面のアプリ(またはその補助プロセス)が 15 秒間ディスプレイのスリープを抑止していて、かつ画面いっぱいに表示されているか、30 秒間入力やクリックがない。caffeinate や Amphetamine のようなスリープ防止ユーティリティは対象外です。
- プレゼンテーションやゲーム:最前面のアプリがディスプレイ全体を占めていて、それが Keynote、PowerPoint、WPS Office、QuickTime Player、またはゲームカテゴリのアプリである。フルスクリーンのエディタやブラウザは保留になりません。一日中フルスクリーンで作業する人も多いからです。
マイクをミュートしていても使用中とみなされます。通話中はそのほうが都合がよいはずです。保留の種類(通話、ビデオ、プレゼンテーション)は、それぞれ設定でオフにできます。
タイミングの選び方
作業時間(初期設定は 20 分)が過ぎると休憩の時間になりますが、PausePace はすぐには表示しません。次のような自然なタイミングを待ちます。
- 保留が終わった直後(たとえば通話を切ったとき)
- 直近 3 秒以内にアプリを切り替えたとき
- 入力やクリックが 8 秒間止まったとき
そのタイミングで、休憩が始まる前に事前通知(初期設定は 20 秒)が理由とともに表示されます。たとえば「よいタイミング — 通話が終わりました」のように。保留中の時間を除いて 5 分以内に自然なタイミングが来なければ、そのまま事前通知を表示します。
通話が長引いたとき
保留によって休憩を延期できるのは合計 30 分までです。この時間は設定で変更できます。上限に達すると、通話が続いていても事前通知が表示され、カウントダウンも最後まで行うので、事前に気づくことができます。「やさしく」と「バランス」ではスヌーズできますが、「しっかり」ではスヌーズできません。
休憩を待っている間も作業時間はカウントされ続けます。会議で休憩が遅れることはあっても、休憩が消えることはありません。
席を離れたとき
画面のロック、スリープ、スクリーンセーバーは、すぐに離席とみなします。それ以外の場合、45 秒間入力がなくても、読み物をしているかもしれないと考えて作業時間のカウントを続けます。5 分間入力がなければ離席とみなします。離席中の時間は作業時間に加算されず、5 分間の離席は 1 回の休憩として数えます。保留中は、入力がないというだけで離席とはみなしません。通話中にじっと座っているのは休憩ではないからです。
休憩中に 3 秒間続けて入力があるとカウントダウンが一時停止し、5 秒間入力がなければ再開します。休憩として数えるのは、実際に休憩している時間だけです。
読み取らないもの、求めるアクセス
PausePace は、キー入力、画面の内容、ウインドウのタイトル、音声や映像を読み取りません。「マイク」「カメラ」「画面収録」「アクセシビリティ」へのアクセスを求めることもありません。そもそもアプリには音声入力やカメラ入力のためのサンドボックスエンタイトルメントがないため、macOS がそれらを許可することもありません。確認するには、インストール後に「システム設定」›「プライバシーとセキュリティ」を開いてください。それらの一覧に PausePace は表示されません。
表示される可能性があるシステムのダイアログは次の 3 つで、いずれもあなたが選んだ機能に関するものです。
- 通知:任意。休憩のお知らせ用です。
- カレンダー:予定前の休憩(Pro)をオンにした場合のみ。
- ローカルネットワーク:iPhone とペアリングするときのみ。それまで Mac はネットワーク上で接続を待ち受けません。
アプリにはアカウントもアクセス解析もありません。信号はメモリ上で使われ、そのまま破棄されます。ディスクに残るのはタイマーの状態と休憩の履歴だけで、これらはアプリ内で保存期間を短くしたりオフにしたりできます。
予定前の休憩(Pro)
次の休憩が、10 分以内に始まる「予定あり」のイベントに重なりそうな場合、作業時間の半分以上が過ぎていれば、PausePace はその直前に休憩を提案します。EventKit を通じて読み取るのは、各予定の開始・終了時刻、空き時間かどうか、そしてあなたが辞退したかどうかだけです。タイトル、メモ、場所、ほかの参加者は読み取らず、ディスクにも何も保存しません。終日の予定、キャンセルされた予定、「空き時間」の予定、辞退した予定は無視します。
正直にお伝えしておくべき点が 1 つあります。macOS では、アプリに与えられるのは「カレンダーへのフルアクセス」か「予定の追加のみ」のどちらかです。予定の時刻を読み取るにはフルアクセスが必要なため、システムのダイアログではそれを求めることになります。それでも PausePace が読み取るのは上記の時刻と空き状況だけで、何も保存しません。この機能をオフにすれば読み取りは止まり、「システム設定」›「プライバシーとセキュリティ」›「カレンダー」でアクセスを取り消すこともできます。
iPhone とのペアリング
iPhone アプリは Mac の状態をミラーでき、Apple Watch は iPhone から休憩の状態を受け取ります。Mac と iPhone はローカルネットワーク上で直接通信し、PausePace のサーバーは関与しません。
- Mac は Bonjour(
_pausepace._tcp)で自身を公開し、6 桁のコードを表示します。ペアリングの受け付けは、2 分たつか 5 回間違えると終了します。 - コードは TLS 1.2 PSK 接続の事前共有鍵(HKDF-SHA256)になるため、コードが違えばハンドシェイクは失敗します。
- その接続の中で、両方のデバイスが一時的な X25519 鍵交換を行います。Mac はランダムな 256 ビットの秘密鍵を送り、これは鍵交換とコードから導出した鍵を使って ChaCha20-Poly1305 で封印されます。ペアリングの通信を記録した人が後からコードを推測できたとしても、秘密鍵を復元することはできません。
- 秘密鍵は各デバイスのキーチェーンに「このデバイスのみ」として保存されるため、iCloud で同期されることはありません。以後の接続はすべて、この秘密鍵から導出した鍵による TLS で行います。
Mac が送るのは、休憩の状態(たとえば「通話の終了を待っています」)と 1 日の合計です。このページで説明した信号は送信しません。
制限事項
- 画面共有だけでは検知できません。macOS には、許可なしで使える公開された信号がないためです。マイクとカメラをオフにしたまま画面を共有している場合、PausePace は気づきません。それを調べるために非公開 API を使うこともしません。
- 通話は推測によって判断しています。マイクやカメラを通常とは違う形で使う通話は見逃すことがあります。また、ブラウザや通話アプリが起動している間に音声入力などの別の用途でマイクを使うと、通話のように見えることがあります。
- 一部の仮想カメラは、状態を正しく報告しないことがあります。
- フルスクリーンは位置と大きさだけで判定しています。最大化していても完全なフルスクリーンでないウインドウは一致せず、フルスクリーンの書類とフルスクリーンの動画は区別できません。
- ビデオの検知はプレーヤー次第です。ディスプレイのスリープを抑止するプレーヤーがほとんどですが、そうでないものもあります。
- 長い通話でも、いずれ休憩は来ます。延期の上限に達したら休憩を出す、という意図的な設計です。
- スマートタイミングは Mac で動作します。Mac と組み合わせずに iPhone だけで使う場合、PausePace はシンプルな休憩タイマーとなり、通話を検知できません。
よくある質問
PausePace は通話を聞いていますか?
いいえ。Core Audio に問い合わせるのは、入力デバイスが動作中かどうかという「はい/いいえ」の答えだけです。マイクの許可を持たず、入力デバイスを開くこともないので、何も聞くことはできません。
Zoom、Teams、Google Meet に対応していますか?
はい。カメラとマイクの信号で対応しています。Zoom、Teams、FaceTime、Slack、Webex、Discord などのアプリは、バンドル ID で識別します。Meet などのウェブ通話も、ブラウザが対象に含まれるため検知できます。
通話中に割り込んでくることはありますか?
保留による延期が上限(初期設定は 30 分)に達した場合だけです。その場合も先に事前通知が表示され、「やさしく」か「バランス」ならスヌーズできます。
Mac の外に送られるデータはありますか?
iPhone とペアリングした場合だけです。そのとき Mac は、休憩の状態と 1 日の合計を暗号化して、ローカルネットワーク経由で iPhone に送ります。このページで説明した信号は Mac の中にとどまります。