こんにちは、皆さんも相席食堂の ちょっと待てぃ!!ボタンで動画を止めたいって思うことありますよね?
こんな感じのものを作ってみました。動画みてね☆
ちょっと待てぃ!! ボタンを実装したので自分の発言にちょっと待てぃ!! してみた
— 菅原のびすけ (プロトアウト9期募集中) (@n0bisuke) November 2, 2023
BluetoothキーボードとChrome拡張機能のセットです。#プログラミングの虎 #相席食堂 #iotlt #m5stack pic.twitter.com/7ooLvXt9nU
祝(?)Chromeのストアにも公開しました!
ということでIoTLTアドベントカレンダー1日目ですね!今年もやっていきましょう〜
有名TV番組、相席食堂のアレをやりたい
相席食堂はお笑い芸人の千鳥の二人が事前収録の動画(VTR)を見ながら、 気になる点があれば手元の「ちょっと待てぃ!!」ボタンを押してVTRを止め、ツッコミを入れるといった番組です。
参考: https://ja.wikipedia.org/wiki/%E7%9B%B8%E5%B8%AD%E9%A3%9F%E5%A0%82
引用: Google検索
これやりたくなりますよね。作ってみました(冒頭の動画↑)。
ガシャポン品ちょっと待てぃ!!ボタンを改造してキーボード化
調べると既製品として、ちょっと待てぃ!!ボタンのおもちゃが発売されていた模様でした。
このおもちゃは音が出るだけなので、これを 改造してキーボード化してPCで再生している動画を止めてみようと思います。
動画編集をする人だと馴染みがあると思いますが、YouTubeや動画再生ツールはスペースキーで停止・再生が出来ます。なのでボタンを押すとスペースキーが発火されるキーボードデバイス化をすればそれっぽい挙動になります。
ステップ1. ちょっと待てぃ!!ボタンの解剖
(製造停止しているため)中古購入したちょっと待てぃ!!ボタンを解剖して信号を取り出せないか検討します。
開けてみると、中の導電性の素材がボタンを押されて接触 -> 通電して「ちょっと待てぃ!!」の音が出るといったものみたいです。
最初は圧力センサなどを入れられないかなど思ってましたが、 @kitazaki さんに相談したところ、タクトスイッチと同じですねと言われて確かにと思ったので、タクトスイッチの要領で信号を取ってみました。
引用元: デバイスプラスさん https://deviceplus.jp/arduino/arduino_f06/
プルダウン抵抗を挟んで信号を取得することができました。
検証時にはobnizを利用
一旦これでボタンを押したらマイコンボード側で信号を受け取ることができました。
ステップ2. 自作キーボード
信号を受け取ることができたので、次はPCにスペースキーとして送るためのキーボード化です。
自作キーボードを作るにあたってはM5Atom Liteを利用しました。
ESP32-BLE-Keyboardというライブラリを使ってBluetoothキーボードとしてPCに認識させます。
M5系は先人が記事書いてくれてる率が高くて助かりますね。
参考: ラズパイの実さんの記事 https://knt60345blog.com/blekeyboard1/
ちなみにエンターキーにする場合はbleKeyboard.write(KEY_RETURN);
とするのですが、KEY_SPACEみたいなものはなくて、通常にスペースを送る感じの実装でした。ここちょっと悩んだ苦笑
- ❌
bleKeyboard.write(KEY_SPACE);
- ⭕️
bleKeyboard.print(" ");
こんな感じで信号をみて押下されたかどうか検知 & スペースキーの送信です。
//ちょっと待てぃが押下されたかどうか 抜粋
if(digitalRead(IN_SW) == LOW){
M5.dis.drawpix(0, dispColor(0, 0, 255));
}else{
M5.dis.drawpix(0, dispColor(20, 20, 20));
bleKeyboard.print(" "); //スペースキー
delay(chotMatePress_ms); //連続で押されないように少しウェイトさせる
}
コード全て
#include "M5Atom.h"
#include <BleKeyboard.h> // https://github.com/T-vK/ESP32-BLE-Keyboard
BleKeyboard bleKeyboard("CHOTO MATEI KB"); //デバイス名
const int longPress_ms = 300; // 長押し判定時間(ms)
const int chotMatePress_ms = 1000;
#define IN_SW 25
CRGB dispColor(uint8_t r, uint8_t g, uint8_t b) {
return (CRGB)((r << 16) | (g << 8) | b);
}
void setup() {
M5.begin(true, false, true);
M5.dis.drawpix(0, 0x000000); // LED OFF
pinMode(IN_SW, INPUT); //ちょっと待てぃの信号を受ける
Serial.begin(115200);
Serial.println("BLEキーボードアプリ開始");
bleKeyboard.begin();
}
void loop() {
M5.update();
// BLE接続中かどうか
if(bleKeyboard.isConnected()){
// ちょっと待てぃ!!ボタンが押下されているか
if(digitalRead(IN_SW) == LOW){
M5.dis.drawpix(0, dispColor(0, 0, 255));
}else{
M5.dis.drawpix(0, dispColor(20, 20, 20));
bleKeyboard.print(" "); //スペースキー
delay(chotMatePress_ms);
}
// ATOMのボタン側もデバッグ用で
if(M5.Btn.wasPressed()){
// M5ATOMのボタンが押されたら一定時間待つ
delay(longPress_ms);
// // キーが押されたままだったら長押しと判定
if(M5.Btn.read() == true){
// 長押し時の処理
M5.dis.drawpix(0, 0x00f0f0); // LED MAGENTA
Serial.println(" 長押し時は、Returnキー押下 を送信 ");
// bleKeyboard.write(KEY_RETURN);
bleKeyboard.print(" "); //スペースキー
delay(100);
// キーがリリースされていたら短押しと判定
}else{
// 短押し時の処理
M5.dis.drawpix(0, 0xf00000); // LED GREEN
Serial.println(" 短押し時は、文字列 Hello World を送信 ");
// bleKeyboard.print(" Hello World ");
bleKeyboard.print(" "); //スペースキー
delay(100);
}
}
// BLE接続であることを、ATOMのLED(青)を知らせる
M5.dis.drawpix(0, 0x0000f0); // LED BLUE
}else{
// BLE未接続であることを、ATOMのLED(赤)を知らせる
M5.dis.drawpix(0, 0x00f000); // LED RED
}
delay(10);
}
ちなみんPlatformIOでやってますが設定はこんなでした。
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
lib_deps =
m5stack/M5Atom@^0.1.1
fastled/FastLED@^3.6.0
M5Atom
t-vk/ESP32 BLE Keyboard@^0.3.2
monitor_speed = 115200
最後に銅線を内部に通して一旦完成です。一旦。。。
ちなみに、銅線は千石電商さんでこういうのを購入して利用してます。半田付けをした箇所だけ表面のフィルムが溶けて通電するけど他の箇所は絶縁された状態を保てるとのことで今回みたいに接触可能性がある場所に仕込むにはちょうどよかったです。
https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-04KM
ここで気付く。「ちょっと待てぃ!!」感が足りない! - Chrome拡張開発
ここまでで一旦実装できたのですが、 使ってみて思ったのは、圧倒的「ちょっと待てぃ!!」感のなさでした。
動画を止めるだけではなく、エフェクトとしてちょっと待てぃ!!が出ないと満足できなかったんですね。
ということで、YouTube用にChromeエクステンションを作ることにして、YouTube画面でスペースキーが押されたらちょっと待てぃ!!の画像が出るような仕組みを作りました。
ちょっと待てぃ!!素材
ちょっと待てぃ!!の画像素材はニコニ・コモンズに自作して公開されてる方( https://twitter.com/oyu_bgm さん)がいてこれを使わせてもらいました。
YouTubeで画像レイヤーを変える
YouTubeのプレイヤーエリアにはytd-playerというidが振られている模様でした。
ほぼChatGPTに書いてもらいましたが、こんな感じでプレイヤーレイヤーの上に画像レイヤーを作って表示される処理を作りました。
function ytCoverChange(){
const playerContainer = document.getElementById('ytd-player'); //プレイヤー部分
const imgLayer = document.getElementById('my-yt-cover');
console.log(imgLayer);
if (playerContainer) {
if(imgLayer){
imgLayer.remove();
}else{
// 新しい画像要素を作成
const imgLayer = document.createElement('img');
imgLayer.src = chrome.runtime.getURL('./images/choto_matei_text.png');
imgLayer.style.position = 'absolute'; // 位置を絶対位置にする
imgLayer.style.top = '0'; // トップに配置
imgLayer.style.left = '0'; // 左に配置
imgLayer.style.width = '100%'; // コンテナの幅に合わせる
imgLayer.style.height = '100%'; // コンテナの高さに合わせる
imgLayer.style.zIndex = '1000'; // 必要に応じてz-indexを高めることで他の要素の上に表示させる
imgLayer.id = 'my-yt-cover';
// 画像レイヤーをプレイヤーコンテナの最初の子として追加
playerContainer.insertBefore(imgLayer, playerContainer.firstChild);
}
}
}
スペースキーが効かない問題 - 既存ショートカットの排除
先ほど書いた関数をスペースキーを押したイベントに紐付けて発火させれば良いのですが、スペースキーはすでにYouTube側で何か処理がされていて、 スペースキーだけうまくイベント取得が出来ない問題が発生しました。
なんとかして既存のショートカットキーを無効化できないか?を調べていたところ、 YouTubeのショートカットキーを無効化する拡張機能を作って公開している人が...!
たぶん同じようなことをしたかったのかなと思います。
これを使いながら開発を一旦行いました。
スペースキーを押すとスクロールしてしまう問題
これでスペースキーを押すとちょっと待てぃが表示されていい感じだったのですが、
ただ今度はスペースを押すと下にスクロールしてしまいました。当然と言えば当然ですね。YouTube側はその辺を元々制御するようなスペースキー実装をしていたと思うのですがそれを無効化しちゃってるので当然です。
以下の質問を見つけて
event.preventDefault()
で上手いこといけました。
集合知ありがたや。。
せっかくなのでストアに公開
Chromeのストアにも公開しました!
最新版では、こちらのコードを取り入れて単体の拡張機能だけでちょっと待てぃが表示されるようになっています。
仕上げ: 箱に詰める
最後に、見栄えを考えて箱に詰めます。
配線はちょっと待てぃボタンの下側から出ているので箱の上にボタンを置いて、箱の中に配線を隠す形にしました。
ボタンのスピーカーが下側にあるため絶妙に音が籠る感じがしたので、 内蔵スピーカーから線を引き出して外部スピーカーに接続しました。
という感じで冒頭の動画のようなボタンキーボード&拡張機能が完成しました。
プロトぺディアにもまとめてあります。
大変だったところ
ちょっと待てぃ!!ボタンが入手できない
これはM5Stackのユーザー会でLTした時のオチ的な感じだったのですが、実装だとハンダ付けがしんどい。。みたいな話題はありつつ、ちょっと待てぃ!!ボタンの入手が大変でした。最終的にメルカリで入手しましたが、 ガシャポンが初めてすぎて、どこかにあるのか,,, 秋葉原散策したらあるのか... と無駄に時間がかかってしまいました。ググっても出てこないしツイッターの情報は古いしでなかなか難しいですね。
あと製造終了しているというのもあり、断線とかしてミスったときに買い増すのもちょっと面倒だったりするので冒険しづらさもありました。
USBキーボード化しようとして沼る
USBキーボードとして使いたかったのですが、USBキーボード化するとATOM Liteが2回目以降にキーボードとして認識されてしまって書き込みがうまくいかず、デバッグがかなりやりにくいという状況になりました。
ただ、IoTLTで話をしたら有識者の方からこんな回答が!泣
ファームつくるときにキーボードとして動き出すまでにウェイトをかけるようにつくるとか、GPIO監視してモードを分けるようにすると便利。
— nanbuwks (@nanbuwks) October 24, 2023
どうにもならなければ強制的にハードウェア的にBootモードのGPIOを下げてリセットして Download Ready にする。(早口) #IoTLT
なるほどっすなぁ。キーボードとして動き出す前にウェイトをかける... 言われてみれば確かにだけどそのとき思いつかなかったので目から鱗。
終わりに
という感じで、ちょっと待てぃをしたいだけだったけどChrome拡張機能を作ったりキーボード作ったりと色々勉強になることが多かったです。
現状ハンダづけして線を引き出してた部分のハンダが剥がれてしまって再起不能状態で転がってるので本体改造無しでやれる方法を少し探っています。
皆さんも「ちょっと待てぃ!!」やってみましょう。
そして、僕はいまだに相席食堂は見たことありません。
カレンダー明日は@kitazakiさんですね!お楽しみに〜〜