Zoom/Teams/Meet 対応のミュート用キーボードを作ってみた
オンラインミーティングでスムーズにミュートの切り換えができるよう、自作キーボードの練習も兼ねて専用のキーボードを作ってみました。筐体はダンボールで。
キーアサインカスタマイズ可能な既製品(例:SimPad Nano)もあったのでその後購入してみました。こちらなら組み立ては不要です。
使ったもの
- キーボード
- PC
- macOS 11
- キーカスタマイザー: Karabiner Elements
キーボードの組み立て
meishi2 keyboard ビルドガイド にとても詳しい手順がありますので、そちらを参考に組み立てます。
電子工作は苦手ですが問題なくできました。ありがたい!
ファームウェアのインストール
開発環境のセットアップ
こちらも手順に従ってセットアップします。
git clone https://github.com/qmk/qmk_firmware.git
cd qmk_firmware
git submodule update --init
./util/qmk_install.sh
補足
- qmk_install.sh を実行すると、Homebrew で必要なパッケージが色々インストールされます。
- meishi2 の手順ページには
git submodule update --init
がありませんが、これをしないと必要な submodule がダウンロードされず、ビルド時にtmk_core/protocol/lufa.mk:14: lib/lufa/LUFA/makefile: No such file or directory
というエラーになってしまいました。(変わったのかも)
デフォルトのファームウェアをインストール
USB ケーブルでキーボードを接続して、以下のコマンドを実行します。
make meishi2:default:avrdude
「reset your controller now....」と表示されたら、リセットボタンを押すと書き込みが開始します。
キーマップを変更する
「default」を元に「mute」という名前のキーマップを作成します。
cp -Rp keyboards/meishi2/keymaps/default keyboards/meishi2/keymaps/mute
keyboards/meishi2/keymaps/mute/keymap.c を編集します。Simple Keycodes を参考に、各キーに割り当てるキーコードを指定します。左から「Esc(キャンセル)」「Cmd+D(Google Meetのミュート)」「Shift+Cmd+A(Zoomのミュート)」「Space(ZoomのPPT)」としてみました。
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(KC_ESCAPE, LGUI(KC_D), SGUI(KC_A), KC_SPACE)
};
さきほどと同様に、インストールします。
make meishi2:mute:avrdude
Karabiner Elements でスクリプトを割り当て
単純なキーコードだけでは、以下の点で使いづらさがありました。
- 対象のアプリケーションにフォーカスがないと動作しない。
- アプリ毎にショートカットが違うので、間違って別の動作をおこなってしまう場合がある。
- アプリケーションごとにボタンを使い分ける必要がある。
そのため、osascript で動作する以下のようなスクリプトを作成して、キーが押されたときにこれが実行されるようにしました。Zoom, Teams, Meet の順にアプリケーションが起動しているかチェックし、フォーカスしてからミュートをおこないます。
例) mute.scpt
#!/usr/bin/env osascript -l JavaScript
ObjC.import('stdlib')
function getApplication(name) {
try {
const app = Application(name)
if (app.running()) {
return app
}
} catch (e) {}
}
function muteZoom(key) {
app = getApplication('zoom.us')
if (!app) {
return false
}
app.activate()
if (key) {
const se = Application('System Events')
delay(0.1)
se.keystroke(key, { using: ['command down', 'shift down'] })
}
return true
}
function muteTeams(key) {
app = getApplication('Teams')
if (!app) {
return false
}
app.activate()
if (key) {
const se = Application('System Events')
delay(0.1)
se.keystroke(key, { using: ['command down', 'shift down'] })
}
return true
}
function muteMeet(key) {
app = getApplication('Google Chrome')
if (!app) {
return false
}
let result = false
app.windows().forEach((window, windowIndex) => {
const tabIndex = window.tabs().findIndex(tab => tab.url().startsWith('https://meet.google.com/'))
if (tabIndex >= 0) {
app.activate()
window.activeTabIndex = tabIndex + 1
const se = Application('System Events')
se.processes['Google Chrome'].windows[windowIndex].actions['AXRaise'].perform()
if (key) {
delay(0.1)
se.keystroke(key, { using: ['command down'] })
}
result = true
}
})
return result
}
function run(args) {
const cmd = args[0]
let result
if (cmd == 'audio') {
result = muteZoom('a') || muteTeams('m') || muteMeet('d')
} else if (cmd == 'video') {
result = muteZoom('v') || muteTeams('o') || muteMeet('e')
} else {
result = muteZoom() || muteTeams() || muteMeet()
}
$.exit(result ? 0 : 1)
}
ファームウェアで割り当てるキーは何でも良いので、以下のようにテンキーの 1〜3 とスペースを割り当てました。
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(KC_KP_1, KC_KP_2, KC_KP_3, KC_SPACE)
};
Karabiner Elements の Simple modifications 設定で、各キーにスクリプトを割り当てます。「Target device」には「meishi2 (Biacco42)」を指定します。他のキーボードには影響しません。
↑のように shell_command への割り当ては GUI からは設定できないので、設定ファイル (.config/karabiner/karabiner.json) に直接以下のように記述します。(GUI で適当に割り当ててから修正すると間違えにくいと思います。)
{
"profiles": [
{
"devices": [
{
"disable_built_in_keyboard_if_exists": false,
"fn_function_keys": [],
"identifiers": {
"is_keyboard": true,
"is_pointing_device": false,
"product_id": 3,
"vendor_id": 48194
},
"ignore": false,
"manipulate_caps_lock_led": false,
"simple_modifications": [
{
"from": {
"key_code": "keypad_1"
},
"to": [
{
"shell_command": "~/bin/mute.scpt audio"
}
]
},
{
"from": {
"key_code": "keypad_2"
},
"to": [
{
"shell_command": "~/bin/mute.scpt video"
}
]
},
{
"from": {
"key_code": "keypad_3"
},
"to": [
{
"shell_command": "~/bin/mute.scpt"
}
]
}
]
}
]
}
]
}
プログラムからのキーボードを操作するには、macOS のセキュリティ管理上 Accessibility の権限が必要になります。そのため、System Preferences > Security&Privacy > Privacy の "Accessibility" に "karabiner_console_user_server" を追加しておきます。(自分の場合は適当に実行して何度か失敗していたら一覧に追加されたので、チェックを入れました。)
スクリプトを書き換えればなんでもできるようになりますね!(これなら専用ハードウェアも別にいらなかった気はします。)
お金あったら Stream Deck 欲しいです。
Discussion