build-zoom-video-sdk-app
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese/build-zoom-video-sdk-app
/build-zoom-video-sdk-app
Background reference for fully custom video-session products. Prefer first when the boundary between Meeting SDK and Video SDK is still unclear.
plan-zoom-productBuild custom video experiences powered by Zoom's infrastructure.
完全自定义视频会话产品的背景参考文档。当Meeting SDK与Video SDK的边界仍不明确时,优先使用。
plan-zoom-product基于Zoom基础设施构建自定义视频体验。
Hard Routing Guardrail (Read First)
硬路由规则(必读)
- If the user asks for custom real-time video app behavior (topic/session join, custom rendering, attach/detach), route to Video SDK.
- Do not switch to REST meeting endpoints for Video SDK join flows.
- Video SDK does not use Meeting IDs, , or Meeting SDK join payload fields (
join_url,meetingNumber).passWord
- 如果用户要求自定义实时视频应用行为(主题/会话加入、自定义渲染、附加/分离),则路由到Video SDK。
- 不要为Video SDK加入流程切换到REST会议端点。
- Video SDK不使用会议ID、或Meeting SDK加入负载字段(
join_url、meetingNumber)。passWord
Meeting SDK vs Video SDK
Meeting SDK与Video SDK对比
| Feature | Meeting SDK | Video SDK |
|---|---|---|
| UI | Default Zoom UI or Custom UI | Fully custom UI (you build it) |
| Experience | Zoom meetings | Video sessions |
| Branding | Limited customization | Full branding control |
| Features | Full Zoom features | Core video features |
| 功能 | Meeting SDK | Video SDK |
|---|---|---|
| UI界面 | 默认Zoom UI或自定义UI | 完全自定义UI(由您自行构建) |
| 体验 | Zoom会议 | 视频会话 |
| 品牌定制 | 有限定制 | 完全品牌控制权 |
| 功能 | 完整Zoom功能 | 核心视频功能 |
UI Options (Web)
Web端UI选项
Video SDK gives you full control over the UI:
| Option | Description |
|---|---|
| UI Toolkit | Pre-built React components (low-code) |
| Custom UI | Build your own UI using the SDK APIs |
Video SDK让您完全控制UI界面:
| 选项 | 描述 |
|---|---|
| UI Toolkit | 预构建React组件(低代码) |
| 自定义UI | 使用SDK API构建自有UI |
Prerequisites
前置条件
- Zoom Video SDK credentials from Marketplace
- SDK Key and Secret
- Web development environment
Need help with OAuth or signatures? See the zoom-oauth skill for authentication flows.
Need pre-join diagnostics on web? Use probe-sdk before Video SDKto reduce first-minute failures.join()
Start troubleshooting fast: Use the 5-Minute Runbook before deep debugging.
- 来自Zoom Marketplace的Zoom Video SDK凭证
- SDK密钥与密钥密码
- Web开发环境
需要OAuth或签名相关帮助? 查看**zoom-oauth**技能获取认证流程说明。
需要Web端加入前诊断? 在调用Video SDK前使用**probe-sdk**以减少初始阶段的失败。join()
快速启动故障排查: 在深度调试前先查看**5-Minute Runbook**。
Quick Start (Web)
Web端快速开始
NPM Usage (Bundler like Vite/Webpack)
NPM使用(适用于Vite/Webpack等打包工具)
javascript
import ZoomVideo from '@zoom/videosdk';
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global', { patchJsMedia: true });
await client.join(topic, signature, userName, password);
// IMPORTANT: getMediaStream() ONLY works AFTER join()
const stream = client.getMediaStream();
await stream.startVideo();
await stream.startAudio();javascript
import ZoomVideo from '@zoom/videosdk';
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global', { patchJsMedia: true });
await client.join(topic, signature, userName, password);
// 重要提示:getMediaStream()仅在join()后可用
const stream = client.getMediaStream();
await stream.startVideo();
await stream.startAudio();CDN Usage (No Bundler)
CDN使用(无需打包工具)
WARNING: Ad blockers block. Self-host the SDK to avoid issues.source.zoom.us
bash
undefined警告:广告拦截器会阻止。建议自行托管SDK以避免问题。source.zoom.us
bash
undefinedDownload SDK locally
本地下载SDK
curl "https://source.zoom.us/videosdk/zoom-video-1.12.0.min.js" -o js/zoom-video-sdk.min.js
```html
<script src="js/zoom-video-sdk.min.js"></script>javascript
// CDN exports as WebVideoSDK, NOT ZoomVideo
// Must use .default property
const ZoomVideo = WebVideoSDK.default;
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global', { patchJsMedia: true });
await client.join(topic, signature, userName, password);
// IMPORTANT: getMediaStream() ONLY works AFTER join()
const stream = client.getMediaStream();
await stream.startVideo();
await stream.startAudio();curl "https://source.zoom.us/videosdk/zoom-video-1.12.0.min.js" -o js/zoom-video-sdk.min.js
```html
<script src="js/zoom-video-sdk.min.js"></script>javascript
// CDN导出的是WebVideoSDK,而非ZoomVideo
// 必须使用.default属性
const ZoomVideo = WebVideoSDK.default;
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global', { patchJsMedia: true });
await client.join(topic, signature, userName, password);
// 重要提示:getMediaStream()仅在join()后可用
const stream = client.getMediaStream();
await stream.startVideo();
await stream.startAudio();ES Module with CDN (Race Condition Fix)
结合CDN使用ES模块(解决竞态条件)
When using with CDN, SDK may not be loaded yet:
<script type="module">javascript
// Wait for SDK to load before using
function waitForSDK(timeout = 10000) {
return new Promise((resolve, reject) => {
if (typeof WebVideoSDK !== 'undefined') {
resolve();
return;
}
const start = Date.now();
const check = setInterval(() => {
if (typeof WebVideoSDK !== 'undefined') {
clearInterval(check);
resolve();
} else if (Date.now() - start > timeout) {
clearInterval(check);
reject(new Error('SDK failed to load'));
}
}, 100);
});
}
// Usage
await waitForSDK();
const ZoomVideo = WebVideoSDK.default;
const client = ZoomVideo.createClient();当使用结合CDN时,SDK可能尚未加载完成:
<script type="module">javascript
// 使用前等待SDK加载完成
function waitForSDK(timeout = 10000) {
return new Promise((resolve, reject) => {
if (typeof WebVideoSDK !== 'undefined') {
resolve();
return;
}
const start = Date.now();
const check = setInterval(() => {
if (typeof WebVideoSDK !== 'undefined') {
clearInterval(check);
resolve();
} else if (Date.now() - start > timeout) {
clearInterval(check);
reject(new Error('SDK加载失败'));
}
}, 100);
});
}
// 使用示例
await waitForSDK();
const ZoomVideo = WebVideoSDK.default;
const client = ZoomVideo.createClient();SDK Lifecycle (CRITICAL ORDER)
SDK生命周期(严格顺序)
The SDK has a strict lifecycle. Violating it causes silent failures.
1. Create client: client = ZoomVideo.createClient()
2. Initialize: await client.init('en-US', 'Global', options)
3. Join session: await client.join(topic, signature, userName, password)
4. Get stream: stream = client.getMediaStream() ← ONLY AFTER JOIN
5. Start media: await stream.startVideo() / await stream.startAudio()Common Mistake (Silent Failure):
javascript
// ❌ WRONG: Getting stream before joining
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global');
const stream = client.getMediaStream(); // Returns undefined!
await client.join(...);
// ✅ CORRECT: Get stream after joining
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global');
await client.join(...);
const stream = client.getMediaStream(); // Works!SDK有严格的生命周期,违反顺序会导致静默失败。
1. 创建客户端: client = ZoomVideo.createClient()
2. 初始化: await client.init('en-US', 'Global', options)
3. 加入会话: await client.join(topic, signature, userName, password)
4. 获取媒体流: stream = client.getMediaStream() ← 仅在加入后可用
5. 启动媒体: await stream.startVideo() / await stream.startAudio()常见错误(静默失败):
javascript
// ❌ 错误:在加入前获取媒体流
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global');
const stream = client.getMediaStream(); // 返回undefined!
await client.join(...);
// ✅ 正确:在加入后获取媒体流
const client = ZoomVideo.createClient();
await client.init('en-US', 'Global');
await client.join(...);
const stream = client.getMediaStream(); // 正常工作!Video Rendering (Event-Driven)
视频渲染(事件驱动)
The SDK is event-driven. You must listen for events and render videos accordingly.
SDK采用事件驱动模式。您必须监听事件并相应地渲染视频。
Use attachVideo()
NOT renderVideo()
attachVideo()renderVideo()使用attachVideo()
而非renderVideo()
attachVideo()renderVideo()javascript
import { VideoQuality } from '@zoom/videosdk';
// Start your camera
await stream.startVideo();
// Attach video - returns element to append to DOM
const element = await stream.attachVideo(userId, VideoQuality.Video_360P);
container.appendChild(element);
// Detach when done
await stream.detachVideo(userId);javascript
import { VideoQuality } from '@zoom/videosdk';
// 启动摄像头
await stream.startVideo();
// 附加视频 - 返回要添加到DOM的元素
const element = await stream.attachVideo(userId, VideoQuality.Video_360P);
container.appendChild(element);
// 完成后分离
await stream.detachVideo(userId);Required Events
必备事件
javascript
// When other participant's video turns on/off
client.on('peer-video-state-change', async (payload) => {
const { action, userId } = payload;
if (action === 'Start') {
const el = await stream.attachVideo(userId, VideoQuality.Video_360P);
container.appendChild(el);
} else {
await stream.detachVideo(userId);
}
});
// When participants join/leave
client.on('user-added', (payload) => { /* check bVideoOn */ });
client.on('user-removed', (payload) => { stream.detachVideo(payload.userId); });See web/references/web.md for complete event handling patterns.
javascript
// 当其他参与者的视频开启/关闭时
client.on('peer-video-state-change', async (payload) => {
const { action, userId } = payload;
if (action === 'Start') {
const el = await stream.attachVideo(userId, VideoQuality.Video_360P);
container.appendChild(el);
} else {
await stream.detachVideo(userId);
}
});
// 当参与者加入/离开时
client.on('user-added', (payload) => { /* 检查bVideoOn状态 */ });
client.on('user-removed', (payload) => { stream.detachVideo(payload.userId); });查看web/references/web.md获取完整的事件处理模式。
Key Concepts
核心概念
| Concept | Description |
|---|---|
| Session | Video session (not a meeting) |
| Topic | Session identifier (any string you choose) |
| Signature | JWT for authorization |
| MediaStream | Audio/video stream control |
| 概念 | 描述 |
|---|---|
| 会话 | 视频会话(非会议) |
| Topic | 会话标识符(可自定义任意字符串) |
| Signature | 用于授权的JWT |
| MediaStream | 音视频流控制 |
Session Creation Model
会话创建模型
Important: Video SDK sessions are created just-in-time, not in advance.
| Aspect | Video SDK | Meeting SDK |
|---|---|---|
| Pre-creation | NOT required | Create meeting via API first |
| Session start | First participant joins with topic | Join existing meeting ID |
| Topic | Any string (you define it) | Meeting ID from API |
| Scheduling | N/A - sessions are ad-hoc | Meetings can be scheduled |
重要提示: Video SDK会话是即时创建的,无需提前创建。
| 方面 | Video SDK | Meeting SDK |
|---|---|---|
| 提前创建 | 不需要 | 需先通过API创建会议 |
| 会话启动 | 第一个参与者使用Topic加入时创建 | 加入已存在的会议ID |
| Topic | 任意自定义字符串 | 来自API的会议ID |
| 日程安排 | 不支持 - 会话为临时创建 | 可安排会议 |
How Sessions Work
会话工作原理
- No pre-creation needed: Sessions don't exist until someone joins
- Topic = Session ID: Any participants joining with the same string join the same session
topic - First join creates it: The session is created when the first participant joins
- No meeting ID: There's no numeric meeting ID like in Zoom Meetings
javascript
// Session is created on-the-fly when first user joins
// Any string can be the topic - it becomes the session identifier
await client.join('my-custom-session-123', signature, 'User Name');
// Other participants join the SAME session by using the SAME topic
await client.join('my-custom-session-123', signature, 'Another User');- 无需提前创建:会话在有人加入前不存在
- Topic = 会话ID:使用相同字符串的参与者会加入同一个会话
topic - 首次加入创建会话:当第一个参与者加入时会话被创建
- 无会议ID:不像Zoom Meetings那样有数字会议ID
javascript
// 当第一个用户加入时,会话会即时创建
// Topic可以是任意字符串 - 它将作为会话标识符
await client.join('my-custom-session-123', signature, 'User Name');
// 其他参与者使用相同的Topic即可加入同一个会话
await client.join('my-custom-session-123', signature, 'Another User');Signature Endpoint Setup
签名端点设置
The signature endpoint must be accessible from your frontend without CORS issues.
Option 1: Same-Origin Proxy (Recommended)
nginx
undefined签名端点必须能被前端访问且无CORS问题。
选项1:同源代理(推荐)
nginx
undefinedNginx config
Nginx配置
location /api/ {
proxy_pass http://YOUR_BACKEND_HOST:3005/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
```javascript
// Frontend uses relative URL (same origin)
const response = await fetch('/api/signature', { ... });Option 2: CORS Configuration
javascript
// Express.js backend
const cors = require('cors');
app.use(cors({
origin: ['https://your-domain.com'],
credentials: true
}));WARNING: Mixed content (HTTPS page → HTTP API) will be blocked by browsers.
location /api/ {
proxy_pass http://YOUR_BACKEND_HOST:3005/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
```javascript
// 前端使用相对URL(同源)
const response = await fetch('/api/signature', { ... });选项2:CORS配置
javascript
// Express.js后端
const cors = require('cors');
app.use(cors({
origin: ['https://your-domain.com'],
credentials: true
}));警告: 混合内容(HTTPS页面 → HTTP API)会被浏览器阻止。
Use Cases
使用场景
| Use Case | Description |
|---|---|
| Video SDK BYOS (Bring Your Own Storage) | Save recordings directly to your S3 bucket |
| 使用场景 | 描述 |
|---|---|
| Video SDK BYOS(自带存储) | 将录制内容直接保存到您的S3存储桶 |
BYOS (Bring Your Own Storage)
BYOS(自带存储)
Video SDK feature - Zoom saves cloud recordings directly to your Amazon S3 bucket. No downloading required.
Official docs: https://developers.zoom.us/docs/build/storage/
Prerequisites:
- Video SDK account with Cloud Recording add-on (Universal Credit includes this)
- AWS S3 bucket
Authentication options:
- AWS Access Key - simpler setup
- Cross Account Access - more secure (IAM role assumption)
S3 path structure:
Buckets/{bucketName}/cmr/byos/{YYYY}/{MM}/{DD}/{GUID}/cmr_byos/Key benefits:
- Zero download bandwidth costs
- Direct storage during recording
- Config-only setup (no webhook/download code needed)
Setup location: Developer Portal → Account Settings → General → Communications Content Storage Location
See ../general/use-cases/video-sdk-bring-your-own-storage.md for complete setup guide.
Video SDK功能 - Zoom将云录制内容直接保存到您的Amazon S3存储桶,无需下载。
前置条件:
- 带有云录制附加组件的Video SDK账户(通用信用包含此功能)
- AWS S3存储桶
认证选项:
- AWS访问密钥 - 设置更简单
- 跨账户访问 - 更安全(IAM角色假设)
S3路径结构:
Buckets/{bucketName}/cmr/byos/{YYYY}/{MM}/{DD}/{GUID}/cmr_byos/核心优势:
- 零下载带宽成本
- 录制时直接存储
- 仅需配置(无需Webhook或下载代码)
设置位置: 开发者门户 → 账户设置 → 常规 → 通信内容存储位置
查看**../general/use-cases/video-sdk-bring-your-own-storage.md**获取完整设置指南。
Detailed References
详细参考文档
UI & Components
UI与组件
- references/ui-toolkit.md - Pre-built UI components (Web)
- references/triage-intake.md - What to ask first (turn vague reports into answers)
- references/session-lifecycle.md - Correct API ordering + event-driven rendering
- references/licensing-and-entitlements.md - License/admin prerequisites
- references/token-contract-test-spec.md - Shared backend token contract and cross-platform smoke test
- references/ui-toolkit.md - 预构建UI组件(Web端)
- references/triage-intake.md - 首次沟通要点(将模糊需求转化为明确问题)
- references/session-lifecycle.md - 正确的API调用顺序 + 事件驱动渲染
- references/licensing-and-entitlements.md - 许可证/管理员前置条件
- references/token-contract-test-spec.md - 共享后端令牌契约与跨平台冒烟测试
Platform Guides
平台指南
- references/authorization.md - Video SDK JWT generation
- web/SKILL.md - Web Video SDK (JavaScript/TypeScript)
- web/SKILL.md - Complete documentation navigation
- web/examples/react-hooks.md - Official React hooks library
- web/examples/framework-integrations.md - Next.js, Vue/Nuxt patterns
- react-native/SKILL.md - React Native Video SDK (mobile wrapper, helper/event architecture)
- react-native/SKILL.md - React Native documentation navigation
- react-native/examples/session-join-pattern.md - Tokenized session join flow
- flutter/SKILL.md - Flutter Video SDK (mobile wrapper, event-driven architecture)
- flutter/SKILL.md - Flutter documentation navigation
- flutter/examples/session-join-pattern.md - Tokenized session join flow
- android/SKILL.md - Android Video SDK (native mobile custom UI, tokenized sessions)
- ios/SKILL.md - iOS Video SDK (native mobile custom UI, delegate-driven lifecycle)
- macos/SKILL.md - macOS Video SDK (desktop native apps, custom session windows)
- unity/SKILL.md - Unity Video SDK wrapper (game-engine integration, scene-driven UX)
- linux/SKILL.md - Linux Video SDK overview (C++ headless bots)
- linux/linux.md - Linux C++ SDK (headless bots, raw media capture/injection)
- linux/references/linux-reference.md - Linux API Reference
- windows/SKILL.md - Windows C++ SDK (desktop applications, raw media capture/injection)
- windows/references/windows-reference.md - Windows API Reference
- references/troubleshooting.md - Common issues and solutions
- references/forum-top-questions.md - Common forum question patterns (what to cover)
- references/authorization.md - Video SDK JWT生成
- web/SKILL.md - Web端Video SDK(JavaScript/TypeScript)
- web/SKILL.md - 完整文档导航
- web/examples/react-hooks.md - 官方React Hooks库
- web/examples/framework-integrations.md - Next.js、Vue/Nuxt集成模式
- react-native/SKILL.md - React Native Video SDK(移动端封装,辅助/事件架构)
- react-native/SKILL.md - React Native文档导航
- react-native/examples/session-join-pattern.md - 令牌化会话加入流程
- flutter/SKILL.md - Flutter Video SDK(移动端封装,事件驱动架构)
- flutter/SKILL.md - Flutter文档导航
- flutter/examples/session-join-pattern.md - 令牌化会话加入流程
- android/SKILL.md - Android Video SDK(原生移动端自定义UI,令牌化会话)
- ios/SKILL.md - iOS Video SDK(原生移动端自定义UI,委托驱动生命周期)
- macos/SKILL.md - macOS Video SDK(桌面原生应用,自定义会话窗口)
- unity/SKILL.md - Unity Video SDK封装(游戏引擎集成,场景驱动用户体验)
- linux/SKILL.md - Linux Video SDK概述(C++无头机器人)
- linux/linux.md - Linux C++ SDK(无头机器人,原始媒体捕获/注入)
- linux/references/linux-reference.md - Linux API参考
- windows/SKILL.md - Windows C++ SDK(桌面应用,原始媒体捕获/注入)
- windows/references/windows-reference.md - Windows API参考
- references/troubleshooting.md - 常见问题与解决方案
- references/forum-top-questions.md - 论坛常见问题模式(需覆盖的要点)
Sample Repositories
示例代码仓库
Official (by Zoom)
Zoom官方仓库
| Type | Repository | Stars |
|---|---|---|
| Web | videosdk-web-sample | 137 |
| Web NPM | videosdk-web | 56 |
| Auth | videosdk-auth-endpoint-sample | 23 |
| UI Toolkit Web | videosdk-zoom-ui-toolkit-web | 17 |
| UI Toolkit React | videosdk-zoom-ui-toolkit-react-sample | 17 |
| Next.js | videosdk-nextjs-quickstart | 16 |
| Telehealth | VideoSDK-Web-Telehealth | 11 |
| Linux | videosdk-linux-raw-recording-sample | - |
Full list: See general/references/community-repos.md
| 类型 | 仓库地址 | 星标数 |
|---|---|---|
| Web | videosdk-web-sample | 137 |
| Web NPM | videosdk-web | 56 |
| 认证 | videosdk-auth-endpoint-sample | 23 |
| UI Toolkit Web | videosdk-zoom-ui-toolkit-web | 17 |
| UI Toolkit React | videosdk-zoom-ui-toolkit-react-sample | 17 |
| Next.js | videosdk-nextjs-quickstart | 16 |
| 远程医疗 | VideoSDK-Web-Telehealth | 11 |
| Linux | videosdk-linux-raw-recording-sample | - |
完整列表: 查看general/references/community-repos.md
Resources
资源
- Official docs: https://developers.zoom.us/docs/video-sdk/
- Developer forum: https://devforum.zoom.us/
Environment Variables
环境变量
- See references/environment-variables.md for standardized keys and where to find each value.
.env
- 查看references/environment-variables.md获取标准化的密钥及各值的获取位置。
.env
Linux Operations
Linux操作指南
- linux/RUNBOOK.md - Linux platform preflight and debugging checklist.
- linux/RUNBOOK.md - Linux平台预检与故障排查清单。