Zoom Meeting SDKをWebアプリに組み込むビデオ会議連携入門
概要
自社サービスの画面内でそのままビデオ会議を開きたい、というニーズは意外と多くあります。オンライン診療、オンライン家庭教師、商談、カスタマーサポートなど、「別アプリに飛ばさず、自分たちのWebアプリの中で会議を完結させたい」というケースです。
これを実現する手段のひとつが Zoom Meeting SDK です。本記事では、Zoom Meeting SDK(Web向け)をWebアプリに組み込む最小構成を、公開ドキュメントに基づいてハンズオン形式でまとめます。
ゴールは次の3つです。
- Zoom Marketplace で Meeting SDK 用アプリを作る
- サーバ側で参加用の署名(JWT)を発行する
- フロント側(Component View)で会議に参加する
> 本記事のコードは解説用の最小構成です。本番導入時は認証・エラーハンドリング・利用規約まわりを別途設計してください。
環境
- Node.js 18 以降
- フロント: React + TypeScript(プレーンなJSでも可)
- Zoom Meeting SDK:
@zoom/meetingsdk - サーバ(署名発行用): Node.js + Express +
jsonwebtoken
Zoom の Web 向け SDK には描画方式が2つあります。
| 方式 | 特徴 | 向いている用途 |
|---|---|---|
| Client View | Zoom純正に近いフルUI。画面をほぼ占有 | Zoomと同等の体験を出したい |
| Component View | 任意のDOM要素に埋め込み。配置を制御しやすい | 自社UIの一部として会議を置きたい |
自社アプリに「溶け込ませる」なら Component View が扱いやすいため、本記事はこちらで進めます。
全体構成
ポイントは「署名をフロントで作らない」ことに尽きます。
[ブラウザ] │ 1. 会議番号などを渡して署名を要求 ▼ [自前のバックエンド] ── SDK Secret を保持 │ 2. JWT署名を生成して返す ▼ [ブラウザ] │ 3. 署名を使って Zoom の会議に参加 ▼ [Zoom インフラ]
SDK Secret はクレデンシャルなので、ブラウザに置いた時点で漏洩します。署名の生成は必ずサーバ側で行います。
手順1: Zoom Marketplace でアプリを作る
- Zoom App Marketplace にサインイン
- 「Develop」→「Build App」から Meeting SDK タイプのアプリを作成
- 発行された Client ID / Client Secret(SDK Key / SDK Secret に相当)を控える
この Client ID / Client Secret が署名生成のキーになります。環境変数に入れておきます。
# .env(コミットしない) ZOOM_SDK_KEY=your_client_id ZOOM_SDK_SECRET=your_client_secret
手順2: サーバ側で署名(JWT)を発行する
Meeting SDK の参加署名は HS256 の JWT です。ペイロードに会議番号・ロール・有効期限を入れ、SDK Secret で署名します。
// server/signature.js
const jwt = require('jsonwebtoken')
/**
* @param {string|number} meetingNumber 会議番号
* @param {number} role 0=参加者, 1=ホスト
*/
function generateSignature(meetingNumber, role) {
const iat = Math.round(Date.now() / 1000) - 30 // 時刻ずれ対策で30秒戻す
const exp = iat + 60 * 60 * 2 // 2時間
const header = { alg: 'HS256', typ: 'JWT' }
const payload = {
appKey: process.env.ZOOM_SDK_KEY,
sdkKey: process.env.ZOOM_SDK_KEY,
mn: meetingNumber,
role,
iat,
exp,
tokenExp: exp,
}
return jwt.sign(payload, process.env.ZOOM_SDK_SECRET, {
algorithm: 'HS256',
header,
})
}
module.exports = { generateSignature }
これを API として露出します。
// server/index.js
const express = require('express')
const cors = require('cors')
const { generateSignature } = require('./signature')
const app = express()
app.use(cors())
app.use(express.json())
app.post('/api/zoom/signature', (req, res) => {
const { meetingNumber, role = 0 } = req.body
if (!meetingNumber) {
return res.status(400).json({ error: 'meetingNumber is required' })
}
// 実運用ではここでログイン状態・会議参加権限を検証する
const signature = generateSignature(meetingNumber, role)
res.json({ signature, sdkKey: process.env.ZOOM_SDK_KEY })
})
app.listen(4000, () => console.log('signature server on :4000'))
> ⚠️ /api/zoom/signature を認証なしで公開すると、誰でも任意の会議番号の署名を発行できてしまいます。必ずログイン・権限チェックを前段に挟んでください。
手順3: フロント側で会議に参加する(Component View)
まずパッケージを入れます。
npm install @zoom/meetingsdk
Component View のエントリは @zoom/meetingsdk/embedded の ZoomMtgEmbedded です。会議を描画する空のDOM要素を用意し、init → join の順で呼びます。
// src/ZoomMeeting.tsx
import { useRef } from 'react'
import ZoomMtgEmbedded from '@zoom/meetingsdk/embedded'
const SIGNATURE_ENDPOINT = 'http://localhost:4000/api/zoom/signature'
export function ZoomMeeting() {
const rootRef = useRef<HTMLDivElement>(null)
const join = async () => {
const meetingNumber = '1234567890' // 実際は入力/APIから取得
const password = '' // 会議パスコード
const userName = 'Guest User'
// 1. 署名をサーバから取得
const res = await fetch(SIGNATURE_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ meetingNumber, role: 0 }),
})
const { signature, sdkKey } = await res.json()
// 2. クライアント初期化
const client = ZoomMtgEmbedded.createClient()
await client.init({
zoomAppRoot: rootRef.current!,
language: 'en-US',
patchJsMedia: true, // メディア周りの互換パッチを有効化
})
// 3. 会議に参加
await client.join({
signature,
sdkKey,
meetingNumber,
password,
userName,
})
}
return (
<div>
<button onClick={join}>会議に参加</button>
{/* Zoom がこの要素の中に会議UIを描画する */}
<div ref={rootRef} style={{ width: 800, height: 600 }} />
</div>
)
}
これで「会議に参加」を押すと、指定したDOM要素の中にZoomの会議UIが埋め込まれます。
確認方法
- 署名発行サーバを起動する(
node server/index.js) - フロントを起動し、有効な会議番号(自分で作ったテスト会議でよい)を指定する
- ボタン押下でブラウザ内に会議UIが表示され、映像・音声がつながるかを確認する
- ブラウザのネットワークタブで
/api/zoom/signatureが 200 を返しているか、署名が JWT 形式(xxxxx.yyyyy.zzzzz)になっているかを確認する
署名が不正な場合、join が拒否されます。JWT をデコードして mn(会議番号)・role・exp が意図どおりかを見ると、切り分けが早くなります。
注意点
1. SDK Secret をフロントに置かない 署名はサーバ生成が鉄則です。ビルド成果物に Secret が混入していないか必ず確認します。
2. 時刻ずれで署名が弾かれる iat を少し過去にずらすのは、クライアントとサーバの時刻ずれで「未来の署名」と判定されるのを防ぐための定番対策です。有効期限 exp が短すぎると会議中に切れるので注意します。
3. ブラウザ要件とHTTPS カメラ・マイクを使うため、ローカル以外では HTTPS が実質必須です。対応ブラウザも公式ドキュメントで確認しておきます。
4. Client View は事前ロードが必要 本記事は Component View 中心ですが、Client View(ZoomMtg)を使う場合は CDN アセットの指定や WASM の事前ロードなど追加手順があります。方式ごとに手順が違う点に注意します。
5. バージョン差異 Zoom SDK は更新が速く、関数名やオプション(例: patchJsMedia)が変わることがあります。導入時はインストールしたバージョンの公式ドキュメントを一次情報として参照してください。
まとめ
- Zoom Meeting SDK を使えば、自社WebアプリにビデオをUIごと埋め込めます
- 肝は「署名はサーバで作り、Secret をフロントに出さない」こと
- 自社UIに溶け込ませたいなら Component View、Zoom純正体験なら Client View
- 最小構成は「Marketplaceでアプリ作成 → サーバで署名発行 → フロントで init/join」の3ステップ
まずはテスト会議でこの3ステップを通すと、全体像が一気につかめます。
