环信提供开源的多人视频会议项目WebVideoCallDemo,在使用SDK集成App前,您可以参考相关代码
1.可在环信音视频Demo源码下载页面,选择Web端Demo下载
2.进入github开源网站https://github.com/easemob/videocall-web, 克隆代码
1.安装一款 Easemob Web SDK 支持的浏览器
2.本地安装 node 环境 >= 6.3.0
3.必须为https+webkit内核浏览器
1. 下载下Demo
2. 进入 videocall-web 文件夹
3. 安装依赖包
npm install
4. 启动项目
HTTPS=true npm start
在开始集成前,你需要注册环信开发者账号并创建后台应用,参见注册并创建应用
a.可以简单的写一个 html,引入 SDK 测试 b.或者使用 脚手架搭建一个项目
<script src="EMedia_sdk-dev.js"></script>
npm install easemob-emedia
import emedia from 'easemob-emedia';
1. 首先 下载 WebIM Demo 包 2. 从Demo 中选取 SDK 文件(EMedia_sdk-dev.js)
emedia.config({
appkey, // 从环信后台 获取的appkey、必填
consoleLogger: true, // boolean 是否开启打印日志,默认true
... 其他的一些配置
});
注意:加入会议之前必须先要 调用 emedia.mgr.setIdentity 方法设置 emedia 对象的memName 、token
emedia.mgr.setIdentity(memName, token); //memName:appkey +'_'+ 环信ID, token: 环信ID登录后返回的access_token
params 为进入会议需要的参数
var params = {
roomName, // string 房间名称 必需
password, // string 房间密码 必需
role // number 进入会议的角色 1: 观众 3:主播 必需
config:{
rec:false, //是否开启录制会议
recMerge:false, //是否开启合并录制
supportWechatMiniProgram: true //是否允许小程序加入会议
}
}
调用 emedia.mgr.joinRoom 进入会议, 若该会议不存在,服务器将会自动创建
const user_room = await emedia.mgr.joinRoom(params);
返回的参数 user_room ,组成如下
user_room: {
confrId: "IM3U9Z0AHDYQTF8KNDAAD00C147" 会议ID
id: "IM3U9Z0AHDYQTF8KNDAAD00C147"
joinId: "IM3U9Z0AHDYQTF8KNDAAD00C147M2" 在会议中的唯一ID
role: 1|3|7 //角色 1观众 3主播 7管理员
roleToken:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJlYXNlbW9iLWRlbW8j..."
ticket: "{\"tktId\":\"IM3U9Z0AHDYQTF8KNDAAD00C147TK1\",..."
type: 10 //会议类型
}
加入会议之后 调用 emedia.publish 发布流
var constaints = { // 发布音频流的配置参数, Object 必需。 video或audio属性 至少存在一个
audio: true, // 是否发布音频
video: true // 是否发布视频
}
var ext = {} // 发布流的扩展信息 Object 非必需。会议其他成员可接收到
const pushedStream = await emedia.mgr.publish(constaints, ext);
发布本地流成功后, 调用 emedia.mgr.streamBindVideo 用于在video标签显示流
var videoTag = document.getElementById('#xxx') //需要显示本地流的 video 标签
emedia.mgr.streamBindVideo(pushedStream, videoTag);
当远端流加入频道时,会触发 emedia.mgr.onStreamAdded 方法,我们需要给 emedia.mgr 赋值 onStreamAdded 用来接收 stream
我们建议项目初始化后,立即设置常用监听函数
注意:
自己发布的本地流也会触发 onStreamAdded 方法,
stream.located() == true 为自己发的本地流,
也可以在 这里绑定 video标签,显示本地流
emedia.mgr.onStreamAdded = function(member, stream) {
// member:发布流人员的信息、stream:流信息
if(!stream.located()) {
var option = {
member: member,
stream: stream,
subVideo: true,
subAudio: true,
videoTag: document.getElementById('#xxx')
}
emedia.mgr.subscribe(option.member, option.stream, option.subVideo, option.subAudio, option.videoTag)
}
}
在emedia.mgr.subscribe 方法中注意以下参数的设置
emedia.mgr.onStreamRemoved = function(member, stream) {
// member:发布流人员的信息、stream:流信息
emedia.mgr.unsubscribe(stream) // 停止订阅流
removeView(stream.id) // 移除video标签,removeView方法需自己实现
}
调用 emedia.mgr.exitConference 方法退出会议
emedia.mgr.exitConference() //无参数
强烈建议:
在加入会议之前定义需要的 SDK 回调函数
//有人加入会议
emedia.mgr.onMemberJoined = function (member) { } // member: 加入会议成员信息
//有人退出会议
emedia.mgr.onMemberExited = function (member) {} // member: 退出会议成员信息
//有媒体流添加 (自己发布的流也会触发 stream.located() == true )
emedia.mgr.onStreamAdded = function (member, stream) { }; // member: 发布流的成员信息,stream:流信息
//有媒体流移除
emedia.mgr.onStreamRemoved = function (member, stream) { } // member: 移除流的成员信息,stream:流信息
//自己角色变更
emedia.mgr.onRoleChanged = role => {} // role: 变更后的角色
//会议退出;自己主动退 或 服务端主动关闭;
emedia.mgr.onConferenceExit = function (reason, failed) {
reason = (reason || 0);
switch (reason){
case 0:
reason = "正常挂断";
break;
case 1:
reason = "没响应";
break;
case 2:
reason = "服务器拒绝";
break;
case 3:
reason = "对方忙";
break;
case 4:
reason = "失败,可能是网络或服务器拒绝";
if(failed === -9527){
reason = "失败,网络原因";
}
if(failed === -500){
reason = "Ticket失效";
}
if(failed === -502){
reason = "Ticket过期";
}
if(failed === -504){
reason = "链接已失效";
}
if(failed === -508){
reason = "会议无效";
}
if(failed === -510){
reason = "服务端限制";
}
break;
case 5:
reason = "不支持";
break;
case 10:
reason = "其他设备登录";
break;
case 11:
reason = "会议关闭";
break;
}
};
//管理员变更
emedia.mgr.onAdminChanged = admin => {} //admin 管理员信息
//监听弱网状态
emedia.mgr.onNetworkWeak = streamId => {} //streamId 会议中的流 ID
//监听断网状态
emedia.mgr.onNetworkDisconnect = streamId => {} //streamId 会议中的流 ID
这里的创建会议 不同于快速集成中的加入会议,这里的是属于另一套逻辑,建议使用快速集成中的加入会议
注意: 如果只单纯的创建,没进行操作,则创建者不是会议的成员,没有相应的角色,不能进行其他操作
1.1 调用 emedia.mgr.createConference 方法创建会议
let params = {
confrType,
password,
rec,
recMerge,
supportWechatMiniProgram
... 其他参数
}
const confr = await emedia.mgr.createConference(params);
在 emedia.mgr.createConference 方法中,注意以下参数的设置:
创建会议成功后,返回的参数 confr 结构如下:
confr:{
error: 0,
confrId: "LBJ13H9WJJEVJTGL1U1PIQ00C2", // 会议id
password: "xxxx", // 创建会议时设置的密码
role: 7, // 在会议中的角色 这里因为是创建者,所以是 7: 管理员
roleToken:"eyJ0eXAiOiJKV1QiLCJhbG *** f1gg_QJWxhs-jqmuFok", //创建者的token
type: 10 // 会议类型
}
1.2 调用 emedia.mgr.joinUsePassword 方法加入会议
const join_result = await this.emedia.joinUsePassword(confrId, password) // 参数为 创建会议成功后返回的 confrId和password
加入会议成功后返回的结果,结构如下:
join_result: {
confrId: "LBJ13H9WJJEVJTGL1U1PIQ00C7", // 会议id
joinId: "LBJ13H9WJJEVJTGL1U1PIQ00C7M9", //创建会议时设置的密码
password: "0.010568535799199363", // 会议成员在会议中的身份id(唯一)
role, // 在会议中的角色 创建者加入会议永远是 7: 管理员,其他人加入返回的是 3: 主播
roleToken: "eyJ0eXAiOiJK *** FaXuMVlqPOTofRRdE", // 加入会议者的token
type: 10 // 会议类型
}
2.1 调用 emedia.mgr.createConference 创建会议时配置
let params = {
...
rec: true,
recMerge: true,
... 其他参数
}
const confr = await emedia.mgr.createConference(params);
2.2 调用 emedia.mgr.joinRoom 加入会议时配置
注意:只有第一个加入会议的人,配置的才有效
参数需要放到 config 对象中
let params = {
... 其他参数
config: {
rec: true,
recMerge: true
}
}
const confr = await emedia.mgr.createConference(params);
rec: 是否开启录制,默认 false
recMerge: 是否开启录制合并,默认false
SDK 不提供邀请接口。邀请的形式,完全可以由用户自行定义,可以是条文本消息,也可以是个控制消息等等。SDK 不做限制。实现方式可以参考官方 demo,通过群组消息邀请,具体代码 可查询 demo/src/components/webrtc/AddAVMemberModal.js 中的 70-89 行。
3.1 成员收到邀请加入会议
解析出邀请消息中带的 confrId 和 password ,调用 emedia.mgr.joinUsePassword 加入会议
调用 emedia.mgr.destroyConference 方法, 注意:只有管理员有权限,其他角色调用不生效
await emedia.mgr.destroyConference(confrId); //confrId: 会议Id
其他人会收到会议结束的回调
emedia.mgr.onConferenceExit = reason => {} // reason:退出会议的原因,因为会议被销毁了,所以这里应为 11: "会议关闭"
5.1 在 emedia.mgr.joinRoom 方法中设置 只有第一个加入房间的人员(也就是管理员),设置的才能生效
var params = {
... 其他参数,
config:{ // 在 config 中指定字段
maxTalkerCount:3,
maxAudienceCount:100,
maxVideoCount:2,
maxPubDesktopCount: 1
}
}
const user_room = await emedia.mgr.joinRoom(params);
5.2 在 emedia.mgr.createConference(创建会议) 方法中设置
var params = {
... 其他参数,
maxTalkerCount:3
maxVideoCount:2
maxAudienceCount:100
maxPubDesktopCount: 1
}
const confr = await emedia.mgr.createConference(params);
以上设置会议参数的注意事项如下:
在 emedia.mgr.joinRoom 方法中设置
var params = {
... 其他参数,
config:{
... 其他参数,
nickName: xxx, // string
}
}
const user_room = await emedia.mgr.joinRoom(params);
调用 emedia.mgr.selectConfr 方法获取会议信息
const confr_info = await emedia.mgr.selectConfr(confrId, password); // confrId:会议id、password:会议密码
// 返回的参数 confr_info 结构如下:
confr_info: {
confr: {
id: "LBJ13H05522QATGIJKXUF800C45639", // 会议id
type: 10, // 会议类型
memTotal: 1, // 会议中总人数 主播和观众
audienceTotal: 0, // 观众人数
talkers: ["018ae39 *** 663282d7495"] // 主播的memName集合
}
error: 0
}
CDN推流是指将会议画面,合并到一张画布推送到远程CDN,其他人可以从CDN拉流而不用加入会议
CDN推流参数 liveCfg为必需 结构如下:
let liveCfg = {
cdn:'', //推流地址、字符串;必需
layoutStyle: 'GRID' | 'CUSTOM', // 格子显示 | 自定义,必需
canvas :{// canvas 参数在 layoutStyle == 'CUSTOM' 必填
bgclr : 0x980000,//背景色 980000 为 十六进制色值
w : 640, //宽度
h : 480, //高度
fps: 20, //输出帧率
bps: 1200000, //输出码率
codec: "H264" //视频编码,现在必须是H264
}
}
1.创建会议时指定 CDN推流
let option = {
...
liveCfg // 创建CDN推流参数
}
emedia.mgr.createConference(option)
2.加入房间时 指定CDN推流
// 只有第一个加入房间的人才能创建 CDN、以后加入的人指定CDN也无效
let params = {
config:{
...
liveCfg // 创建CDN推流参数
}
}
emedia.mgr.joinRoom(params);
通过 emedia.mgr.addLive 方法指定一路推流CDN,需要几路CDN,就调用几次方法
注意:只有管理员,可创建 CDN
// confrId: 会议id, 必需
// liveCfg: cdn 配置,必需
media.mgr.addLive(confrId, liveCfg);
// 只有管理员才能 更新布局。更新布局会 将layoutStyle 变为 CUSTOM 而且不可逆
emedia.mgr.updateLiveLayout(confrId, liveId, regions)
// confrId 会议id 必需
// liveId 推流CDN id, 必需 可通过 emedia.config.liveCfgs 获取 Array
regions:[ // 希望定义视频流 显示的配置集合
{
"sid": stream_id,//视频流的id
"x": 320,//距离 x 轴的距离 Number
"y": 240,//距离 y 轴的距离 Number
"w": 960,//宽度 Number
"h": 720,//高度 Number
"style": "fill" | "AspectFit" //视频显示模式 fill:铺满、AspectFit:原比例显示
},
.... 其他视频流配置(数组有几个项,就显示几个视频流)
]
// 只有管理员可操作
//confrId 会议id 必需
// liveId 推流CDN id, 必需 可通过 emedia.config.liveCfgs 获取 Array
emedia.mgr.deleteLive(confrId, liveId)
开启集群部署,SDK内部会自动请求代理,实现通话最优
调用 emedia.config 方法开启
emedia.config({
...
useDeployMore: true // 默认:false 不开启
rtcConfigUrl: 'yourConfigUrl' // 自定义config文件路径, 默认有一个路径
...
})
在浏览器控制台,输入 emedia.fileReport ,敲下回车键会下载下一份日志文件
emedia.fileReport() //无参数
// 用来自定义一些属性,广播给会议中的成员
// 有人设置会议属性,所有的成员都能收到
let options = {
key:username,
val:'request_tobe_speaker'
}
// a. 设置会议属性
emedia.mgr.setConferenceAttrs(options)
// b. 删除会议属性
emedia.mgr.deleteConferenceAttrs(options)
// c. 会议属性变更回调
emedia.mgr.onConfrAttrsUpdated = attrs => {} //attrs 会议属性集合 Array
1v1通话支持不同集群区域的人员通话使用代理,减小延迟; 使用多集群代理需要音视频后台配置IP及端口的映射文件rtcconfig.json,并禁用相关appkey的直连, 也可以指定 rtcconfig.json 的私有化部署
调用 emedia.config 方法开启海外代理
emedia.config({
...
useDeployMore: true, // 默认:false 不开启
rtcConfigUrl: 'your rtcConfigUrl' // 如果不设置,将使用 sdk 后台配置的代理文件
})
发布本地媒体流时,可指定音视频的码率和分辨率,非必需。 共享桌面不可指定
var constaints = {
audio: {bitrate: 100},// 指定音频码率
video: {
width: { // 指定视频分辨率宽度
exact: 1280
},
height: { // 指定视频分辨率高度
exact: 720
},
bitrate: 200,// 指定视频码率
}
}
emedia.mgr.publish(constaints)
const devices = await emedia.mgr.mediaDevices(); //获取设备列表
// 设备信息
device: Object {
deviceId: "529a6fe76467d****9498ab22f5f362cd" // 设备ID
groupId: "2b74c9b9ab99*****d513fbabc1e86b3c5d99f7f8a0c16"
kind: "audioinput" | audiooutput | videoinput | videooutput // 设备类型
label: "Internal Microphone (Built-in)"
}
constraints: { // 选择设备, 然后指定设备(只需要传入设备信息中的deviceId属性,为String类型,其他的属性在推流时暂时用不到)
audio: {deviceId: deviceId ? {exact: deviceId} : undefined}, //判断如果deviceId存在那么就传入对象。
video: {deviceId: deviceId ? {exact: deviceId} : undefined}
},
const stream = await emedia.mgr.publish(constraints) // 推流
调用 emedia.mgr.unpublish 方法停止自己已经发布的流
emedia.mgr.unpublish(pushedStream); // pushedStream:自己发布的流
会议中人员(包括自己)会收到 流被移除的回调函数 emedia.mgr.onStreamRemoved
emedia.mgr.onStreamRemoved = function (member, stream) {
// member: 停止发布流人员信息
// stream:流的信息,stream.located() == true 代表是自己的流,false则为其他人的流
};
调用 emedia.mgr.unsubscribe 方法停止订阅别人的流
emedia.mgr.unsubscribe(stream); // stream:已经订阅的流
5.1 打开/关闭自己的视频
const res_stream = await emedia.mgr.pauseVideo(own_stream) //关闭视频
const res_stream = await emedia.mgr.resumeVideo(own_stream) //开启视频
5.2 打开/关闭自己的音频
const res_stream = await emedia.mgr.pauseAudio(own_stream) // 关闭音频
const res_stream = await emedia.mgr.resumeAudio(own_stream) // 开启音频
执行开启/关闭音视频方法时, * own_stream:自己已经发布的媒体流(不能是桌面流) * res_stream:设置音视频成功后返回的流对象
执行上述操作后,会议中其他人员会收到流变化的回调 emedia.mgr.onMediaChanaged
emedia.mgr.onMediaChanaged 应该在流变化之前监听
var videoTag = document.getElementById('#xxx') // 获取 video 标签
emedia.mgr.onMediaChanaged(videoTag, function(constaints, stream) {
});
// 回调函数中 constaints、stream
constaints: {
audio: true // true: 开启了音频,false:关闭了音频
video: true // true: 开启了视频,false:关闭了视频
}
stream:媒体流变化后的 stream 对象
5.3 切换摄像头
// 随机切换摄像头
emedia.mgr.changeCamera(confrId).then(function(){
// 无参数
}).catch(function(){
})
// 切换手机前后摄像头
emedia.mgr.switchMobileCamera(confrId).then(function(){
// 无参数
}).catch(function(){
})
建议进入会议之前绑定网络状态监听函数
//监听弱网状态
emedia.mgr.onNetworkWeak = streamId => {} //streamId 会议中的流 ID
//监听断网状态
emedia.mgr.onNetworkDisconnect = streamId => {} //streamId 会议中的流 ID
这是监听的video标签,
建议:在将video标签与stream绑定时(emedia.mgr.streamBindVideo), 调用 emedia.mgr.onSoundChanaged 方法
var videoTag = getElementById('#xxx');
emedia.mgr.onSoundChanaged(videoTag,, function (meterData) {});
// 返回的参数 meterData 结构如下:
meterData: {
instant: 0.26280892641627845 // instant 大约每50毫秒变化一次, 小于1的浮点数
slow: 0.06802768487276245 // slow大约是一秒钟内的平均音量,小于1的浮点数
clip: 0
}
仅支持PC Chrome浏览器或electron平台
SDK 3.2.1 版本 文档
需要 SDK 3.2.1 版本开始支持,并且 Chrome 72 或以上版本。
const screenStream = await emedia.mgr.shareDesktopWithAudio({
confrId: confrId, // 会议ID, 必须
audio: false,
});
//在 sdk 内部会自动判断,浏览器是否含有 navigator.mediaDevices.getDisplayMedia API,
//如果没有,将会跳转至 使用 插件的 API,如果没有安装插件将给出提示
//1. 版本起支持在 Windows 平台的 Chrome 浏览器 74 及以上版本同时共享屏幕和本地播放的背景音,
//2. 将 audio 设置为 true 即可
//1. sdk 内部会判断是否是在 electron 平台内
//2. electron 平台 会默认选择 第一个屏幕
//3. 如果需要自定义选择框,请重新定义 emedia.chooseElectronDesktopMedia 方法
emedia.chooseElectronDesktopMedia = function(sources, accessApproved, accessDenied){
sources // Array 获取到的屏幕列表
accessApproved(source)// 选中的 source 对象,进行分享
accessDenied()// 取消分享,关闭自定义框需要调用此方法
}
停止共享桌面,执行 取消流的发布 emedia.mgr.unpublish(screenStream)
SDK 3.2.1 之前版本 文档
/**
* let params = {
* videoConstaints,
* withAudio,
* videoTag,
* ext,
* confrId,
* stopSharedCallback
* }
*/
/**
* videoConstaints {screenOptions: ['screen', 'window', 'tab']} or true
* withAudio: true 携带语音,false不携带 如携带语音,需自己调用关闭流,不会执行 stopSharedCallback 回调
* ext 用户自定义扩展,其他成员可以看到这个字段
* stopSharedCallback 共享插件 点击【停止共享】的回调函数,做相应的处理(比如删除流...)
*/
emedia.mgr.shareDesktopWithAudio(params).then(function(pushedStream){
//stream 对象
}).catch(function(error){
});
//electron平台 默认选择第一个屏幕,如果需要选择其他,需要重写方法
emedia.chooseElectronDesktopMedia = function(sources, accessApproved){
var firstSources = sources[0];
accessApproved(firstSources);
}
注意: 在chrome浏览器中使用时,需要从chrome store 或者从环信服务器 中下载插件,解压后在chrome浏览器中输入 chrome://extensions/, 选择“Load unpacked” 选择解压后的文件夹中的1.0_0文件夹,加载插件。
可通过 emedia.mgr.Role 获取会议中的角色类型
emedia.mgr.Role: {
ADMIN: 7, // 会议管理员: 能创建会议,销毁会议,移除会议成员,切换其他成员的角色
TALKER: 3, // 主播: 能上传自己的音视频,能观看收听其他主播的音视频,即能发布流和订阅流)
AUDIENCE: 1 // 观众: 只能观看收听音视频,即只能订阅流
};
// 可在会议中定义更加语义化的判断:
if(member.role == emedia.mgr.Role.ADMIN){ }
等同于
if(member.role == 7){ }
在以下申请主播和申请管理员的过程,请注意: 1.从发起申请到管理员回复(同意或拒绝),是一个完整的过程 2.因此可以认为:当管理员收到请求,会收到两个函数参数(同意和拒绝),用于管理员调用 3.当管理员处理了请求(同意或拒绝),申请者会收到处理结果(同意或拒绝),未处理则不会收到
以下方法非回调函数均为异步函数
try {
await emedia.mgr.xxx;
} catch(error) { }
// 以下出现的参数注解
confrId: 会议id
memberId: 与会人员的id,member 中的id
nickName: 昵称
观众通过调用 emedia.mgr.requestToTalker 方法申请主播
// 观众上麦申请方法
emedia.mgr.requestToTalker(confrId)
// 管理员收到上麦申请的回调 (主播不会收到这个回调)
emedia.mgr.onRequestToTalker = function(applicat, agreeCallback, refuseCallback) {
/*
* applicat { memberId, nickName } object 申请者信息
* agreeCallback 管理员同意的回调 示例:agreeCallback(memberId) memberId 申请者 id 必需
* refuseCallback 管理员拒绝的回调 示例:refuseCallback(memberId) memberId 申请者 id必需
*/
}
// 观众收到 上麦申请的回复
emedia.mgr.onRequestToTalkerReply = function(result) {
// result 0: 同意 1: 拒绝
}
// 主播申请管理员
emedia.mgr.requestToAdmin(confrId);
//管理员收到申请管理员的回调 (主播不会收到这个回调)
emedia.mgr.onRequestToAdmin = function(applicat, agreeCallback, refuseCallback) {
/*
* applicat { memberId, nickName } object 申请者信息
* agreeCallback 管理员同意的回调 示例:agreeCallback(memberId) memberId 申请者 id 必需
* refuseCallback 管理员拒绝的回调 示例:refuseCallback(memberId) memberId 申请者 id必需
*/
}
// 主播收到 申请管理员的回复
emedia.mgr.onRequestToAdminReply = function(result) {
// result 0: 同意 1: 拒绝
}
只有管理员有权限授权
调用 方法改变与会人员的角色(可升可降)
var option = {
confr:, //会议对象 Object 必需
memberNames: // 被授权人员的memberName集合(可同时给多人授权)Array
role: // 需要授权成什么角色 Number 必需
}
emedia.mgr.grantRole(option.confr, option.memberNames, option.role)
注意:只能角色降级 从管理员到主播、从主播到观众、从管理员到观众,不可逆向操作
与会成员调用 emedia.mgr.degradeRole 方法就会角色降级
//[memName] 与会人员的memName、 toRole 想要 达到的角色
emedia.mgr.degradeRole(confrId, [memName], toRole);
只有管理员可踢人
// confr: 会议对象,必需 Object
// memberNames: 被踢掉人员的 memberName, 必需 Array
emedia.mgr.kickMembersById(confr, memberNames)
只有管理员可操作,其他角色操作不生效,管理员不会被静音
6.1管理员静音全体
await emedia.mgr.muteAll(confrId); // confrId: 会议Id
// 主播收到回调
emedia.mgr.onMuteAll = () => {
// 在收到回调后,需要在程序中执行关闭麦克风的逻辑(emedia.mgr.pauseAudio(own_stream))
}
6.2取消全体静音
await emedia.mgr.unmuteAll(confrId); // confrId: 会议Id
//主播收到回调
emedia.mgr.onUnMuteAll = () => {
// 在收到回调后,需要在程序中执行关闭麦克风的逻辑(emedia.mgr.resumeAudio(own_stream))
}
只有管理员可操作,其他角色操作不生效
7.1管理员指定成员静音
emedia.mgr.muteBymemberId(confrId, memberId);// memberId 被静音主播的memberId
// 单个主播被管理员静音的回调(只他自己收到回调)
emedia.mgr.onMuted = () => {
// 在收到回调后,需要在程序中执行关闭麦克风的逻辑(emedia.mgr.pauseAudio(own_stream))
}
7.2管理员取消指定成员静音
emedia.mgr.unmuteBymemberId(confrId, memberId);// memberId 被取消静音主播的memberId
// 单个主播被管理员取消静音的回调 (只他自己收到回调)
emedia.mgr.onUnmuted = () => {
// 在收到回调后,需要在程序中执行关闭麦克风的逻辑(emedia.mgr.resumeAudio(own_stream))
}
如果想要变更自己的角色,需要向管理员申请,管理员同意后,角色就会变更
emedia.mgr.onRoleChanged = function (role) {
// role: 变更后的角色
};
当会议中的管理员变更时,与会人员都会收到这个回调
emedia.mgr.onAdminChanged = admin => {} //admin 管理员信息
emedia.mgr.captureVideo(videoTag, true, filename)
等价于
emedia.mgr.triggerCaptureVideo(videoTag, true, filename);
emedia.mgr.freezeFrameRemote(stream);
等价于
emedia.mgr.triggerFreezeFrameRemote(videoTag).catch(function(){
alert("定格失败");
});
/**
* torch true 打开,否则 关闭; 可缺失
*/
emedia.mgr.torchRemote(stream, torch);
等价于
emedia.mgr.triggerTorchRemote(videoTag, torch).catch(function(){
alert("Torch失败");
});
emedia.mgr.capturePictureRemote(stream);
等价于
emedia.mgr.triggerCapturePictureRemote(videoTag).catch(function(){
alert("抓图失败");
});
emedia.mgr.zoomRemote(stream, multiples);
等价于
emedia.mgr.triggerZoomRemote(videoTag, multiples).catch(function(){
alert("zoom失败");
});
/**
* clickEvent 为 videoTag的点击事件。通过event计算点击的坐标传给sdk进行控制
*
*/
emedia.mgr.focusExpoRemote(stream, videoTag, clickEvent).catch(function(){
alert("focusExpoRemote失败");
});
等价于
/**
* event string. 如点击 “click”
* fail 失败回调;success成功回调
*/
emedia.mgr.onFocusExpoRemoteWhenClickVideo(videoTag, event, fail, success);
//用来对onFocusExpoRemoteWhenClickVideo的撤销
emedia.mgr.offEventAtTag(videoTag);
//视频收发数据统计
emedia.mgr.onMediaTransmission(videoTag, function notify(trackId, type, subtype, data) {
var $iceStatsShow = $div.find("#iceStatsShow");
var $em = $iceStatsShow.find("#"+subtype);
if(!$em.length){
$em = $("<em></em>").appendTo($iceStatsShow).attr("id", subtype);
}
$em.text(subtype + ":" + (data*8/1000).toFixed(2));
});
//连接状态变化
emedia.mgr.onIceStateChanged(videoTag, function (state) {
console.log(state);
});
// 用来自定义一些属性,广播给会议中的成员
// 有人设置会议属性,所有的成员都能收到
let options = {
key:username,
val:'request_tobe_speaker'
}
// a. 设置会议属性
emedia.mgr.setConferenceAttrs(options)
// b. 删除会议属性
emedia.mgr.deleteConferenceAttrs(options)
// c. 会议属性变更回调
emedia.mgr.onConfrAttrsUpdated = attrs => {} //attrs 会议属性集合 Array
多人音视频通话的API包括以下接口
以下方法均为 emedia.mgr 对象的属性方法:
方法 | |
---|---|
createConference | 创建会议 |
createConference | 销毁会议 |
getConferenceInfo | 获取会议信息 |
grantRole | 改变角色 |
joinConference | 通过password 加入会议 |
kickMembersById | 通过id踢出成员 |
publish | 发布媒体流 |
unpublish | 取消发布媒体流 |