Web
本文以实现音视频通话为例,结合 SDK API 和示例代码,介绍如何快速接入。
如需查看完整 SDK API 列表,请点击左侧导航 SDK API 部分。
导入SDK
可以通过 2 种方式来导入 SDK。
- 方式1:NPM 安装
- 通过命令行工具执行
npm install @pano.video/panortc
命令即可获取 Web SDK 包。- 某些工具(例如 VSCode 默认的 powershell)需要在包名前后添加引号:
npm install '@pano.video/panortc'
- 某些工具(例如 VSCode 默认的 powershell)需要在包名前后添加引号:
- 通过代码
import PanoRtc from '@pano.video/panortc'
导入 SDK。
- 通过命令行工具执行
- 方式2:导入 JS 文件
- 请到 下载中心 下载 Web SDK 包,解压后得到 JS 文件。
- 通过
<script>
标签导入 JS 文件。
配置权限
除 localhost(127.0.0.1) 外的其他域名,必须部署 HTTPS 才能访问摄像头和麦克风。
当浏览器弹出想要"使用摄像头"和"使用你的麦克风"之类的提示时,请点击 允许。
否则可能会出现报错:Uncaught TypeError: Cannot read property 'enumerateDevices' of undefined
。
初始化
通过 new PanoRtc.RtcEngine(appId)
初始化 RtcEngine
实例。
const rtcEngine = new PanoRtc.RtcEngine(appId); // 下文均使用 rtcEngine 作为 RtcEngine 实例名
请登录 Pano控制台,点击左侧导航 应用管理 ,查看应用ID(即
appId
)。
注册通知
通过 RtcEngine
实例的 on
方法注册回调通知,通过 off
或 removeAllListeners
方法移除通知。
注意:必须尽早注册通知,以免错过某些通知。
function joinChannelConfirmCB(data){
// 处理自己加入频道的通知
}
function leaveChannelIndicationCB(data){
// 处理自己被动离开频道的通知
}
function userJoinCB(data){
// 处理其他用户加入频道的通知
}
function userLeaveCB(data){
// 其他用户离开频道的通知
}
// 注册各种通知
rtcEngine.on(PanoRtc.RtcEngine.Events.joinChannelConfirm, joinChannelConfirmCB);
rtcEngine.on(PanoRtc.RtcEngine.Events.leaveChannelIndication, leaveChannelIndicationCB);
rtcEngine.on(PanoRtc.RtcEngine.Events.userJoin, userJoinCB);
rtcEngine.on(PanoRtc.RtcEngine.Events.userLeave, userLeaveCB);
// 移除通知
// 方式一:使用 off 方法,格式为:off(event, cb),其中 cb 表示特定的单个回调函数
// [注意] 通过匿名函数或箭头函数注册的通知函数,无法使用 off 方法移除,请使用下文 removeAllListeners 方法
rtcEngine.off(PanoRtc.RtcEngine.Events.joinChannelConfirm, joinChannelConfirmCB);
// 方式二:使用 removeAllListeners 方法移除指定通知类型的所有监听器,格式为:removeAllListeners(event)
rtcEngine.removeAllListeners(PanoRtc.RtcEngine.Events.joinChannelConfirm);
// 方式三:使用 removeAllListeners 方法移除所有的监听器,格式为:removeAllListeners()
rtcEngine.removeAllListeners();
以上仅为部分通知示例,完整的通知列表,请查看 RtcEngine.Events。
获取摄像头列表
通过 RtcEngine
实例的 getCams
方法获取摄像头列表。
rtcEngine.getCams(devices => {
// 请保存返回的数组元素的 deviceId 以便稍后用于 本地预览、发送视频 等
console.log('getCams devices:', devices);
}, error => {
console.error('getCams error:', error);
});
本地预览
通过 RtcEngine
实例的 startPreview
方法开启本地摄像头预览。
// 第一个参数为 deviceId ,需要预先通过 getCams 获取后传入
// 从 1.4.9 版本开始,增加第四个可选参数,类型为 VideoProfileName,表示"视频分辨率"
rtcEngine.startPreview(
deviceId,
videoTag => {
// 将 videoTag 添加到 UI 布局中(可以通过 CSS 控制 videoTag),例如:
// videoTag.setAttribute('style', 'width: 160px; height: 90px; object-fit: contain;');
// previewVideoContainer.appendChild(videoTag);
},
error => {
console.error('startPreview error:', error);
},
PanoRtc.Constants.VideoProfileName.HD720P
);
如果有多个摄像头,需要切换预览时:
- 先通过
RtcEngine
实例的stopPreview(videoTag: HTMLVideoElement)
方法停止当前预览;- 重新调用
startPreview
方法传入新的deviceId
,并获取新的videoTag
用于显示预览。
加入频道
加入频道
通过 RtcEngine
实例的 joinChannel
方法加入频道。
// 此方法有两个参数:channelParam(必须)、optionalConfig(可选)
rtcEngine.joinChannel({
channelId: '...',
// channelMode 频道模式:Web SDK 仅支持 TYPE_MEETING (会议模式)
channelMode: PanoRtc.Constants.ChannelMode.TYPE_MEETING,
token: '...',
userId: '...',
userName: '...',
// 如果 subscribeAudioAll 配置为 true,SDK 会自动订阅音频
// 如果配置为 false,需要开发者自行订阅音频
subscribeAudioAll: true
}, {
// joinChannelType 默认值为 mediaAndWhiteboard
joinChannelType: PanoRtc.Constants.JoinChannelType.mediaOnly
});
- 这些参数有一定的要求,例如:
channelId
、token
、userId
、userName
都为String
类型,更多内容请查看 joinChannel 接口文档详细了解。- 另请参考 名词解释 了解
channelId
、token
、userId
、userName
的作用。userId
号段 [0xFFFEFF0000000000, 0xFFFEFFFFFFFFFFFF] (18446461499221213184 - 18446462598732840959) 保留给 PANO 内部使用,开发者请勿使用 ,否则会返回错误。- 可以使用 临时token 来进行临时测试。
- 对于私有化环境,加入频道之前,请通过
RtcEngine.setServer('https://server.domain')
类方法配置服务器地址(server.domain
为示意,请按实际情况配置;公有云无需此配置)。
自己加入频道的通知
调用 joinChannel
方法后,将触发 joinChannelConfirm
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.joinChannelConfirm, data => {
// data 中将返回 result、code、message,result 为 'success' 表示加入频道成功,其他表示加入频道失败
});
其他用户加入频道的通知
其他用户加入频道时,将触发 userJoin
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.userJoin, data => {
// 返回 userId 和 user 信息,可将其加入到与会者列表中
});
倒计时通知
加入频道后,如果存在倒计时限制,将触发 channelCountDown
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.channelCountDown, data => {
// 请保存 data.remainsec 用于展示倒计时,此回调仅在加入频道后回调一次,单位为秒
});
- 已实名认证,并且使用正式token,Pano不限制频道时长
- 未实名认证,或者使用临时token,最大频道时长为 30 分钟
操作视频
发送本地视频
加入频道成功后,通过 RtcEngine
实例的 startVideo
方法发送本地视频。
/* # 调用 startVideo 方法后,其他用户才能看到你的画面
# 可以按需指定发送分辨率(VideoProfileType),SDK 将尝试发送指定的分辨率
实际发送分辨率受硬件配置、浏览器环境、订阅情况、网络状态等因素综合影响,可能会比指定的低
# 2.1.4 版本起,startVideo 方法增加可选的 sourceMirror 参数
当 sourceMirror 参数设置为 true 后,本地渲染和发送的视频都是镜像模式
# 如果只需要本地渲染镜像,不需要发送的视频镜像,请不要配置 sourceMirror 参数
而是通过 CSS 控制本地渲染镜像,请见下文介绍
*/
rtcEngine.startVideo(PanoRtc.Constants.VideoProfileType.HD720P, true);
VideoProfileType
表示分辨率档位,具体可选值请点此查看,可按需配置。- 如果有多个摄像头,默认发送第 0 个摄像头,需要切换发送时,请调用
RtcEngine
实例的selectCam(deviceId: string)
方法传入摄像头 ID。
如果发送本地视频成功,会触发 getLocalVideo
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.getLocalVideo, data => {
// 发送本地视频成功,可将 data.data.videoTag 添加到 UI 布局中用于展示自己的画面
// 可以通过 CSS 控制 videoTag 的渲染镜像:
// transform: rotateY(180deg);
});
如果发送本地视频超时失败,会触发 startVideoTimeout
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.startVideoTimeout, () => {
// 发送本地视频超时失败
});
停止发送本地视频
通过 RtcEngine
实例的 stopVideo
方法停止发送本地视频。
rtcEngine.stopVideo(); // 调用此方法后,其他用户将看不到你的画面;本地预览不会被停止
其他用户开启视频的通知
当其他用户发送视频时,将触发 userVideoStart
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.userVideoStart, data => {
// userId: "...", // 请保存 data.userId 以便稍后订阅其视频
// maxVideoProfile: "..."
/* 1.3.3 版本开始,可以通过 data.maxVideoProfile 参数获取该用户的最大可发送分辨率
取决于 摄像头支持的最大分辨率 和 设置的发送分辨率 这两个值中的较小值
*/
});
订阅其他用户的视频
通过 RtcEngine
实例的 subscribeVideo
方法订阅其他用户的视频。
// 请在收到其他用户的 userVideoStart 通知后,再调用订阅
rtcEngine.subscribeVideo({
// 可以根据显示窗口的大小来决定订阅分辨率,比如大窗口订阅高分辨率,小窗口订阅低分辨率
// 此处示例订阅 1280 x 720,实际使用请按需配置
quality: PanoRtc.Constants.VideoProfileType.HD720P,
userId: '...' // 对方的userId
});
- Pano采用订阅模式来接收视频,参与者之间需要相互订阅,才可以看到彼此的视频画面。
- 默认 正式token 最多可以订阅 10 路视频,临时token 最多可以订阅 3 路视频。
- 如果订阅失败,会触发
failedToSubscribeVideo
通知。
收到其他用户视频的通知
当收到其他用户的视频时,将触发 userVideoReceived
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.userVideoReceived, data => {
// data.data 中将返回 videoTag、userId、userName,可以用于信息展示
// 将 videoTag 添加到 UI 布局中(可以通过 CSS 控制 videoTag)
});
取消订阅其他用户的视频
通过 RtcEngine
实例的 unsubscribeVideo
方法取消订阅其他用户的视频。
// 调用此方法后,你将看不到该用户的画面
rtcEngine.unsubscribeVideo({
userId: ''
});
操作声音
发送本地声音
通过 RtcEngine
实例的 startAudio
方法发送本地声音。
rtcEngine.startAudio(); // 调用此方法后,其他用户才能听到你的声音;请在加入频道成功后再调用
如果发送本地声音超时失败,会触发 startAudioTimeout
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.startAudioTimeout, () => {
// 发送本地声音超时失败
});
停止发送本地声音
通过 RtcEngine
实例的 stopAudio
方法停止发送本地声音。
// 调用此方法后,其他用户将听不到你的声音
// 不影响通过"屏幕共享"功能共享的系统声音
// 不影响你接收其他用户的声音
// 可以调用 startAudio 重新发送
rtcEngine.stopAudio();
静音麦克风
通过 RtcEngine
实例的 muteMic
方法静音本地麦克风。
rtcEngine.muteMic(); // 调用此方法后,其他用户将听不到你的麦克风的声音
停止发送本地声音(
stopAudio
) 和 静音本地麦克风(muteMic
) 这两个接口都可以将自己静音(不让其他用户听到你的声音)。它们的区别在于:
1 "停止发送本地声音"会断开音频通道连接(同时会取消其他用户订阅你的声音,如需重建连接需要消耗时间)
2 "静音本地麦克风"会发送静音包(不影响订阅关系,静音包数据量很小,临时静音建议使用此方式,取消静音能够迅速恢复发送声音)
取消静音麦克风
通过 RtcEngine
实例的 unmuteMic
方法取消静音本地麦克风。
rtcEngine.unmuteMic(); // 静音麦克风后,需要取消静音,其他用户才能听到你的麦克风的声音
其他用户开启声音的通知
当其他用户发送声音时,将触发 userAudioStart
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.userAudioStart, data => {
console.log('userAudioStart', data);
});
订阅其他用户的声音
- 如果在 加入频道 时配置了
subscribeAudioAll: true
,SDK 会自动订阅其他所有用户的声音,开发者无需手工操作。 - 如果配置了
subscribeAudioAll: false
,开发者可以在收到 其他用户开启声音的通知 后,通过RtcEngine
实例的subscribeAudio
方法订阅其声音。
rtcEngine.on(PanoRtc.RtcEngine.Events.userAudioStart, data => {
rtcEngine.subscribeAudio(data.userId); // 可以在此时订阅该用户的声音
});
取消订阅其他用户的声音
可以通过 RtcEngine
实例的 unsubscribeAudio
方法取消订阅其他用户的声音。
如果在 加入频道 时配置
subscribeAudioAll: true
,SDK 将自动订阅声音,开发者无法主动取消订阅。
当配置 subscribeAudioAll: false
时,典型的需要取消订阅声音的场景例如:
- 不需要再听到某位用户的声音,可以主动取消订阅其声音;
- 收到其他用户停止发送声音的通知时,应取消订阅其声音。
rtcEngine.on(PanoRtc.RtcEngine.Events.userAudioStop, data => {
// 收到其他用户停止发送声音的通知,如果配置了"subscribeAudioAll: false",此时应取消订阅其声音
rtcEngine.unsubscribeAudio(data.userId);
});
离开频道
离开频道
通过 RtcEngine
实例的 leaveChannel
方法离开频道。
rtcEngine.leaveChannel();
注意:调用此接口主动离开频道,自己不会收到
leaveChannelIndication
回调。
其他用户离开频道的通知
其他用户离开频道后,将触发 userLeave
通知。
rtcEngine.on(PanoRtc.RtcEngine.Events.userLeave, data => {
// 返回 userId 信息,可将其从与会者列表中移除
};
释放资源
通过 RtcEngine
实例的 destroy
方法释放资源。
rtcEngine.destroy();
反馈问题
我们强烈建议您集成反馈功能,以便用户遇到问题时,可以提交信息给我们分析排查,具体请 点此查看。
SDK API 指南
本文仅介绍接入Pano Web SDK实现视频通话的基本流程和接口。
实际场景可能需要结合使用更多接口,请 点此查看 API 列表。
示例代码
为方便开发者了解丰富的接口使用方式,我们还提供示例代码,请体验参考: