すべてのAIミーティングアシスタントの裏側にあるアーキテクチャ:bot がミーティングを録画し、webhook がトランスクリプトを配信し、LLM がサマリーを生成します。コード付きでパイプライン全体を解説します。

LLazare Rossillon
··2 min read
午後一杯でAIミーティングノートテイカーを構築する

すべてのAIミーティングアシスタント — ノートテイカー、営業通話分析ツール、コンプライアンス録画システム — は同じ3段階のパイプラインで構築されています:

  1. キャプチャ: bot がミーティングに参加して録画する
  2. 文字起こし: 音声が話者付きのテキストに変換される
  3. 推論: LLM がトランスクリプトをサマリー、アクションアイテム、CRM更新へと変換する

ステージ1と2はインフラです。ステージ3があなたのプロダクトです。このガイドでは、ステージ1と2をAPI1回の呼び出しで完結させ、ステージ3に集中できるようにする方法を紹介します。

録画と文字起こしはMeeting BaaSから購入するインフラです。文字起こしに基づく推論があなたが構築するプロダクトです

キャプチャー層が最も難しい部分です。Zoom、Google Meet、Microsoft Teamsにわたって、待機室、レイアウト変更、4時間に及ぶ通話を乗り越えられるbotが必要です。これは自分で構築するのではなく、購入すべき部分です。

キャプチャー層:1回のPOSTリクエスト

import { createBaasClient } from "@meeting-baas/sdk";

const client = createBaasClient({
  api_key: process.env.MEETING_BAAS_API_KEY,
  api_version: "v2"
});

const { success, data, error } = await client.createBot({
  bot_name: "Acme Notetaker",
  meeting_url: meetingUrl // Zoom, Google Meet or Microsoft Teams
});

同じリクエストが3つのプラットフォームすべてで機能します。カレンダー連携を有効にすれば、このステップすら不要です。ユーザーの今後のミーティングに合わせて、botが自動的にスケジュールされます。

文字起こしはwebhookで届きます

ミーティングが終了すると、webhook経由で話者帰属付きの文字起こし、参加者リスト、録画URLが届きます。最小限のハンドラーの例:

export async function POST(req: Request) {
  const rawBody = await req.text();

  // Verify the webhook signature over the raw body before parsing —
  // see the webhooks documentation for the signing scheme
  if (!verifySignature(req.headers, rawBody)) {
    return new Response("invalid signature", { status: 401 });
  }

  const event = JSON.parse(rawBody);

  if (event.event === "complete") {
    const { bot_id, transcript, participants } = event.data;
    // Deduplicate on bot_id so replayed deliveries don't re-run the LLM
    if (await alreadyProcessed(bot_id)) return new Response("ok");
    await summarize(bot_id, transcript, participants);
  }

  return new Response("ok");
}

話者分離はすべての録画に含まれており、セグメントは実際の参加者名に対応しています。LLMのプロンプトには「Speaker 2: 金曜日にリリースします」ではなく「Sarah: 金曜日にリリースします」という形式でデータが渡されます。この違いがアクションアイテム抽出を実際に機能させるポイントです。

推論層:あなたのプロダクト

話者が明確に紐付けられたクリーンな文字起こしがあれば、LLMのステップはプロジェクトではなくプロンプトの問題になります:

async function summarize(botId: string, transcript: Segment[], participants: Participant[]) {
  const text = transcript
    .map((segment) => `${segment.speaker}: ${segment.text}`)
    .join("\n");

  const summary = await llm.complete({
    prompt: `Summarize this meeting. Extract decisions and action items with owners.\n\n${text}`
  });

  await saveNotes(botId, summary);
}

ここからの差別化はプロダクト開発の領域です。参加者ごとのフォローアップメール、CRMへのデータ補完、定例ミーティングをまたいだトピック追跡、あるいはライブで質問に答える発話bot(最後の機能はspeaking bots APIで対応)など、様々な可能性があります。

運用コスト

録画は話者分離込みで1時間あたり1トークン。文字起こしは1時間あたり0.25トークンが追加されます。トークンパックは1トークンあたり$0.35〜$0.50のため、文字起こし付きの1時間のミーティングコストは$0.44〜$0.63です(LLMのコストを除く。1時間のミーティングの文字起こしに対するLLMコストは通常1〜2セント程度です)。

次のステップ

関連ブログtutorial