#1 で「こう解く」と書いたことを、実際に作った。
想定通りに動いたものもある。
最初の30分で詰まったものもある。
その記録。
前回は6つの問題を整理した。今回はそれを実際にコードにした。
作ってみてわかったのは、「書くより動かす方がずっと難しい」という当たり前のことだった。
— #1 計画編 で整理した6つの問題
最終的に6つのファイルに分けた。それぞれが #1 の「Problem」に対応している。
meet_bot.py — Google Meet / Zoom に Bot として参加する
transcriber.py — Whisper API で音声を文字に変換する
speaker.py — 誰が話しているかを特定する
minutes_maker.py — 3段階のAI処理で議事録を作る
notifier.py — HTMLメールで送信する
calendar_watcher.py — Google Calendar から会議URLを自動取得する
Bot が会議に参加する部分が、最初の難所だった
Playwright(ブラウザを自動操作するツール)でGoogle Meetを開き、参加ボタンをクリックする。 書くと1行だが、実際にやると最初から詰まった。
参加ボタンが「押せない状態」で表示されていた。 Googleアカウントにログインしていないブラウザでは、ボタンが有効にならない仕組みになっていたからだ。
解決策は、すでにログインしているChromeのCookieを引き継ぐこと。 ChromeのCookieファイルを一時フォルダにコピーして、そこからブラウザを起動する。 これでログイン済みの状態を再現できた。
「Quill 📝 が参加しました」と表示され、チャットに 「📝 Quill が記録します。停止したい方はホストにお伝えください。」 と自動で送られることを確認した。
文字起こしのコストは、最初から記録しておく
OpenAIのWhisper APIは、音声の長さに応じて課金される。 1分あたり約0.6円。小さい金額だが、ユーザーが増えれば増えるほど積み上がっていく。
だから最初からコストを自動で記録する仕組みを入れた。 会議のたびに「今回いくらかかったか」「今月合計いくらか」をログに残す。 月の合計が一定額を超えたら、切替の検討を促すアラートも出るようにした。
テスト実行のログ:
文字起こしコスト: $0.0028(今月合計: $0.02)
30秒のテストで約0.4円。把握できている。
AIに3回聞く、という構造が効いた
文字起こしのテキストをそのままAIに渡して「議事録にして」と頼んでも、うまくいかない。 長い文章から必要な情報を一度に全部抜き出すのは、AIが苦手とする処理だ。
そこで3段階に分けた。
まず「決定事項・ToDo・保留事項をJSONで抜き出して」と頼む。
次に、担当者や期限が空のToDoだけを対象に「文章から補完して」と頼む。
最後に「全体を200〜400字で要約して」と頼む。
1回で全部やらせるより、小さい仕事を順番に渡す方が精度が上がった。
決定事項・ToDo(担当者・期限付き)・保留事項・サマリーの4セクションが自動で生成される。 内容のない会議(テスト用の無音に近い音声)でも、「判断できる情報がない」と正直に返してくれた。
話者の特定は、まだ完全ではない
「誰がこの発言をしたか」を自動で判別する機能を実装した。 ただし、Whisper APIは話者を区別する機能を持っていない。 返ってくるのは「テキスト」と「何秒から何秒の発言か」という時間情報だけだ。
今の実装では、発言と発言の間が2秒以上空いたら話者が変わったと推定する。 そこに参加者リストの名前を順番に当てはめていく。精度は高くない。
改善策として「声紋キャッシュ」を入れた。 初回だけ「この声は田中さんで合ってますか?」と確認してもらい、 2回目以降は確認なしで同じ人の声を割り当てる。少しずつ精度が上がっていく設計にしている。
動く。ただし正確ではない。これは「動く状態で出して、使いながら直す」対象として残す。
会議終了から2秒でメールが届いた
会議が終わった瞬間に処理を始め、できたらすぐ送る。この流れを実装した。
メールはHTMLで送るようにした。テキストだと読みにくいし、 受け取った側が「ちゃんとしたサービスから来た」と感じる見た目にしたかった。 ダークヘッダー・ゴールドのアクセント・セクション区切り—— LPのデザインと統一感を出した。
テスト実行のログ:
✅ 送信完了(会議終了から 2.1秒後)
3分以内どころか、2秒だった。
「録音されている」ことを、見えるようにする
Botが会議に入った瞬間、チャット欄に通知を送る。 「📝 Quill が記録します。停止したい方はホストにお伝えください。」
これは機能ではなく、態度の設計だ。 黙って録音しているBotと、入った瞬間に名乗るBotでは、受け取られ方がまったく違う。 技術的には1行のコードだが、プロダクトとしては一番大事な部分かもしれない。
チャット通知は動作確認済み。 ホスト向けのワンクリック退出ボタンは、次回のUIとして追加予定。
#1 で「たぶんこの計画は半分くらい裏切られる」と書いた。実際どうだったか。
想定通りだったもの:
文字起こしの精度・3段階プロンプトの効果・メール送信の速さ
想定外だったもの:
Googleアカウントのログイン問題・Playwrightのボタン操作の細かい挙動・
Whisper APIのレスポンス形式(辞書型ではなくPydanticモデルだった)
まだ動いていないもの:
Google Calendar の自動連携(コードは書いたが認証設定が必要)・
Zoom の参加(Google Meet は動くが Zoom はまだテスト中)
計画編を書いた翌日に、実際に動くものができた。
Google Meet のURLを渡すと、Botが参加して、会議が終わると議事録がメールで届く。
コードの行数は約 700 行。GitHubのプライベートリポジトリに保存してある。
次にやること:
Zoom 参加のテスト・Google Calendar 自動連携の認証設定・話者特定の精度改善
それが終わったら、実際の会議で使ってみる。
使ってみてはじめて、本当に必要なものがわかる。