0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Zoom AI Servicesで会議ログを実行キューに変える:dry-runで作るAPI連携設計

0
Last updated at Posted at 2026-06-02

ig_0d5236f800a0877a016a1e3e31131081919674c8d18c8d250c.png

この記事は、Qiita Tech Festa 2026の「Zoom AI Servicesで文字起こし、翻訳、要約をやってみよう!」に参加するための実装メモです。

会議AIでよくある失敗は、きれいな議事録ができても、誰が何をいつまでにやるかが実行系に流れないことです。

そこで今回は、Zoom AI Servicesを「議事録生成」ではなく、実行キュー生成APIとして扱う設計にしました。

先に検証範囲を明記します。
この記事では、Scribe / Summarizer / Translator APIの実レスポンス品質はまだ評価していません。
手元のZoom Workplaceベーシック環境では、Zoom App MarketplaceのServer-to-Server OAuth appにAI Services用のscopeが見つからず、公式ドキュメントが案内するBuild PlatformのAPI key / secret / JWTまで到達できませんでした。

そのため、この記事の主眼は次の2つです。

  • 実API接続前でも、後続ワークフローを壊さず検証できるdry-run構成を作る
  • 実APIに差し替えるとき、どこを境界にして安全性・再現性を確認するかを整理する

結論

Zoom AI Servicesの3つのAPIは、次のように役割を分けると実務フローに載せやすいです。

API 役割 実務での出口
Scribe API 音声や録画をテキスト化する 会議ログの検索・保存
Summarizer API 決定事項とAction Itemsを抽出する GitHub Issues / Jira / Notion
Translator API 要約やタスクを多言語化する 海外チーム向け共有 / Slack下書き

ポイントは、3つを横に並べて紹介するのではなく、会議後の手作業を減らす1本のパイプラインとして接続することです。

今回の実装では、API応答をmock化し、Summarizerのfull_summaryに近いテキストからAction Itemsを抽出してGitHub Issue draftとSlack draftに変換します。

つまり、AIの精度を測る前に、AI結果を受け取った後の業務導線を先に固めるアプローチです。

作ったもの

今回は、会議ログから次の3つを生成する最小構成を作りました。

  • GitHub Issue用のAction Items
  • Slack投稿用の会議サマリー
  • 海外チーム向けの英語要約

ローカル検証用のコードは以下に置いています。

tmp/zoom-ai-services-action-queue/
├── meeting-transcript.txt
├── mock-zoom-results.json
├── package.json
└── zoom-action-queue.mjs

実行コマンドです。

cd tmp/zoom-ai-services-action-queue
npm run dry-run

出力はこうなります。

{
  "mode": "dry-run",
  "elapsed_ms": 1,
  "action_item_count": 4,
  "output_dir": "/Users/yushiy/qiita-backup/tmp/zoom-ai-services-action-queue/out/"
}

生成されたファイルです。

out/action-queue.json
out/github-issues.md
out/slack-summary.md

今回の検証範囲

この記事で検証済みの範囲と、まだ検証していない範囲を分けます。

区分 内容 状態
dry-run実行 ローカル会議ログからAction Itemsを4件生成 検証済み
後続変換 GitHub Issue draft / Slack summary / action JSONを生成 検証済み
安全境界 redaction後にAPIへ渡し、外部反映前に人間レビューを挟む設計 設計済み
Scribe API実行 音声URLをZoom AI Servicesへ送る 未接続
Summarizer API実行 実レスポンスのAction Items品質を見る 未接続
Translator API実行 実レスポンスの翻訳品質を見る 未接続
コスト・latency Build Platform上の利用量と処理時間を見る 未評価

この分離をしておくと、APIキー待ちの間でも「記事がただの構想で止まる」ことを避けられます。
APIが使える環境になったら、mock部分だけを実API呼び出しに差し替えればよい構成です。

アーキテクチャ

会議AIを「読ませる」だけで終わらせず、最後をIssueやSlack draftにしています。

これにより、会議後の作業は次のように変わります。

従来 今回の設計
議事録を読む Action Itemsだけ確認する
手で担当者を拾う ownerつきJSONに変換する
英語共有を別途作る Translator APIで共有文を作る
チケット起票を忘れる Issue draftを生成する

Zoom AI Services APIの使い分け

公式ドキュメントでは、AI Servicesはメディアデータを処理して独自ソリューションを作るためのintelligence API群として説明されています。

また、AI Servicesの認可は一般的なZoom App Marketplace OAuth scopeではなく、Build PlatformのAPI key / secretから生成するJWTを使う構成として案内されています。

https://developers.zoom.us/docs/ai-services/auth/
https://developers.zoom.us/docs/ai-services/build-platform/

ここが今回いちばん詰まった点でした。Zoom App MarketplaceでServer-to-Server OAuth appを作ると、通常のZoom API用のscopeは選べます。

しかし、手元ではScribe / Summarizer / Translatorに対応するscopeは見つかりませんでした。

AI Companionのaic:read:conversation_archives:adminは会話アーカイブ閲覧のscopeであり、この記事で使いたいAI Services APIとは目的が違うため選びません。

実API接続に必要な環境変数はこの2つに分けました。

# 必須: Build PlatformのAPI key / secretから生成した短命JWT
export ZOOM_AI_SERVICES_TOKEN="..."

# 任意: Scribe APIへ渡す短い音声ファイルURL
export ZOOM_AUDIO_URL="$YOUR_SHORT_AUDIO_FILE_URL"

ZOOM_AUDIO_URLがない場合でも、後続のSummarizer / Translator連携設計を検証できるように、ローカルのmeeting-transcript.txtを使う設計にしています。

Scribe API

Scribe APIは音声をテキスト化するAPIです。Fast modeでは短い音声ファイルを同期的に処理でき、WAV、MP3、M4A、MP4が対象です。

Fast modeのリクエストはこの形です。

curl -X POST https://api.zoom.us/v2/aiservices/scribe/transcribe \
  -H "Authorization: Bearer $ZOOM_AI_SERVICES_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "'"$ZOOM_AUDIO_URL"'",
    "config": {
      "language": "en-US",
      "word_time_offsets": true,
      "channel_separation": false
    }
  }'

記事では、Build Platform JWTがない環境でも後続処理を検証できるよう、meeting-transcript.txtを入力にしたdry-runを用意しています。

Summarizer API

Summarizer APIは、会議や通話などの会話テキストを要約するAPIです。
Fast modeではinline transcript textを1リクエストで処理できます。
公式ドキュメント上、taskにはrecapsummaryaction_itemsfull_summaryを指定できます。

今回の設計では、full_summaryを使います。理由は、要約だけでなくAction Itemsも同時に扱いたいからです。

const summary = await zoomPost("/aiservices/summarizer/summarize", {
  input: { text: transcript },
  config: {
    summary_type: "conversation",
    task: "full_summary",
    language: "ja-JP",
  },
  reference_id: `meeting-${Date.now()}`,
});

dry-runでは次のようなAction Itemsを生成しました。

[
  {
    "owner": "Yushi",
    "task": "顧客名と機密情報のredaction checklistを作る。",
    "labels": ["zoom-ai-services", "meeting-action-item"]
  },
  {
    "owner": "Mika",
    "task": "GitHub Issue templateを作る。",
    "labels": ["zoom-ai-services", "meeting-action-item"]
  }
]

Translator API

Translator APIはテキスト翻訳用APIです。
Fast modeでは短いテキストを同期的に翻訳できます。
公式ドキュメントでは、英語と8言語の双方向翻訳に対応し、英語を含まない2言語間の直接翻訳はまだ対象外とされています。

日本語要約を英語チームに共有する場合は、source_language: "ja-JP"target_languages: ["en-US"]にします。

const translation = await zoomPost("/aiservices/translator/translate", {
  text: summary.result.text.slice(0, 4000),
  config: {
    source_language: "ja-JP",
    target_languages: ["en-US"],
  },
  reference_id: `summary-${Date.now()}`,
});

GitHub Issueに変換する

Summarizer APIのaction_items系出力は、人間が読むには十分ですが、そのままではタスク管理ツールに流しにくいです。

そこで、ownerごとにAction Itemsを取り出してIssue draftへ変換します。

function parseActionItems(summaryText) {
  const actionStart = summaryText.indexOf("Action Items:");
  const actionText = actionStart >= 0 ? summaryText.slice(actionStart) : summaryText;
  const lines = actionText.split(/\r?\n/);
  const items = [];
  let owner = "Unassigned";

  for (const rawLine of lines) {
    const line = rawLine.trim();
    if (!line || line === "Action Items:") continue;
    if (!line.startsWith("-")) {
      owner = line.replace(/\*\*/g, "");
      continue;
    }
    items.push({
      owner,
      task: line.replace(/^-\s*/, ""),
      labels: ["zoom-ai-services", "meeting-action-item"],
    });
  }
  return items;
}

出力されるIssue draftの例です。

## Yushi: 顧客名と機密情報のredaction checklistを作る。

- source: Zoom AI Services pipeline
- labels: zoom-ai-services, meeting-action-item

ここまでできれば、最後にGitHub API、Jira API、Notion APIなどへ送れます。

重要なのは、自動起票する前にdraftとして人間が確認する境界を残すことです。

実APIで見るべき検証観点

Zoom AI Servicesの選出基準では、独自性だけでなく実用性、再現性、検証の視点も重要です。
単にAPIを叩くだけでは弱いので、実API接続後は次の表で測ります。

観点 測るもの 理由
latency Scribe / Summarizer / Translatorごとの処理時間 会議後ワークフローに入るか判断する
action-item accuracy 担当者・タスク・期限の抽出精度 Issue化できる品質か見る
translation quality 日英共有で意味が崩れないか 多言語チームで使えるか見る
redaction漏れ 顧客名・個人情報が残らないか API送信前の安全性を見る
review cost 人間の修正時間 自動化の費用対効果を見る

dry-runでは処理自体はローカル変換なので、API品質やコストは評価していません。
実API接続後は、3本以上の短い会議ログでこの表を埋めます。

実APIへの差し替えチェックリストです。

  • Build PlatformのAPI key / secretを取得する
  • 1時間以内で失効するJWTを生成する
  • ZOOM_AI_SERVICES_TOKENをローカル環境変数として渡す
  • 音声をAPIに送る前にredaction方針を決める
  • ZOOM_AUDIO_URLは短い音声ファイルから始める
  • npm run liveでScribe / Summarizer / Translatorの境界を確認する
  • 生成されたIssue draftを人間が確認してから外部ツールへ反映する

セキュリティとプライバシー

会議ログは、メールやソースコードよりも不用意に個人情報が混ざりやすいです。
APIに送る前に、最低限この処理を入れます。

const redactionRules = [
  { name: "email", pattern: /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, replace: "[EMAIL]" },
  { name: "phone", pattern: /\+?\d[\d -]{8,}\d/g, replace: "[PHONE]" },
  { name: "customer", pattern: /Customer[A-Z0-9_-]+/g, replace: "[CUSTOMER]" },
];

function redact(text) {
  return redactionRules.reduce(
    (value, rule) => value.replace(rule.pattern, rule.replace),
    text,
  );
}

自動化するときは、次の順番が安全です。

  1. ローカルでredaction
  2. Zoom AI Servicesへ送信
  3. Action Itemsをdraft化
  4. 人間が確認
  5. GitHub Issues / Slack / Notionへ反映

会議ログからいきなり外部チケットを作ると、誤抽出や機密情報混入の事故が起きます。
実運用では、draft段階を挟むのが現実的です。

失敗パターン

失敗 何が起きるか 対策
議事録だけ作る 誰もタスク化しない Action ItemsをIssue draftへ変換する
API結果をそのまま投稿 誤抽出や機密情報が流れる draft reviewを必須にする
日本語だけで共有 海外チームが追えない Translator APIで英語要約を作る
長時間音声を同期処理 待ち時間や失敗が増える Batch modeとwebhookを使う
担当者が曖昧 Issueのownerが決まらない Unassignedを人間レビュー対象にする
App Marketplace OAuth scopeを探し続ける AI Services用のJWTに到達できない Build PlatformのAPI key / secret導線を確認する

まとめ

Zoom AI Servicesは、単に「文字起こし・翻訳・要約ができるAPI」として見るより、会議を実行キューへ変換する部品として見ると使い道が広がります。

今回の設計では、Scribeでテキスト化し、Summarizerで決定事項とAction Itemsを抽出し、Translatorで英語共有まで作ります。
最後にGitHub IssueやSlack draftに落とすことで、会議後の手作業を減らせます。

今回の実API未接続は弱点でもありますが、読者にとっては再現時の落とし穴でもあります。Zoom App MarketplaceのServer-to-Server OAuth appだけではなく、AI Services向けのBuild Platform JWTが必要な点を最初に切り分けると、無駄なscope探索を避けられます。

次に実APIで確認したいのは、速度よりもAction Itemsの品質です。
会議ログから「誰が」「何を」「どの粒度で」持ち帰れるかを測ると、Zoom AI Servicesを業務フローに組み込む判断がしやすくなります。

参考リンク

この記事を書いた人✏️@YushiYamamoto
ITPRODX.com代表 / AIアーキテクト
Next.js / TypeScript / n8nを活用した自律型アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?