授業中、スライドのコピーやメモ取りに必死になって、結局説明が頭に入ってこないことがよくあります。
メモを取る作業は自動化して、自分は授業を聞くことに集中したいので、録音ファイルを投げたら自動で「復習ノート」と「テストの予想問題」を作ってDiscordに送る仕組みを作りました。
仕組み
スマホで録音した音声(mp3)をアップロードすると、以下の流れで処理されます。
- Scribe API: 音声から文字起こしする
- Summarizer API: 文字起こしデータから復習ノートとクイズを作る
- Discord Webhook: 生成されたテキストをスマホに送る
コード
Next.js (App Router) で実装していきます。
音声ファイルのアップロード部分は、受け取ったファイルを public/uploads に保存してURLを返すだけの一般的な処理です。
基本的なZoomのAPIを叩いてDiscordに流す部分のコードは以下の通りです。
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { audioUrl } = await request.json();
// 1. Zoomのアクセストークンを取得 (OAuth)
const auth = Buffer.from(`${process.env.ZOOM_CLIENT_ID}:${process.env.ZOOM_CLIENT_SECRET}`).toString("base64");
const tokenRes = await fetch("https://zoom.us/oauth/token", {
method: "POST",
headers: {
Authorization: `Basic ${auth}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "account_credentials",
account_id: process.env.ZOOM_ACCOUNT_ID!,
}),
});
const { access_token } = await tokenRes.json();
// 2. Scribe API で文字起こし
const scribeRes = await fetch("https://api.zoom.us/v2/ai/scribe/transcribe", {
method: "POST",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
audio_url: audioUrl,
language: "ja-JP",
}),
});
const { transcript } = await scribeRes.json();
// 3. Summarizer API で要約と予想問題を生成
const summarizerRes = await fetch("https://api.zoom.us/v2/ai/summarizer/summarize", {
method: "POST",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: transcript,
prompt_instruction: "この講義の文字起こしデータから、講義の要点ノート(3つのトピック)と、テスト予想問題を3問(一問一答)作成してください。",
}),
});
const { summary } = await summarizerRes.json();
// 4. Discordへ通知
await fetch(process.env.DISCORD_WEBHOOK_URL!, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
content: `講義ノートと予想問題が届きました。\n\n${summary}`,
}),
});
return NextResponse.json({ success: true });
}
実際に届くノートの例
Discordに以下のようなテキストが送信されます。
通学中などにスマホで見るのにちょうどいいです。
講義ノートと予想問題が届きました。
■ 講義の要点ノート
・[関係データベース(RDB)のACID特性]:
データベースのトランザクション処理において信頼性を保証するための4つの特性(Atomicity, Consistency, Isolation, Durability)について。
・[排他制御とデッドロック]:
複数のプロセスが同時に同じデータにアクセスするのを防ぐロックの仕組みと、デッドロックの発生条件について。
■ テスト予想問題
・Q1. トランザクションのACID特性のうち、「障害が発生しても、一度コミットされた処理結果は失われない」ことを保証する特性は何と呼ぶか?
A1. Durability(耐久性 / 永続性)。
・Q2. デッドロックが発生した場合、データベース管理システム(DBMS)は通常どのように対処するか?
A2. トランザクションの一方を強制的にロールバックし、もう一方の処理を進行させます。
ハマりどころ
1. 音声ファイルはインターネット公開されている必要がある
Scribe APIに渡す audio_url は、ZoomのサーバーからアクセスできるパブリックURLである必要があります。ローカルの localhost:3000/... は渡せません。
開発時は ngrok を使ってローカルサーバーを外部公開すると動作確認ができます。
本番で動かすなら、S3やVercel Blobに一度アップロードしたURLを渡すのが無難です。
2. 教室の雑音対策
教室のざわざわしたノイズを拾うと文字起こしが崩れることがあります。
APIリクエストのパラメータで language: "ja-JP" を指定しておくと、ノイズを英語の単語と誤認識するのを防ぐことができ、動作が安定します。
まとめ
メモを取る必要がなくなったので、授業中は話の理解に集中できるようになります。
また、ZoomのAPIはREST APIを数回叩くだけなので、面倒なAIモデルの準備なしでカンタンに実装できます。