Zoomの文字起こしデータを取得する
社内ツールとして取り組んだものの、あまり共有する場もない + とんでもなく沼ったので記事に残しておく。半年以上あれこれ迷走したので正直初期に調べた内容はすでに怪しい。。
なお今回は「話している最中に文字起こしが実行される」というリアルタイム文字起こしにのみに焦点を当てる。音声データをあとから解析する系はそれこそ無限にやり方があるため。
するとだいたいこれくらいの選択肢になるかと思う。
1. Zoom デフォルトの文字起こし機能
(1) Web からダウンロード
(2) Marketplace App 作成
(3) 3rdParty サービスで検知
2. Meeting Bot の利用
3. 自前実装
Zoom デフォルトの機能で取得
まず前提として、この取得を「自動化」するためには録画データをクラウド保存出来る必要があり、 Zoom の Pro プラン以上[1]であることが条件 となる。ローカルかつ手動取得で良ければ文字起こしデータの保存先を PC にするだけで良い。保存先を Google Drive などにする Marketplace App もあったはず。
そもそも Zoom には文字起こし機能が内蔵されていて、それをそのまま流用してもそこそこの精度は出る。ただ注意すべきは 「話している最中に文字起こしが実行される」が「その取得は会議終了後 30 分程度経過してから」 ということ。この時間差については a~c いずれも時間差が無かったので内部処理時間的なものと思われる。
(1) Web からのダウンロード
これは クラウドかつ手動取得
の方法。
クラウドレコーディングや字幕保存の設定を事前に済ませた状態で会議中にクラウド録画を実行すると、会議終了後に「レコーディングと文字起こし」タブに保存された動画が表示されるようになる。
更に会議詳細に進むと動画データ・音声データ・文字起こしデータのダウンロードが可能となっていて、下記の形式のテキストデータが取得できるのであとは煮るなり焼くなり。これを自動取得するのが後続 (2), (3) の方法。
なおこの文字起こしデータは言語が指定できず、10 回に 1 回くらい英語になる。回避策不明[2]。どういうこっちゃ。
// VTTファイル中身イメージ
WEBVTT
1
00:00:XX.XXX --> 00:00:YY.YYY
USER_1: COMMENT_1
2
00:00:YY.YYY --> 00:00:ZZ.ZZZ
USER_2: COMMENT_2
...
(2) Marketplace App 作成
クラウドかつ自動取得
の方法。
Zoom App Marketplace[3] にて新規アプリを作成・登録して、イベントが飛んできたあとの処理をガリガリ書く。開発者的には一番快適…だと思っていたのだが、組織内の数名(=会議ホスト)にアプリを配布する場合には途端に難易度が跳ね上がる。。
(補足)その辺の細かい話
Chrome Extension のような組織内・ドメイン内公開がなく、ストア非表示 + 特定ユーザ配布する場合でも通常アプリと同等に利用手順・技術ドキュメント・利用規約・…などの提出が必須な Zoom 審査を行うことになる。
あまりにめんどすぎて Notion Site とかで作って提出してみたけどふつうに落ちた…正直組織内公開の手順はまだ納得行ってないので勘違いだとむしろ嬉しい。
おそらく利用したい人数分、アプリを複製してそれぞれの環境変数でデプロイしたほうがステップ的には楽…だが各人にアプリ登録 + clientId/clientSecret 発行してもらうのも気が引けるし、かといって Zoom アカウントに紐付いた Google アドレスなんて管理したくない。。
とはいえ単に 1 ユーザかつローカルサーバで試すだけなら簡単で、
Zoom App Marketplace > Server to Server OAuth App > Event Subscriptions
にてイベントを登録したあとでローカルで待ち受ければ受信可能。下記は Hono で試したときのサンプル。
app.post("/webhook", async (c) => {
const body = await c.req.json();
// 実在確認用
if (body.event === "endpoint.url_validation") {
const { plainToken } = body.payload;
return c.json({
plainToken,
encryptedToken: await createEncryptedToken(plainToken),
});
}
console.log("Webhook event received:", body);
return c.json({ status: "success" });
});
{
event: 'meeting.sharing_started',
payload: {
object: {
uuid: ...,
participant: [Object],
id: ...,
type: 1,
topic: ...,
host_id: ...,
duration: 0,
start_time: ...,
timezone: ''
},
account_id: ...
},
event_ts: ...
}
(3) 3rdParty サービスで検知
クラウドかつ自動取得
の方法。
今回採用したのはこのアプローチで、ワークフロー自動化用の Web サービスである Zapier を用いた。決め手は大きく分けて下記 2 点。
- イベント検知回りが優秀
- 複数の Zoom アカウントに対してまとめて認証が出来る
Zoom アカウント単位でアプリを作ってデプロイする (2) の方法と違い、これは各人に Zapier にログイン + Zoom アカウントを接続してさえ貰えればあとはフロー作成側で呼び出せるので快適。
実際には Zapier を用いて「Zoom の文字起こしファイル作成イベント」をトリガーとした。後続フローではファイル名をパースしたり URL からファイル DL したり、会議単位で設定されたプロンプトを読んで OpenAI API に渡したりなど色々設定して運用している。
Meeting Bot の利用
自前で実装するアプローチもあるが、今回試したのは公式フォーラムで紹介されている(紹介しに来ている)[4] Recall.ai を用いる方法。一応 React + Express.js + Recall.ai を用いたデモアプリ[5]の事例もある。
この場合下記 2 つの登録が必要。
- Recall.ai: Zoom Meeting Bot を提供
- Gladia: 音声文字起こし API を提供
文字起こしについては幾つか選択肢[6]がある。文字起こしの精度も速度もかなり優秀で感動したが審査を通すのが面倒で断念。
自前実装
デスクトップ音声のリアルタイムキャプチャ、音声を引き抜けるような Zoom 拡張 web アプリ実装、Whisper の活用、…などなど選択肢は多いがこの辺りはお好み。
所感
Zoom のドキュメントの解読はかなり大変。AI 生成しているのか知らないが、
- 同一の機能に関する記事が複数ヒットする
- 言語別で最終更新日が(時に年単位で)異なる
- 結果、何が正しいのかわからないので結局 1 つずつ自分で設定を変えながら出力を見る
という色々苦しい感じになっている。今回の検証に際して有料プラン間を何度も切り替えることになった。。今後似たようなことに取り組む誰かの参考になれば幸い。
Discussion