この記事はリンクアンドモチベーションAdventCalendar2024の22日目です。
はじめに
リンクアンドモチベーションでモチベーションクラウドの開発をしているymk25です。
さて、世界中のサンタクロースが積載量の多いトナカイを奪い合い、クリスマスケーキが店頭オーディションに向けておめかしに気合を入れはじめるこの季節。
ふと、気づいてしまいました。
「今年、何も作っていないのでは?」
何か作ろう!
エンジニアたるもの、思うがままに何かを創出してはニヤニヤしてなんぼ
私も2024年滑り込みでニヤニヤしたい…
ところで、我が家には3匹の猫がいるのですが、
ビデオ通話中、デスクに飛び乗り目の前を横切っていくことがしばしば。
そして稀有なことに、私のカメラが猫にジャックされることを喜んでくれる素敵な仲間がいます。
そうだ、猫がカメラに映ったら、コメントで即座に教えてあげよう!
ビデオ通話中に猫がカメラに映ったら自動コメントで教えてあげる方法を考える
作りたいものは決まりましたが、私には2時間しか時間がありません。
なぜ2時間なのか、それは私が誰かのサンタクロースだからかもしれないし、年内に消化したい積みゲーが待機列を作っているからなのかもしれません。
とにかく2時間で作るしかない。
要件(もとい願望)はこちら
- ビデオ通話はMeetを使用
- 猫だけを検知してほしい
- Chrome拡張機能って作ったことないな、作ってみたいな
ということで、助っ人をお呼びしました。
ありがとうChatGPT、草木も眠る時間にこんな要件で呼び出しても怒らないのは君だけです。
さて!心強いパートナーが参戦したことで、開発に移っていきましょう!
作ってみよう!
ChatGPT先生に全体の流れと開発手順を教えてもらい、粛々と開発を進めていきました。
猫を事前学習済みのcoco-ssdモデルを使い、TensorFlow.jsで猫を検出するそうです。
そしてなんやかんや紆余曲折しながら…
最初のChatGPT先生の教えから5回くらいの手直しで完成です。
本当に2時間くらいで開発完了しました。
最終的なディレクトリ構成と主要なファイルの中身はこちら
├── background.js
├── dist
├── manifest.json
├── node_modules
├── package-lock.json
├── package.json
├── popup.html
├── popup.js
├── src
│ └── content.js
└── webpack.config.js
{
"manifest_version": 3,
"name": "猫検出拡張機能",
"version": "1.0",
"content_scripts": [
{
"matches": ["https://meet.google.com/*"],
"js": ["dist/content.bundle.js"]
}
]
}
import * as cocoSsd from '@tensorflow-models/coco-ssd';
import '@tensorflow/tfjs';
// カメラ映像を取得する関数
async function setupCamera() {
const video = document.createElement('video'); // <video>要素を作成
video.autoplay = true; // 自動再生を有効にする
video.playsInline = true; // インライン再生を有効にする
video.width = 640; // 必要に応じて幅を設定
video.height = 480;
try {
// カメラ映像を取得
const stream = await navigator.mediaDevices.getUserMedia({
video: true, // ビデオストリームを要求
audio: false // 音声ストリームは不要
});
video.srcObject = stream; // ストリームを<video>に設定
document.body.appendChild(video); // 確認のため<body>に追加
return video;
} catch (err) {
console.error("カメラ映像の取得に失敗しました:", err);
throw err;
}
}
// TensorFlow.jsで猫を検出する関数
async function detectCat() {
const video = await setupCamera(); // カメラ映像をセットアップ
const model = await cocoSsd.load(); // coco-ssdモデルをロード
console.log("モデルがロードされました");
// 1秒ごとに映像を解析
setInterval(async () => {
const predictions = await model.detect(video);
predictions.forEach(prediction => {
if (prediction.class === 'cat') {
console.log("猫が検出されました!");
sendChatMessage();
}
});
}, 1000); // 1秒間隔で処理
}
// Meetのチャット欄にメッセージを送信
function sendChatMessage() {
const chatInput = document.querySelector('[aria-label="参加者全員にメッセージを送信"]');
if (chatInput) {
chatInput.value = "猫が通り過ぎました";
chatInput.dispatchEvent(new Event('input', { bubbles: true }));
const sendButton = document.querySelector('button[aria-label="参加者全員にメッセージを送信"]');
sendButton.click();
}
}
detectCat();
※コードはほぼChatGPTに書いてもらっています
紆余曲折ポイント
最初に提案されたコードでの動作確認はうまくいきませんでした。
Meet内のvideo要素を取得しようとしていましたが、そのような要素は存在しません。
const video = document.querySelector('video'); // Meetのカメラ映像を取得
カメラ映像の取得方法は自分で検索し、getUserMedia()メソッドを使用して修正するよう指示することで、問題解決しました。
他にもテキスト入力や送信ボタン要素の取得がうまくいかなかったので、DevToolsを使ってせっせと自分で探索する必要があります。
動かしてみよう!
Chrome拡張機能のデベロッパーモードをONにして、拡張機能を読み込む。
エラーはない。学習モデルもカメラも読み込めているようだ、よし。
そして、いざ、猫をカメラの前へ…
見事、猫がカメラ前にいる時にだけコメントが自動投稿されるようになりました!!!!!
1秒ごとに「猫が通り過ぎました」というコメントが続々流れていきます。
我が家の2/3猫で成功したので検証成功です(1/3は捕獲に失敗しました)
これでいち早く猫の存在を伝えることができるので、猫派のモチベーションを高め、来年のプロジェクトはきっと大成功を収めることでしょう。
おわり
AI時代、こんなにもスピーディに何かを作って楽しむことができるようになりました。
ただ、100%動く完全体が出てくるわけではない現状、こうじゃないかな〜と勘を働かせてAIに提案するための知識の下積みは必要だなと感じました。
これからも良きパートナーとして一緒に、役立つものも、そうでないものも、たくさん作っていこうと思います。
ちなみにこの開発で一番大変だったことは、猫をカメラに映すことでした。
どうぞご参考までに。