微信小程序视频直播开发实现流程

微信小程序视频直播开发实现流程

2023年6月28日发(作者:)

微信⼩程序视频直播开发实现流程微信⼩程序开发需要基于微信提供的开发者⼯具与 SDK。如果开发者对⼩程序开发流程不熟悉,建议先系统学习:微信⼩程序开发官⽅⽂档。由于微信官⽅⽂档⽐较详细,本⽂对⼩程序开发流程中的框架说明、API 调⽤、组件使⽤等,不再赘述,⽽是重点介绍如何使⽤ ZEGOSDK 开发出⽀持⾳视频直播的微信⼩程序。SDK 集成指引详见:SDK 提供的 API 说明详见:⼩程序开发主要⽤到 web 开发知识( js、html、css )。1、组件说明微信⼩程序中的推拉流功能,需要⽤到微信提供的 live-player live-pusher 标签。其他的常规组件同原⽣ App 开发类似,此处不⼀⼀介绍。1.1 live-playerlive-player 是微信提供的⽀持实时⾳视频播放的组件,官⽅介绍详见组件介绍。开发者创建组件成功后,需要在 js ⽂件中,调⽤ API 操作对应的组件来实现需求,微信官⽅ API 详见 API 说明。即构⾳视频云⼩程序中,创建 live-player 的演⽰源码如下:ZegoLive/pages/liveroom/room/ {{ID}}请注意:1.

live 模式主要⽤于直播类场景,⽐如赛事直播、在线教育、远程培训等等。该模式下,⼩程序内部的模块会优先保证观看体验的流畅,通过调整min-cache 和 max-cache 属性,您可以调节观众(播放)端所感受到的时间延迟的⼤⼩,⽂档下⾯会详细介绍这两个参数。2.

RTC 则主要⽤于双向视频通话或多⼈视频通话场景,⽐如⾦融开会、在线客服、车险定损、培训会议 等等。在此模式下,对min-cache 和 max-cache 的设置不会起作⽤,因为⼩程序内部会⾃动将延迟控制在⼀个很低的⽔平(500ms 左右)。1.2 live-pusherlive-pusher 是微信提供的⽀持实时⾳视频录制的组件,官⽅介绍详见:组件介绍开发者创建组件成功后,需要在 js ⽂件中,调⽤ API 操作对应的组件来实现需求,官⽅ API 详见:API 说明即构⾳视频云⼩程序中,创建 live-pusher 的演⽰源码如下:ZegoLive/pages/liveroom/room/ {{isPublishing ? "我(" + publishStreamID + ")": ""}}请注意:SD、HD 和 FHD 主要⽤于直播类场景,⽐如赛事直播、在线教育、远程培训等等。SD、HD 和 FHD分别对应三种默认的清晰度。该模式下,⼩程序会更加注重清晰度和观看的流畅性,不会过分强调低延迟,也不会为了延迟牺牲画质和流畅性。RTC 则主要⽤于双向视频通话或多⼈视频通话场景,⽐如⾦融开会、在线客服、车险定损、培训会议等等。该模式下,⼩程序会更加注重降低点到点的时延,也会优先保证声⾳的质量,在必要的时候会对画⾯清晰度和画⾯的流畅性进⾏⼀定的缩⽔。2、实现流程2.1 推流 API 调⽤流程图详细讲解请参考 2.6 ⼩节。2.2 拉流 API 调⽤流程图2.3 初始化 SDKZegoLive/pages/liveroom/room/// 声明变量var ZegoSDK = require("../../../js/");var zg;// 初始化实例zg = new ient();// 配置必要参数({ appid: appid, // 必填,应⽤id,由即构分配 idName: idName, // 必填,⽤户⾃定义id,全局唯⼀ nickName: nickName, // 必填,⽤户⾃定义昵称 remoteLogLevel: 1, // 上传⽇志最低级别,建议跟 logLevel ⼀致 logLevel: 1, // ⽇志级别,debug:0,info:1,warn:2,error:3,report:99,disable:100(数字越⼤,⽇志越少),建议选择 1 server: server // 必填,接⼊服务器地址,由即构分配 logUrl: logUrl // 必填,logServer 地址,由即构分配});2.4 获取登录 token登录 token 的获取详见后⽂ 安全⽅案 中的 房间登录安全 ⼩节。即构⼩程序中演⽰源码⽚段如下:ZegoLive/pages/liveroom/room/// 获取登录 tokengetLoginToken: function () { var self = this; const requestTask = t({ url: 'xxxx', // 该接⼝由开发者后台⾃⾏实现,开发者的 Token 从各⾃后台获取 data: { app_id: , id_name: , }, header: { 'content-type': 'text/plain' }, success: function (res) { (">>>[liveroom-room] get login token success. token is: " + ); if (Code != 200) { return; } rStateUpdate(true); oom(, self); }, fail: function (e) { (">>>[liveroom-room] get login token fail, error is: ") (e); } });},2.5 登录房间登录房间成功是后续所有操作的前提。即构⾳视频云⼩程序中演⽰源码⽚段如下,仅供参考:ZegoLive/pages/liveroom/room/(, ype == "anchor" ? 1 : 2, token, function (streamList) { // 登录成功处理 ('>>>[liveroom-room] login succeeded');}, function (err) { // 登录失败处理 ('>>>[liveroom-room] login failed, error is: ', err);});登录错误码列表如下:2.6 单主播直播单主播直播时,⼀个房间内仅有⼀个主播,主播不会与观众进⾏互动。2.6.1 开始推流主播登录房间成功后,根据业务逻辑准备推流。使⽤ SDK 推流播放需要遵循如下步骤:触发推流调⽤ SDK 的 startPublishingStream 获取 streamID 对应的推流地址在 SDK 的回调 onStreamUrlUpdate 中获推流地址调⽤微信⼩程序的 LivePusherContext 创建 live-pusher ,将步骤 3 中获取的推流地址设置为live-pusher 的 url,然后调⽤ live-pusher 的 start() 录制视频演⽰源码⽚段如下,仅供参考:ZegoLive/pages/liveroom/room/// 1/2. 主播登录房间成功后触发推流,调⽤ SDK 的 startPublishingStream 获取 streamID 对应的推流地址(, ype == "anchor" ? 1 : 2, token, function (streamList) { // 主播登录成功即推流 if (ype == 'anchor') { ('>>>[liveroom-room] anchor startPublishingStream, publishStreamID: ' + hStreamID);

ferPublishSourceType(1); // 0:推流到 CDN,观众拉流延迟在 2 秒左右;1:推流到 ZEGO 服务器,延迟在 400ms 左右 ublishingStream(hStreamID, ''); }}, function (err) { ('>>>[liveroom-room] login failed, error is: ', err);});// 3. 在 SDK 的回调 onStreamUrlUpdate 中获取推流地址// type: {play: 0, publish: 1};amUrlUpdate = function (streamid, url, type) { (">>>[liveroom-room] zg onStreamUrlUpdate, streamId: " + streamid + ', type: ' + (type == 0 ? 'play' : 'publish') + ', url: ' + url); ...};// 4. 调⽤微信⼩程序的 LivePusherContext 创建 live-pusher ,将步骤 3 中获取的推流流地址设置为 live-player 的 url,然后调⽤ live-pusher 的 start

录制视频setPushUrl: function (url) { ('>>>[liveroom-room] setPushUrl: ', url); var self = this; ... a({ pushUrl: url, pusherVideoContext : LivePusherContext("video-livePusher", self), }, function () { (); (); });},2.6.2 开始拉流观众登录房间成功后,根据业务逻辑准备拉流。使⽤ SDK 拉流播放需要遵循如下步骤:触发拉流调⽤ SDK 的 startPlayingStream 获取 streamID 对应的播放地址在 SDK 的回调 onStreamUrlUpdate 中获取拉流地址调⽤微信⼩程序的 LivePlayerContext 创建 live-player ,将步骤 3 中获取的推流地址设置为live-player 的 src,然后调⽤ live-player 的 play() 播放视频。此步骤也可以设置 live-player为 autoplay,此时播放器会⾃动播放,⽆需再⼿动调⽤ play()。演⽰源码⽚段如下,仅供参考:ZegoLive/pages/liveroom/room/// 1. 登录后拉流(, ype == "anchor" ? 1 : 2, token, function (streamList) { // 房间内已经有流,拉流 layingStreamList(streamList);}, function (err) { ('>>>[liveroom-room] login failed, error is: ', err);});// 2. 通过 SDK 获取 streamID 对应的播放地址startPlayingStreamList: function (streamList) { var self = this; ... // 设置拉流⽬标地址,可选,0:auto;1:从 bgp 拉流 ferPlaySourceType(1);

// 获取每个 streamID 对应的拉流 url var playStreamList = reamList; for (var i = 0; i < ; i++) { var streamID = streamList[i].stream_id; // 调⽤ SDK 的 startPlayingStream 获取 streamID 对应的播放地址 layingStream(streamID); }},// 3. 在 SDK 的回调 onStreamUrlUpdate 中获取拉流地址// type: {play: 0, publish: 1};amUrlUpdate = function (streamid, url, type) { (">>>[liveroom-room] zg onStreamUrlUpdate, streamId: " + streamid + ', type: ' + (type == 0 ? 'play' : 'publish') + ', url: ' + url); ...};// 4. 调⽤微信⼩程序的 LivePlayerContext 创建 live-player ,将步骤 3 中获取的拉流地址设置为 live-player 的 src,然后调⽤ live-player 的 play() 播放视频。此步骤也可以设置 live-player 为 autoplay,此时播放器会⾃动播放,⽆需再⼿动调⽤ play()setPlayUrl: function (streamid, url, self) { ... // 相同 streamid 的源不存在,创建新 player if (!isStreamRepeated) { streamInfo['streamID'] = streamid; streamInfo['playUrl'] = url; streamInfo['playContext'] = LivePlayerContext(streamid, self); (streamInfo); } ... a({ playStreamList: reamList, }, function(){});},2.6.3 拉流、推流事件处理微信⼩程序会在 live-player 和 live-pusher 的 bindstatechange 绑定的⽅法中通知出推拉流状态事件,开发者需要:在 bindstatechange 绑定的回调函数中,调⽤ SDK 提供的 API updatePlayerState 将推流事件透传给 SDK在 SDK 提供的 onPlayStateUpdate onPublishStateUpdate 回调中处理播推、拉流的开始、失败状态演⽰源码⽚段如下,仅供参考:ZegoLive/pages/liveroom/room/// live-player 绑定的拉流事件onPlayStateChange(e) { // 透传拉流事件给 SDK,type 0 拉流 PlayerState(, e, 0);},// 服务端主动推过来的 流的播放状态, 视频播放状态通知;type: { start:0, stop:1};StateUpdate = function (updatedType, streamID) { (">>>[liveroom-room] zg onPlayStateUpdate, " + (updatedType == 0 ? 'start ' : 'stop ') + streamID);};// live-pusher 绑定推流事件onPushStateChange(e) { // 透传推流事件给 SDK,type 1 推流 PlayerState(hStreamID, e, 1);},// 推流后,服务器主动推过来的,流状态更新;type: { start: 0, stop: 1 },主动停⽌推流没有回调,其他情况均回调ishStateUpdate = function (type, streamid, error) { ('>>>[liveroom-room] zg onPublishStateUpdate, streamid: ' + streamid + ', type: ' + (type == 0 ? 'start' : 'stop') + ', error: ' + error);};另外,⼩程序会在 live-player 和 live-pusher 的 bindnetstatus 绑定的⽅法中通知出推拉流⽹络事件,开发者也需要在对应的⼩程序回调中,调⽤ updatePlayerNetStatus 将推流事件透传给 SDK。演⽰源码⽚段如下,仅供参考:// live-player 绑定⽹络状态事件onPlayNetStateChange(e) { // 透传⽹络状态事件给 SDK,type 0 拉流 PlayerNetStatus(, e, 0);},// SDK 拉流⽹络质量回调QualityUpdate = function (streamId, streamQuality) { ...},// live-pusher 绑定⽹络状态事件onPushNetStateChange(e) { //透传⽹络状态事件给 SDK,type 1 推流 PlayerNetStatus(hStreamID, e, 1);},// SDK 推流⽹络质量回调ishQualityUpdate = function (streamId, streamQuality) { ...},2.6.4 停⽌推、拉流停⽌推拉流,开发者需要:调⽤ SDK 提供的 stopPublishingStream(streamid) stopPlayingStream(streamid) 清空推、拉流状态调⽤ live-pusher 和 live-player 提供的 stop() 停⽌推、拉流请注意,上述第 1 点⼀定要处理,否则可能导致 SDK 状态异常!演⽰源码⽚段如下,仅供参考:// 停⽌拉流ayingStream(reamList[i]['streamID']);reamList[i]['playContext'] && reamList[i]['playContext'].stop();// 停⽌推流blishingStream(hStreamID);();2.7 多主播直播多主播直播是主播与观众连麦,使观众也成为主播的互动功能。视频会议也可通过该模式实现。多主播直播较单主播直播多出了连麦信令交互过程。推流、拉流流程同单主播基本⼀致,本节不再赘述。2.7.1 连麦交互观众申请连麦交互的主要步骤是:观众申请连麦,SDK 接⼝: requestJoinLive主播收到观众的申请连麦,SDK 接⼝: onRecvJoinLiveRequest主播同意/拒绝连麦,SDK 接⼝: respondJoinLive观众或主播结束连麦,SDK 接⼝: endJoinLive主播邀请连麦交互的主要步骤是:主播邀请观众连麦,SDK 接⼝: inviteJoinLive观众收到主播的邀请连麦,SDK 接⼝: onRecvJoinLiveRequest观众同意/拒绝连麦,SDK 接⼝: respondJoinLive主播或观众结束连麦,SDK 接⼝: endJoinLive开发者可按需调⽤ SDK 连麦相关 API。即构⾳视频云⼩程序中演⽰源码⽚段如下,仅供参考:ZegoLive/pages/liveroom/room/// 观众请求连麦requestJoinLive: function () { var self = this; // 观众正在连麦时点击,则结束连麦 if (ishing) { nLive(ID, function(result, userID, userName) { ('>>>[liveroom-room] endJoinLive, result: ' + result); }, null); // 停⽌推流 blishingStream(hStreamID); a({ isPublishing: false, publishTitle : "未推流", }); (); return; } // 观众未连麦,点击开始推流 ('>>>[liveroom-room] audience requestJoinLive'); tJoinLive(ID, null, null, function(result, userID, userName) { tJoinLive(ID, null, null, function(result, userID, userName) { ('>>>[liveroom-room] requestJoinLive, result: ' + result); if (result == false) { ast({ title: '主播拒绝连麦', icon: 'none', duration: 2000 }) } else { ast({ title: '主播同意连麦,准备推流', icon: 'none', duration: 2000 }); // 主播同意连麦后,观众开始推流 ('>>>[liveroom-room] startPublishingStream, userID: ' + userID + ', publishStreamID: ' + hStreamID); ferPublishSourceType(1); // 0:推流到 CDN,观众拉流延迟在 2 秒左右;1:推流到 ZEGO 服务器,延迟在 400ms 左右 ublishingStream(hStreamID, ''); }},// 收到连麦请求JoinLiveRequest = function(requestId, fromUserId, fromUsername, roomId) { ('>>>[liveroom-room] onRecvJoinLiveRequest, roomId: ' + roomId + 'requestUserId: ' + fromUserId + ', requestUsername: ' + fromUsername); var content = '观众 ' + fromUsername + ' 请求连麦,是否允许?'; dal({ title: '提⽰', content: content, success: function(res) { if (m) { ('>>>[liveroom-room] onRecvJoinLiveRequest accept join live'); dJoinLive(requestId, true); // true:同意;false:拒绝

} else if () { ('>>>[liveroom-room] onRecvJoinLiveRequest refuse join live'); dJoinLive(requestId, false); // true:同意;false:拒绝

} } });};2.8 混流混流可以把多路直播的流根据配置信息,输出成⼀路流。开发者可按需调⽤ SDK 混流相关 API。演⽰源码⽚段如下,仅供参考://更新混流配置updateMixStream: function () { ('>>>[liveroom-room] updateMixStream'); var self = this; if (ype !== 'anchor') { return; } var width = 360; var height = 640; var mixConfig = {}; //混流输出流ID StreamId = "mix-" + hStreamID; //混流输出帧率 Fps = 15; Fps = 15; //混流输出码率 Bitrate = 800 * 1000; //混流输出分辨率 Width = width; Height = height; //混流背景⾊ BgColor = 0xc8c8c800; //混流输⼊流信息 List = []; var margin = 0; if (ishing) { var streamInfo = { streamId: hStreamID, top: margin, left: margin, bottom: height - margin, right: width - margin }; (streamInfo); } for (var i = 0; i < ; i++) { var streamId = reamList[i].streamID; var streamInfo = { streamId: streamId, top: 0, left: 0, bottom: 0, right: 0 }; if ( == 0) { = height; = width; } else if ( == 1) { = parseInt(height * 2 / 3); = parseInt(width * 2 / 3); = height; = width; } else if ( == 2) { = parseInt(height * 2 / 3); = 0; = height; = parseInt(width / 3); } (streamInfo); } MixStream(mixConfig, function(mixStreamId, mixStreamInfo) { (">>>[liveroom-room] updateMixStream success"); var rtmpUrls = mixStreamInfo["rtmpUrls"]; for (var i = 0; i < ; i++) { (">>>[liveroom-room] updateMixStream mix Rtmp: " + rtmpUrls[i]); } dal({ title: '提⽰', content: '混流成功', showCancel: false showCancel: false }); }, function(error, info) { (">>>[liveroom-room] updateMixStream error " + ); if (info) { for (var i = 0; i < ; i++) { (">>>[liveroom-room] input stream not exist " + info[i]); } } dal({ title: '提⽰', content: '混流失败', showCancel: false }); });},//停⽌混流stopMixStream: function () { (">>>[liveroom-room] stopMixStream"); var self = this; var mixConfig = {}; StreamId = "mix-" + hStreamID; xStream(mixConfig, undefined, undefined);},3、退后台处理切后台,会停⽌视频采集,但不会禁⽤⾳频采集。开发者可以通过 background-mute 属性来设置是否禁⽤⾳频采集。切后台,会停⽌视频播放,默认退后台静⾳。4、安全⽅案4.1 房间登录安全4.1.1 基本流程⼩程序与业务后台建⽴通信,获取 Token 信息。⼩程序调⽤ 登录 Zego 服务器,传⼊ Token 信息,验证通过后,完成登录。ZegoClient 会保持与 Zego 服务器的长连接,处理发送或接收的消息。⼩程序调⽤ 登出 Zego 服务器。请注意:⽣成 Token 信息需要业务后台⾃⾏开发。4.1.2 login_token 信息login_token 信息为标准 json 格式,具体为:{ "ver": 1, "hash": xxxxx, "nonce": xxxxx, "expired": xxxxx,}字段说明如下:对于 hash 计算中使⽤字段的更详细说明:请注意:1.

login_token 传输过程中,会经过 base64 加密。每次登录都要重新获取 login_token。2.

业务⽅开发的⼩程序需要和业务后台建⽴⼀种安全通讯和鉴权机制,业务⽅使⽤⾃有的账户体系或第三⽅认证体系的登录完成后,业务⽅⼩程序和业务后台交互获取该3.

login_token, AppSecret 是存储在业务后台的。4.2 login_token ⽣成⽰例代码go 语⾔ login_token ⽣成⽰例代码如下:func makeTokenSample(appid uint32, app_key string, idname string, expired_add int64) (ret string, err error){ nonce := UniqueId() expired := ().Unix() + expired_add //单位:秒 app_key = e(app_key, "0x","",-1) app_key = e(app_key, ",", "", -1) if len(app_key) < 32 { return "", ("app_key wrong") } app_key_32 := app_key[0:32] source := f("%d%s%s%s%d",appid,app_key_32,idname,nonce,expired) sum := GetMd5String(source) token := tokenInfo{} = 1 = sum = nonce d = expired buf, err := l(token) if err != nil { return "", err } encodeString := ToString(buf) return encodeString, nil}php 语⾔ login_token ⽣成⽰例代码如下:public function getToken(int $app_id, string $app_key, string $idname, int $expired_add){ $nonce = uniqid(); $expired = time() + $expired_add; //单位:秒 $app_key = str_replace("0x", "", $app_key); $app_key = str_replace(",", "", $app_key); if(strlen($app_key) < 32) { return false; } $app_key_32 = substr($app_key, 0, 32); $source = $app_id.$app_key_32.$idname.$nonce.$expired; $sum = md5($source); $tokenInfo = [ 'ver' => 1, 'hash' => $sum, 'nonce' => $nonce, 'expired' => $expired, ]; $token = base64_encode(json_encode($tokenInfo)); return $token;}java 语⾔ login_token ⽣成⽰例代码如下:package demo;import ject;import eDigest;import AlgorithmException;import ;import ;import 64;public class ZegouUtils { public static void main(String[] args) { String appid = ""; //即构分配的appId String appKey = "0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"; //即构分配的appKey String idName = "xxxxxxx"; //业务系统⽤户唯⼀标识 String Token = getZeGouToken(appid,appKey,idName); n("--Token--:"+Token); } /** * 拉流端获取登录token * @param appId 即构分配的appId * @param appKey 即构分配的appKey * @param idName 业务系统⽤户唯⼀标识 * @return */ public static String getZeGouToken(String appId,String appKey,String idName){ String nonce= UUID().toString().replaceAll("-", ""); long time=new Date().getTime()/1000+30*60; String appKey32=new String(e("0x", "").replace(",", "").substring(0, 32)); n("appKey:"+time+" "+appKey32+" "+nonce); if(()<32){ n("private key erro"); return null; } String sourece= getPwd(appId+appKey32+idName+nonce+time); n("hash:"+sourece); JSONObject json=new JSONObject(); ("ver", 1); ("hash", sourece); ("nonce", nonce); ("expired",time); //unix时间戳,单位为秒 64 base64 = new 64(); n("json"+ng()); return AsString(ng().getBytes()); } /** * 获取MD5加密 * @param pwd 需要加密的字符串 * @return String字符串 加密后的字符串 */ public static String getPwd(String pwd) { try { // 创建加密对象 MessageDigest digest = tance("md5"); // 调⽤加密对象的⽅法,加密的动作已经完成 byte[] bs = (es()); // 接下来,我们要对加密后的结果,进⾏优化,按照mysql的优化思路⾛ // mysql的优化思路: // 第⼀步,将数据全部转换成正数: String hexString = ""; for (byte b : bs) { // 第⼀步,将数据全部转换成正数: int temp = b & 255; // 第⼆步,将所有的数据转换成16进制的形式 // 注意:转换的时候注意if正数>=0&&<16,那么如果使⽤tring(),可能会造成缺少位数 // 因此,需要对temp进⾏判断 if (temp < 16 && temp >= 0) { // ⼿动补上⼀个“0” hexString = hexString + "0" + tring(temp); } else { hexString = hexString + tring(temp); } } return hexString; } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block tackTrace(); } return ""; }}5、状态码5.1 推流状态码onPublishStateUpdate stateCode 含义如下:其他 4 位错误码均为⼩程序框架的报错,请参考:⼩程序官⽅⽂档5.2 拉流状态码onPlayStateUpdate stateCode 含义如下:其他 4 位错误码均为⼩程序框架的报错,请参考:⼩程序官⽅⽂档6、常见错误6.1 登录房间时,控制台输出返回 t解决⽅案: 请检查 初始化配置 ⾥⾯每个参数的类型是否正确,⼀般情况下都是类型不正确引起的问题。6.2 登录房间时,控制台输出返回 result=1000001002原因: 观众⾓⾊不允许创建房间,也就是这个房间不存在。解决⽅案:1)在 ⾥⾯的 ceCreateRoom 设置为 TRUE2)在 ⾥⾯将 role 设置为 1,主播⾓⾊。6.3 登录房间时,控制台输出返回 token Error 的报错原因:计算 token 的时候,算法不对引起,可通过这个链接: 来验证是否正确:1. ⾸先验证 hash 字段是否有错,这⾥要注意 id_name 是 string 类型,不是数值类型; expired 是 uninx 的时间戳,不是北京时间。2. login_token 由业务侧后台⽣成后,将 json ⾥⾯的字段经过 base64 加密后再下发给⼩程序端。详情请参考: 4.1 房间登录安全6.4 ⼩程序如何设置分辨率?微信⼩程序提供设置清晰度的 mode,⽆法指定具体的分辨率,码率和帧率,具体可参考:微信⼩程序组件 live-pusher6.5 ⼩程序如何切换摄像头、截图?微信⼩程序的 LivePusherContext ⾥⾯有提供相关的接⼝,⼤家可参考:微信⼩程序 API LivePusherContext切换摄像头的⽰例代码可参考:7、微信公众平台域名配置ZEGO 分配给开发者的 URL(包含 HTTPS、WSS 协议),需要在微信公众平台进⾏“合法域名”配置后,⼩程序才能正常访问。微信后台配置地址:微信公众平台 -> 设置 -> 开发设置 -> 服务器域名。请开发者将 ZEGO 分配的请求域名,按照协议分类,填到指定的 request合法域名 或者 socket合法域名 中。例如:

发布者:admin,转转请注明出处:http://www.yc00.com/news/1687890467a54309.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信