2026.05.06 開発ログ

計画通りには進まなかった
— Quill 開発ログ #2:実装編

#1 で「こう解く」と書いたことを、実際に作った。
想定通りに動いたものもある。
最初の30分で詰まったものもある。

その記録。

← Blog に戻る 📝 実際に動いてる様子を見る — インタラクティブデモ quill-static.pages.dev →

前回は6つの問題を整理した。今回はそれを実際にコードにした。
作ってみてわかったのは、「書くより動かす方がずっと難しい」という当たり前のことだった。

#1 計画編 で整理した6つの問題

  1. Problem 01 Botが会議の音声をどう取得するか
  2. Problem 02 文字起こしの精度をどう上げるか
  3. Problem 03 議事録をどう構造化するか
  4. Problem 04 誰が話しているかをどう特定するか
  5. Problem 05 会議終了後すぐに送るにはどうするか
  6. Problem 06 参加者への心理的障壁をどう下げるか

全体の構成

最終的に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を自動取得する

— 実装 01

Bot が会議に参加する部分が、最初の難所だった

Playwright(ブラウザを自動操作するツール)でGoogle Meetを開き、参加ボタンをクリックする。 書くと1行だが、実際にやると最初から詰まった。

参加ボタンが「押せない状態」で表示されていた。 Googleアカウントにログインしていないブラウザでは、ボタンが有効にならない仕組みになっていたからだ。

解決策は、すでにログインしているChromeのCookieを引き継ぐこと。 ChromeのCookieファイルを一時フォルダにコピーして、そこからブラウザを起動する。 これでログイン済みの状態を再現できた。

→ 結果

「Quill 📝 が参加しました」と表示され、チャットに 「📝 Quill が記録します。停止したい方はホストにお伝えください。」 と自動で送られることを確認した。

— 実装 02

文字起こしのコストは、最初から記録しておく

OpenAIのWhisper APIは、音声の長さに応じて課金される。 1分あたり約0.6円。小さい金額だが、ユーザーが増えれば増えるほど積み上がっていく。

だから最初からコストを自動で記録する仕組みを入れた。 会議のたびに「今回いくらかかったか」「今月合計いくらか」をログに残す。 月の合計が一定額を超えたら、切替の検討を促すアラートも出るようにした。

→ 結果

テスト実行のログ:
文字起こしコスト: $0.0028(今月合計: $0.02)
30秒のテストで約0.4円。把握できている。

— 実装 03

AIに3回聞く、という構造が効いた

文字起こしのテキストをそのままAIに渡して「議事録にして」と頼んでも、うまくいかない。 長い文章から必要な情報を一度に全部抜き出すのは、AIが苦手とする処理だ。

そこで3段階に分けた。

まず「決定事項・ToDo・保留事項をJSONで抜き出して」と頼む。
次に、担当者や期限が空のToDoだけを対象に「文章から補完して」と頼む。
最後に「全体を200〜400字で要約して」と頼む。

1回で全部やらせるより、小さい仕事を順番に渡す方が精度が上がった

→ 結果

決定事項・ToDo(担当者・期限付き)・保留事項・サマリーの4セクションが自動で生成される。 内容のない会議(テスト用の無音に近い音声)でも、「判断できる情報がない」と正直に返してくれた。

— 実装 04

話者の特定は、まだ完全ではない

「誰がこの発言をしたか」を自動で判別する機能を実装した。 ただし、Whisper APIは話者を区別する機能を持っていない。 返ってくるのは「テキスト」と「何秒から何秒の発言か」という時間情報だけだ。

今の実装では、発言と発言の間が2秒以上空いたら話者が変わったと推定する。 そこに参加者リストの名前を順番に当てはめていく。精度は高くない。

改善策として「声紋キャッシュ」を入れた。 初回だけ「この声は田中さんで合ってますか?」と確認してもらい、 2回目以降は確認なしで同じ人の声を割り当てる。少しずつ精度が上がっていく設計にしている。

→ 結果

動く。ただし正確ではない。これは「動く状態で出して、使いながら直す」対象として残す。

— 実装 05

会議終了から2秒でメールが届いた

会議が終わった瞬間に処理を始め、できたらすぐ送る。この流れを実装した。

メールはHTMLで送るようにした。テキストだと読みにくいし、 受け取った側が「ちゃんとしたサービスから来た」と感じる見た目にしたかった。 ダークヘッダー・ゴールドのアクセント・セクション区切り—— LPのデザインと統一感を出した。

→ 結果

テスト実行のログ:
✅ 送信完了(会議終了から 2.1秒後)
3分以内どころか、2秒だった。

— 実装 06

「録音されている」ことを、見えるようにする

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 自動連携の認証設定・話者特定の精度改善

それが終わったら、実際の会議で使ってみる。
使ってみてはじめて、本当に必要なものがわかる。

← Blog に戻る ← #1 計画編を読む