如何快速实现小程序1v1实时音视频通话?
本文将详细介绍如何使用ZEGO SDK结合微信小程序能力,快速实现低延迟、高稳定的一对一/多人实时音视频通话。相比微信原生<live-pusher>/<live-player>组件,即构封装的<zego-pusher>与<zego-player>组件更简洁、兼容性更好,适合快速落地在线客服、视频问诊、在线会议、社交互动等场景。
一、典型应用场景
小程序音视频通话无需用户下载额外App,触达率高,适配多行业高频需求,核心典型场景如下:
-
一对一社交互动:陌生人匹配聊天、好友视频通话、情侣互动等,依托小程序轻量化特性,无需跳转,点击即可发起通话,提升用户留存。
-
在线咨询服务:电商客服视频答疑、教育机构试听课、心理咨询视频沟通、房产/汽车远程带看等,实现“面对面”高效沟通,提升转化。
-
医疗健康场景:在线问诊、远程复诊、慢病随访等,患者无需到院,通过小程序即可与医生实时视频沟通,降低就医成本。
-
多人协同场景:小型团队会议、线上班会、家庭视频团聚等,支持多人同时接入,低延迟不卡顿,适配轻量化协同需求。
-
合规审核场景:实名认证视频核验、企业资质视频审核、网约车司机人脸核验等,通过实时音视频完成身份确认,保障合规性。
二、实现微信小程序音视频通话的前提条件
在开始开发前,请确保完成以下准备:
-
已在项目中集成 ZEGO SDK(建议 2.10.0 及以上版本),参考官方集成文档完成引入。
-
已在ZEGO 控制台创建项目,获取有效的
AppID、Server地址与Token(用于鉴权)。 -
微信小程序基础库 ≥ 2.10.0,微信 App 版本 ≥ 7.0.9。
-
已在微信公众平台完成类目与权限开通(社交-直播、教育、医疗等合规类目),并开启实时播放音视频流、实时录制音视频流权限。
三、ZEGO音视频SDK实现流程
用户通过 ZEGO Express SDK 进行视频通话的基本流程为:
用户 A、B 加入房间,用户 B 预览并将音视频流推送到 ZEGO 云服务(推流),用户 A 收到用户 B 推送音视频流的通知之后,在通知中播放用户 B 的音视频流(拉流)

3.1 配置微信小程序后台
在初始化 SDK 前,需要在微信公众平台中进行如下配置:
-
服务器域名配置:在“小程序后台 > 开发管理 > 开发设置 > 服务器域名”中,按照协议分类,将即构
Server 地址、LogUrl、以及用户业务需要用到的地址填到指定的“socket合法域名”或“request合法域名”中,详情请参考 控制台 - 项目信息。
注意
控制台提供的
Server 地址格式为:wss://xxxxxxxxxx.com/ws。在 微信公众平台 填写时,不能直接复制原地址,需要删除原地址的 “/ws”,应填入地址的格式为:wss://xxxxxxxxxx.com。控制台提供的
LogUrl地址格式为:https://xxxxxxxxxx.com/httplog。在 微信公众平台 填写时,不能直接复制原地址,需要删除原地址的 “/httplog”,应填入地址的格式为:https://xxxxxxxxxx.com。如果您使用 3.0.0 或以上版本(包括 3.6.0 及以上版本)的 SDK,还需要添加一些 socket 域名,详情请参考 3.0.0 及以上版本升级指南。
如果您使用 3.6.0 或以上版本的 SDK,还需要添加一些 request 域名,详情请参考 3.6.0 及以上版本升级指南。

-
相关功能开启:在“小程序后台 > 开发管理 > 接口设置 > 接口权限”中,打开 实时播放音视频流 和 实时录制音视频流 功能开关。

-
由于使用摄像头或者麦克风涉及到用户隐私,请参考微信官方文档 配置小程序用户隐私保护指引 补充相应用户隐私保护指引。否则,当您的项目部署到正式环境时,将无法推流。
3.2 初始化
1.创建界面
根据场景需要,为您的项目创建视频通话的用户界面。我们推荐您在项目中添加如下元素:
-
本地预览窗口
-
远端视频窗口
-
结束按钮

参考界面代码:
<view wx:if="{{canShow== 1}}" class="">
<view class="containerBase">
<zego-pusher id="zegoPusher" pusher="{{pusher}}" />
<zego-player wx:for="{{zegoPlayerList}}" wx:key="id" id="{{item.componentID}}" playerId="{{item.playerId}}"
playerList="{{playerList}}" />
</view>
<view class="index-container">
<view class='input-container'>
<input value="{{roomID}}" bindinput="bindKeyInput" placeholder="请输入房间 ID" placeholder-style='color: #b3b3b3; font-size: 14px;' class="room-input" />
<text class="tip"></text>
</view>
<view class="button-container">
<button bindtap="openRoom" data-role="1" data-option="videoAndAudio" hover-class="none" class="openRoom">
加入房间(推流)
</button>
<button bindtap="logout" hover-class="none">退出房间</button>
</view>
</view>
</view>
<view class="settings">
<button wx:if="{{canShow==0}}" open-type="openSetting" bindopensetting="settingCallback">
授权使用摄像头和麦克风
</button>
</view>
2.创建引擎
创建 ZegoExpressEngine 引擎实例,将申请到的 AppID 传入参数 “appID”,将获取到的 Server 地址传入参数 “server”。
// 初始化实例,server 参数可直接填空字符串
zg = new ZegoExpressEngine(appID, server);
注意
若使用 3.6.0 及以上版本 SDK,
server参数可填写控制台获取的Server 地址或者直接填空字符串。
3.设置回调
创建引擎后,开发者可根据实际需要,通过引擎实例的 on 方法设置回调。
注意
为避免错过事件通知,建议在创建引擎后立即监听回调
zg.on('roomStateUpdate', (roomID, state, errorCode, extendedData) => {
if (state == 'DISCONNECTED') {
// 与房间断开了连接
// ...
}
if (state == 'CONNECTING') {
// 与房间尝试连接中
// ...
}
if (state == 'CONNECTED') {
// 与房间连接成功
// ...
}
})
3.3 登录房间
1. 获取登录 Token
登录房间需要用于验证身份的 Token,获取方式请参考 用户权限控制。如需快速调试,建议使用控制台生成的临时 Token,生成临时 Token 的具体操作请参考 控制台 - 项目管理。
2. 登录房间
您可以调用 SDK 的 loginRoom 接口,传入房间 ID 参数 “roomID”、“token” 和用户参数 “user”,登录房间。如果房间不存在,调用该接口时会创建并登录此房间。
您可通过监听 roomStateUpdate 回调实时监控自己在本房间内的连接状态,具体请参考 常见通知回调 中的“我在房间内的连接状态变化通知”。
roomID 和 user 的参数由您本地生成,但是需要满足以下条件:
-
同一个 AppID 内,需保证 “roomID” 全局唯一。
-
同一个 AppID 内,需保证 “userID” 全局唯一,建议开发者将 “userID” 与自己业务的账号系统进行关联。
-
“userID” 必须与生成 token 时传入的 userID 保持一致,否则登录失败。
注意
为避免错过任何通知,建议在登录房间前先设置监听回调(如房间状态、用户状态、流状态、推拉流状态等),具体请参考 常见通知回调。
// 登录房间,成功则返回 true
const result = await zg.loginRoom(roomID, token, {
userID: "user1", // userID,需用户自己定义,保证全局唯一,建议设置为业务系统中的用户唯一标识
userName: "user1_name" // userName 用户名
}, {
userUpdate: true // 是否接收用户进出房间的回调,设置为 true 才能接收到房间内其他用户进出房间的回调
});
3.4 初始化小程序组件实例
调用 initContext 接口初始化小程序组件。
组件中用于存储推流属性 pusher 和拉流属性列表 playerList 的两个字段需要传给 SDK,SDK 后续将通过传入的两个字段对相应的推拉流作状态及视图更新处理。
-
pusher 字段中的属性值请参考 ZegoWxPusherAttributes。
-
playerlist 字段中的属性值请参考 ZegoWxPlayerAttributes。
zg.initContext({
wxContext: this,
pushAtr: "pusher", // pushAtr 配置的变量名,必须与传给 <zego-pusher> 组件 pusher 属性的变量名完全一致。
playAtr: "playerList" // playAtr 配置的变量名,必须与传给 <zego-player> 组件 playerList 属性的变量名完全一致。
})
3.4 创建对应业务场景的 WXML
1.复制组件代码到项目工程中
将示例代码 components 文件夹下的 zego-player 和 zego-pusher 两个文件夹,复制到您的业务代码 components 文件夹中。
2. 在项目 JSON 文件中引入组件
根据您的项目结构,在对应的 JSON 文件中引入 <zego-pusher> 和 <zego-player> 组件。
// 在 JSON 文件中引入组件
{
"usingComponents": {
"zego-pusher": "../../components/zego-pusher/zego-pusher",
"zego-player": "../../components/zego-player/zego-player"
}
}
3.5 在 WXML 文件中使用推拉流组件
在 WXML 文件中使用推拉流组件 <zego-pusher> 和 <zego-player> 。
// 在 WXML 文件中使用组件
// 传给 <zego-pusher> 组件 pusher 属性的变量名,必须与 initContext 配置中 pushAtr 的参数值完全一致。
<zego-pusher id="zegoPusher" pusher="{{pusher}}" />
// 传给 <zego-player> 组件 playerList 属性的变量名,必须与 initContext 配置中 playAtr 的参数值完全一致。zegoPlayerList 见 “拉取其他用户的音视频” 章节。
<zego-player wx:for="{{zegoPlayerList}}" wx:key="id" id="{{item.componentID}}" playerId="{{item.playerId}}" playerList="{{playerList}}" />
3.6 推送音视频流到 ZEGO 音视频云
必须完成初始化小程序组件实例和创建业务场景的 WXML 之后,才能调用 SDK 接口创建推流和拉流实例。
用户先获取 <zego-pusher> 组件的实例对象,再调用该对象的 startPush 方法传入 SDK 实例和 streamID 参数即可发起推流。
// 获取 <zego-pusher> 组件实例对象
const zegoPusher = this.selectComponent("#zegoPusher");
// 调用 <zego-pusher> 实例对象的 startPush 方法进行推流。zg 为 SDK 实例对象,"streamID_xxx" 为 streamID。
await zegoPusher.startPush(zg, "streamID_xxx");
注意
您可通过监听 publisherStateUpdate 回调知晓推流是否成功
streamID由您本地生成,但是需要保证:
同一个 AppID 下,
streamID全局唯一。如果同一个 AppID 下,不同用户各推了一条streamID相同的流,后推流的用户推流失败。
streamID长度不超过 256 字节的字符串。仅支持数字、英文字符和 "-"、"_"。
3.7 拉取其他用户的音视频
进行视频通话时,我们需要拉取到其他用户的音视频。
用户先获取 <zego-player> 组件实例对象,再调用 该对象的 startPlay 方法传入 SDK 实例和 streamID 参数即可发起拉流。
远端用户推送的 “streamID” 可以从 roomStreamUpdate 回调中获得
// 在 SDK 的回调 roomStreamUpdate 中获取拉流 streamID
// 当房间内其他用户推的流增加或减少时触发
zg.on("roomStreamUpdate", async (roomID, updateType, streamList) => {
if (updateType === "ADD") {
// ----- 使用 zego-player 组件的 startPlay 接口播放 -----
for (let i = 0; i < streamList.length; i++) {
try {
// 设置 zego-player 组件属性
const zegoPlayerAttr = {
componentID: `zego-${streamList[i].streamID}`,
playerId: streamList[i].streamID
}
// 添加到组件列表中
this.data.zegoPlayerList.push(zegoPlayerAttr)
// 更新,并渲染组件列表
this.setData({
zegoPlayerList:this.data.zegoPlayerList
})
// 在zegoPlayerList更新后, 将zg实例传入对应的流id的组件内
const zegoPlayer = this.selectComponent(`#${zegoPlayerAttr.componentID}`)
if (!zegoPlayer) return console.warn("未能获取到组件节点", streamList[i].streamID)
// 开始播放
console.warn("开始拉流", roomID, streamList[i].streamID);
await zegoPlayer.startPlay(zg, streamList[i].streamID)
} catch (error) {
console.error("拉流出错,等待房间重连恢复", error)
}
}
} else if (updateType === 'DELETE') {
// 流删除,停止拉流
}
});
注意
如果用户在音视频通话的过程中遇到相关错误,可查询 常见错误码。
3.8 停止音视频通话
停止推送和拉取音视频流
1.停止推流
用户先获取 <zego-pusher> 组件实例对象,再调用该对象的 stopPush 方法结束拉流。
// 停止推流
// 获取 <zego-pusher> 组件实例对象
const zegoPusher = this.selectComponent("#zegoPusher");
// 调用 <zego-pusher> 实例对象的 stopPush 方法停止推流。
await zegoPusher.stopPush();
2.停止拉流
用户先获取 <zego-player> 组件实例对象,再调用该对象的 stopPlay 方法结束拉流。
// 停止拉流
// 获取 <zego-player> 组件实例对象
const zegoPlayer = this.selectComponent(`#${zegoPlayerAttr.componentID}`);
// 调用 <zego-player> 实例对象的 stopPlay 方法停止拉流。
await zegoPlayer.stopPlay();
3.退出房间
调用 SDK 的 logoutRoom 接口退出房间。
zg.logoutRoom(roomID);
4.销毁引擎
如果用户彻底不使用音视频功能时,可调用 destroyEngine 接口销毁引擎,释放麦克风、摄像头、内存、CPU 等资源。
zg.destroyEngine();
zg = null;
3.9视频通话 API 调用时序
整个推拉流过程的 API 调用时序可参考下图:

四、调试与常见问题
-
真机调试:开发者工具不支持推拉流,必须用真机预览/真机调试。
-
域名与权限:检查 socket/request 域名、实时音视频权限、隐私协议。
-
Token 鉴权:userID 必须与生成 Token 时一致,否则登录失败。
-
streamID 唯一:同一 AppID 下不可重复,否则推流失败。
-
互通测试:使用 ZEGO Web 端调试页,输入相同 AppID、RoomID、Token 即可与小程序互通。
五、总结
通过ZEGO SDK,只需初始化引擎 → 登录房间 → 推流 → 自动拉流四步,即可快速实现微信小程序音视频通话。即构组件封装了原生组件的复杂配置与兼容性问题,支持一对一、多人通话,延迟低、抗丢包强,可直接用于线上生产环境,适配各类音视频场景需求。
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)