🔇

他のタブを開いていてもショートカットで Google Meet のマイクをミュートできる Chrome 拡張を作った

2024/12/03に公開

Google Meet で picture-in-picture が提供されましたね[1]

Use picture-in-picture in a Google Meet meeting

他のタブの議事録とかを開きつつ参加者の反応を見たりと便利に使っていますが、そのままショートカットキーでマイクのミュート/ミュート解除ができたらさらに便利そうだと思い、Chrome 拡張を作ってみました

https://chromewebstore.google.com/detail/google-meet-global-shortc/jdkiffhdknhmflombljefcdcolcbbihb

https://github.com/mkobayashime/google-meet-global-shortcuts/tree/main

使い方

Chrome Web Store からインストールしてください
(インストール時既に開かれている Google Meet のタブはリロードが必要です)

以下のショートカットキーが利用可能です
※変更可能、手順は後述します

ショートカットキー 用途
Ctrl+Shift+D
macOS では Option+Shift+D
マイクのミュート/ミュート解除
Ctrl+Shift+E
macOS では Option+Shift+E
カメラのオンオフ

ショートカットキーの変更方法

Chrome の拡張機能設定ページ (chrome://extensions) に行き、画面左のメニューバーから キーボードショートカット をクリックしてください

Google Meet - Global Shortcuts の欄を探し、お好みのキーに変更してください

Toggle Microphone がマイク、Toggle Camera がカメラのオンオフです

実装

フレームワーク

勤務先の別事業部が直近 Chrome 拡張を開発/提供開始しており、WXT というブラウザ拡張のフレームワークが結構便利という話を雑談で聞いていたので採用しました

今回はバンドルするスクリプトも使用する API も多くない単純な拡張なので特に苦労することもなく終わってしまい評価が難しいですが、HMR 効いたりと開発者体験はなかなか良かったです

もっと実務的な Chrome 拡張を開発する上での苦労などに興味のある方は同僚の記事をどうぞ

https://hilinker.hatenablog.com/entry/2024/11/29/151320

Commands API

WebExtensions API にはショートカットキーを実装するための commands[2] という API があり、これを利用したショートカットには以下のような特徴があります

  • ユーザーがキーバインドを自由にカスタムできる
    • UI もブラウザが用意してくれるためお手軽
  • ブラウザウィンドウがアクティブでさえあれば、アクティブなタブに関わらず効くショートカットを定義できる
    • ページ内で実行される通常のスクリプトや content script で keydown イベントなどを利用して実装した場合は、当然ながらそのタブがアクティブである場合にしか効かない

今回は Meet のタブ以外を開いているときにも効くことが肝心であるため、Commands がうってつけでした

commands.onCommand.addListener は content script からは利用できないため、まずは background script (service worker) で command event を受け取り、Meet のタブを探して tabs.sendMessage で転送し、Meet のタブで動いている content script でそれを受け取る流れとしました

Content script でのページ上の操作

Content script で実際にマイクのミュートなどページ上の操作を行うには Element.querySelector などでボタンを探して HTMLElement.click する方法がありますが、Google の製品群はスタイルなどの指定にランダム生成されたクラス名が使われており、data-test-id などもなく、操作すべき要素を安定して探索するのが難しいことが多いです

以下のように aria-label を用いれば一応可能ではありますが、Google Meet は多言語対応のため表示言語が変わると aria-label も変わってしまい、全言語分をクエリに列挙するのは大変です

document.querySelector('button[aria-label="Turn off microphone"]');

そこで今回は Google Meet がデフォルトで持っている Ctrl+D/Ctrl+E といったショートカットキーを活用し、ユーザーが Ctrl+D をタイプした場合に発生する KeyboardEvent を模擬的に発火させることにしました
dev tools で keydown / keypress といったイベントの listeners を1つずつ消して検証したところ、当該ショートカットは documentkeydown event を listen して実装されていることがわかったため、模擬的な発火の実装は以下のようになりました

// マイクのミュート/ミュート解除コマンドが流れてきた場合
document.dispatchEvent(
  new KeyboardEvent("keydown", { ctrlKey: true, key: "d" }),
);

EventTarget.dispatchEvent はこのようにブラウザ拡張の content scripts や userscripts などでページ上の操作を再現したい場合たまに役立つので、頭の片隅に置かれていると良さそうです

脚注
  1. Picture-in-picture in Google Meet will now open automatically when switching tabs
    Monday, August 26, 2024
    ↩︎

  2. commands - Mozilla | MDN ↩︎

Discussion