動機
ZoomやMicrosoft Teamsでのオンランミーティングが仕事や生活の一部になりました。操作にはずいぶん慣れましたが、とくにマイクのミュート、アンミュートは頻繁に使う機能です。話の隙間を狙ってアンミュートしようと、カーソルをマイクコントロールアイコンの上にのせてタイミングを待つマウスの上の手がつらい。
ボタン一発でマイクやカメラのOn-Offができるものがあればいいのに。
あればいい、なら作ってみたら?ということで引き出しに入りっぱなしだったAdafruit Circuit Playground Express(CPX)を引っ張り出して活躍してもらうことにしました。
しくみ
CPXからキーボードショートカットをパソコンに送出するという仕掛けです。今の状態を表すために、Neopixelがついたり消えたりするようにもしました。(On-Offどちらも同じショートカットでトグルさせているだけなので、NeopixelのOn-Off状態と合わせるために、最初にパソコン側でマイクとカメラをOffにしてから使い始めるという、”なんちゃって仕様”です。CPXをキーボードとして使っているのだけなので、パソコン側の今の状態を引き出すことはできないのです。できるともっといいのですが。今回は今すぐほしい、を優先しました。)
windowsとmacとではショートカットキーの組み合わせが違うので、CPXのスライドスイッチでどちらで使うのかを切り替えることができるようにしました。
Windowsでのショートカットキー
- microphone: Alt + A
- camera: Alt + V
Macでのショートカットキー
- microphone: Command + Shift + A
- camera: Command + Shift + V
見た目はこんな感じ
左がマイク用のAボタン、右がカメラ用のBボタンです。真ん中下にあるのがスライドスイッチで、この個体ではWindows用、Mac用を切り替えられるようにしてあります。(もう一つの個体ではZoomとMicrosoft Teamsとを切り替えられるようにしました)
Neopixelで今の状態をお知らせ。左(赤)がマイク、右(青)がカメラ。点灯がunmute (on)を表す。

動作の様子
code
Circuitpythonで書きました。Neopixelとbuttonの部分がうまく動くのを確認した後、スライドスイッチの部分を書き足そうと、adafruit_circuitplayground
libを読み込んでエラー。少々混乱しましたが、何とか書けました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import board import time import usb_hid import adafruit_fancyled.adafruit_fancyled as fancy from digitalio import DigitalInOut, Direction, Pull from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode from adafruit_circuitplayground import cp # cp.switch: left=True, right=False # left: windows # right: mac # Zoom/Windows # toggle microphone: Alt + A # toggle camera: Alt + V # Zoom/Mac # toggle microphone: Cmd + Shift + A # toggle camera: Cmd + Shift + V # Set up a keyboard device. kbd = Keyboard(usb_hid.devices) # colors mic_color = fancy.CHSV( 0 , 1.0 , 0.01 ).pack() # hue, saturation, value cam_color = fancy.CHSV( 0.6 , 1.0 , 0.01 ).pack() # hue, saturation, value # neopixel on cpx npx = cp.pixels # neopixel hue demo i = 0 while i < 1 : for pp in range ( 10 ): h = (pp * ( 1.0 / 10 ) + i) % 1.0 hsvcolor = fancy.CHSV(h, 1.0 , 0.01 ) # hue, saturation, value npx[pp] = hsvcolor.pack() npx.show() time.sleep( 0.03 ) i = i + 0.1 # off all npx.fill(( 0 , 0 , 0 )) npx.show() # previous status mic_status = False cam_status = False def neopix_control(idxs, rgb): for i in idxs: npx[i] = rgb # set with CHSV().pack(), brigntness included npx.show() while True : # when button pressed if cp.button_a: if cp.switch: # True=Left=Windows kbd.send(Keycode.ALT, Keycode.A) # --- windows else : # False=Right=Mac kbd.send(Keycode.COMMAND, Keycode.SHIFT, Keycode.A) # --- mac if mic_status: # was on. turn it off neopix_control([ 1 , 2 , 3 ], ( 0 , 0 , 0 )) else : # was off. turn it on neopix_control([ 1 , 2 , 3 ], mic_color) # toggle status mic_status = not mic_status while cp.button_a: pass if cp.button_b: if cp.switch: # True=Left=Windows kbd.send(Keycode.ALT, Keycode.V) # --- windows else : # False=Right=Mac kbd.send(Keycode.COMMAND, Keycode.SHIFT, Keycode.V) # --- mac if cam_status: # was on. turn it off neopix_control([ 6 , 7 , 8 ], ( 0 , 0 , 0 )) else : # was off. turn it on neopix_control([ 6 , 7 , 8 ], cam_color) # toggle status cam_status = not cam_status while cp.button_b: pass |
使ってみて
便利。
buttonがdebounceで複数押しになってしまうことがあるので、debounce対策をコードにいれるべき。
CPXのpinoutはいくつかがtouch sensorとしても使えるので、二つのボタンにとどまらず、もっとショートカットをアサインしてさらに便利にしたいと思っています。スクリーンシェアの切り替えや、ホスト以外をミュートなど、キーボードショートカットのあるものならなんでもできるハズ。家族にも聞いて必要なものを組み込んで使ってみます。
Zoom, Teams切り替えバージョン(Windows専用)も作って使っています。
