通过 createClient()
获取到 client
模块后,就可以使用 client
模块进行管理会议和渲染操作。
【AUTO 布局】用于会中动态切换显示/隐藏 Local 画面,切换完成后,下发的 Layout 回调 list 数据中将不在包含 Local 的画面数据。
client.toggleLocal(): Promise<{ status: boolean }
关联 video 和 streamId 信息,内部控制视频的播放。
参数:
layout
或custom-layout
事件消息上报的id字段;client.setVideoRenderer(key: string, wrapEleId: string): void
关联 audio 和 streamId 信息,内部控制音频的播放。
参数:
audio-track
事件消息获取。client.setAudioRenderer(key: string, wrapEleId: string): void
会中设备发生变化,配置是否自动执行切换设备操作,默认是 true ,自动执行切换设备操作。 设备的切换规则:
设备发生变化后,也会推送相应设备详细列表数据和 Diff 差异设备的数据,可以通过监听 device
事件消息获取数据。
参数:
client.switchAutoDevice(status: boolean): Promise<boolean>
切换显示布局模式,默认演讲者模式(SPEAKER)。可切换演讲者模式和画廊模式; 如果想在入会前设置布局方式,那么可以在 createClient
中配置 templateMode
属性即可;
参数:
兼容: v2.0.2+ 版本开始支持 templateMode 字段;
client.switchLayout(templateMode?: IMode): Promise<IMode>;
/**
* 布局模式
*/
type IMode = ITemplateMode | IContentTemplateMode;
/**
* Layout布局方式
*
* @value SPEAKER 默认值,演讲者模式,即 1大N小 画面模式
* @value GALLERY 另一种是画廊模式,即 宫格布局
*/
type ITemplateMode = 'SPEAKER' | 'GALLERY';
/**
* 主画面/Content布局模式
*
* @value MULTI_PIC_CONTENT_HIGH_PRIORITY Content是大窗口
* @value MULTI_PIC_ACTIVE_HIGH_PRIORITY ActiveSpecker是大窗口
* @value TWO_PIC_PIP 画中画模式(picture in picture)
* @value CONTENT_ONLY 只显示Content
* @value TWO_PIC_SYMMETRIC 对称显示content和speker(side by side)
*/
type IContentTemplateMode =
| 'MULTI_PIC_CONTENT_HIGH_PRIORITY'
| 'MULTI_PIC_ACTIVE_HIGH_PRIORITY'
| 'TWO_PIC_PIP'
| 'CONTENT_ONLY'
| 'TWO_PIC_SYMMETRIC';
发起呼叫,需要携带会议号、入会密码、token、入会用户名等信息; 如果返回 true ,代表是否可以继续呼叫;
此步骤后续可以通过监听error
事件查看异常信息;
备注:
client.makeCall(data: IMackCall): Promise<Boolean>;
/**
* 呼叫参数
*
* @property { string } token 网关token
* @property { string } confNumber 云会议号/终端号/手机号
* @property { string? } password 入会密码,没有则为空
* @property { string? } displayName 入会显示昵称
* @property { boolean } muteAudio 非必填 | false | 是否开启/关闭麦克风入会,默认是false,开启麦克风
* @property { boolean } muteVideo 非必填 | false | 是否开启/关闭摄像头入会,默认是false,开启摄像头
*/
interface IMackCall {
token: string;
// 云会议号
// v2.0.2+版本支持呼叫硬件终端号码、手机号
// v2.1.1+版本支持呼叫H323会议/硬件
confNumber: string;
password?: string;
displayName?: string;
// 兼容 v3.9.3+
muteAudio?: boolean;
// 兼容 v3.9.3+
muteVideo?: boolean;
}
推送本地流,开始推拉流;
本地 stream
是通过 createStream()
创建的流对象;
此步骤执行完毕后,入会前的步骤执行完毕,之后的事件处理及其状态变化请在回调事件中进行监听;
参数:
createStream()
创建的 stream 对象数据;client.publish(stream: Stream, params: IPublishParams): void;
interface IPublishParams {
// 是否是推送本地数据流,默认是false,初始入会需要设置为true;
isSharePeople?: boolean;
// 是否是推送共享屏幕流,默认是false,不推送,当需要屏幕共享时,请配置为true;
isShareContent?: boolean;
}
停止共享屏幕
client.stopShareContent(): Promise<Boolean>
挂断会议,销毁资源
client.destroy(): Promise<Boolean>
小鱼用户账号登录
此方法即将废弃,但是不影响老客户调用,建议使用新登录方法:loginXYAccount
参数:
client.loginXYlinkAccount(userName: string, password: string): Promise<IReturnResult>;
// 成功code:XYSDK:950120
// 失败code详见错误码文档
interface IReturnResult {
code: number;
msg: string;
detail: {} | { access_token: string };
}
三方用户统一认证登录 - 小鱼易连账号登录
兼容:v3.9.3+
XYClient.loginXYAccount(params: LoginXYAccountParams): Promise<IReturnResult>;
/**
* 三方用户统一认证登录 - 小鱼账号登录 参数
*
* @param { string } account - 必填,用户账号
* @param { string } password - 必填,用户密码
* @param { string } extId - 必填,企业ID
* @param { string? } countryCode - 可选,国家码:默认+86
*/
export interface LoginXYAccountParams {
account: string;
password: string;
extId: string;
countryCode?: string;
}
// 成功code:XYSDK:950120
// 失败code详见错误码文档
interface IReturnResult {
code: number;
msg: string;
detail: {} | { access_token: string };
}
第三方账号登录,第三方业务请使用此接口进行登录操作。
参数:
兼容:
1、v2.0.3+ 版本开始支持 extuserId
字段;
2、v3.9.0+版本开始,由内部接口改为外部接口,需要在分区云环境使用0724版本以上的环境包;
3、v3.9.3+对此方法进行了安全升级,但需要传authCode
和isTempUser
两个参数,为兼容旧的登录方式,authCode和isTempUser作为可选参数;
client.loginExternalAccount(params: ILoginExtAccount): Promise<IReturnResult>;
/**
* 第三方登录用户信息
*
* @property { string } displayName - 必填,用户名称
* @property { string } extId - 必填,企业id
* @property { string } extUserId - 可选,三方用户ID
* @property { string } authCode - 可选,授权码
* @property { boolean } tempUser - 可选,临时账号
*/
interface ILoginExtAccount {
displayName: string;
extId: string;
extUserId?: string;
authCode?: string;
tempUser?: boolean;
}
// 成功code:XYSDK:950120
// 失败code详见错误码文档
interface IReturnResult {
code: number;
msg: string;
detail: {} | { access_token: string };
}
三方用户统一认证登录-Token登录
兼容: v3.9.3+
XYClient.loginExtToken(params: LoginExtTokenParams): Promise<IReturnResult>;
/**
* 三方用户统一认证登录 - token登录
*
* @param { string } authCode - 必填,登录码
* @param { string } extId - 必填,企业ID
*/
interface LoginExtTokenParams {
authCode: string;
extId: string;
}
// 成功code:XYSDK:950120
// 失败code详见错误码文档
interface IReturnResult {
code: number;
msg: string;
detail: {} | { access_token: string };
}
授权码登录
XYClient.loginWithAuthCode(params: ILoginWidthAuthCode): Promise<IReturnResult>;
/**
* 授权码登录
*
* @property { string } extId - 必填,企业id
* @property { string } extUserId - 必填,用户id
* @property { string } displayName - 必填,用户名
* @property { string } oauthCode - 必填,授权码
* @property { boolean } isTempUser - 必填,是否是临时账号
* @property { string } channelId - 必填,渠道id
*/
interface ILoginWidthAuthCode {
extId: string;
extUserId: string;
displayName: string;
oauthCode: string;
isTempUser: boolean;
channelId: string;
}
// 成功code:XYSDK:950120
// 失败code详见错误码文档
interface IReturnResult {
code: number;
msg: string;
detail: {} | { access_token: string };
}
麦克风静音,静音后,远端将听不到本地端声音
client.muteAudio(): Promise<IVideoAudioType>;
type IVideoAudioType = 'muteAudio' | 'muteVideo' | 'unmuteAudio' | 'unmuteVideo'
取消麦克风静音,取消后,远端可以听到本地端声音
client.unmuteAudio(): Promise<IVideoAudioType>;
type IVideoAudioType = 'muteAudio' | 'muteVideo' | 'unmuteAudio' | 'unmuteVideo'
关闭摄像头;
v1.3.5+版本之后,支持关闭摄像头后同时关闭摄像头指示灯
client.muteVideo(): Promise<IVideoAudioType>;
type IVideoAudioType = 'muteAudio' | 'muteVideo' | 'unmuteAudio' | 'unmuteVideo'
开启摄像头;
client.unmuteVideo(): Promise<IVideoAudioType>;
type IVideoAudioType = 'muteAudio' | 'muteVideo' | 'unmuteAudio' | 'unmuteVideo'
举手发言
client.onHandUp(): Promise<boolean
取消举手
client.onHandDown(): Promise<boolean
结束发言
client.onMute(): Promise<boolean
切换 debug 模式,控制推送发送&接收路所有流的状态数据(包括帧率,码率,带宽,抖动,分辨率等会议详细信息),开启后,通过监听 meeting-stats
事件获取数据
client.switchDebug(status: boolean): Promise<boolean>
兼容:v2.0.2+
自定义布局,用于请求参会者成员的分辨率、质量视频数据;
请求完成视频画面数据后,会通过 client 的 custom-layout
事件返回布局视频流数据;
如果涉及到翻页查看更多参会者画面需求,请使用此方法,此方法暂时可以查看最多 120 个参会者画面数据;
参数:
client.requestNewLayout(reqList: IReqInfo[], maxViewCountPerPage: number, pageIndex: number, extReqList: IReqInfo[] = [], extParams?: IExtParams): Promise<boolean>;
interface IReqInfo {
// 是否是共享内容设备,0:people画面,1:content共享画面;
mediagroupid: 0 | 1;
// 设备唯一calluri
// 没有可以指定为空即可,会按照主会场/语音激励/音视频开启/音频开启/视频开启/关闭的优先级推送远端数据
calluri: string;
// 请求当前设备的分辨率数据:
// 1: 180P
// 2: 360P
// 3: 720P people默认最多请720P画面;企业如果配置请求1080P画面的能力,则最多可请1080P的画面
// 4: 1080P content最多请1080P画面
resolution: IResolutionType;
// 0: low 低画面质量,帧率会自动降低到15帧接收;
// 1: normal 普通画面质量,会基于带宽信息自动在30/15帧切换;
// 2: high 高画面质量,会优先匹配高帧率高分辨率画面;
quality: IQualityType;
};
// 如上定义
type IResolutionType = 1 | 2 | 3 | 4 | 5;
// 如上定义
type IQualityType = 0 | 1 | 2;
// 额外的参数
interface IExtParams {
// 分页查看更多画面时,第一页是否包含Local画面数量,默认是 true,包含Local的数量
uiShowLocalWhenPageMode: boolean;
}
兼容:v2.0.0 - v2.0.1 版本支持
自定义布局,用于请求参会者成员的分辨率、质量视频数据; 请求完成视频画面数据后,会通过 client 的 custom-layout
事件返回布局视频流数据;
client.requestLayout(reqList: IReqInfo[]): Promise<string>;
type IReqInfo = {
// 是否是共享内容设备,可以从roster中的isContent中获取;
isContent: boolean;
// 设备id,可以从roster中的endpointId中获取;
callUri: string;
// 请求当前设备的分辨率数据:
// 0: 90P
// 1: 180P
// 2: 360P
// 3: 720P people最多请720P画面
// 4: 1080P content最多请1080P画面
resolution: IResolutionType;
// 0: low 质量较低
// 1: normal 质量普通
// 2: high 质量高优先级
quality: IQualityType;
};
// 如上定义
type IResolutionType = 0 | 1 | 2 | 3 | 4 | 5;
// 如上定义
type IQualityType = 0 | 1 | 2
兼容:v2.0.1+
自动轮询请求 Layout 画面数据;
参数:
client.requestAutoPollingLayout(command: TCommand, interval: number = 5, reqList: IReqInfo[]): Promise<boolean>;
// 轮询多画面状态: 0 开始 | 1 停止 | 2 暂停 | 3 恢复
type TCommand = 0 | 1 | 2 | 3;
type IReqInfo = {
// 是否是共享内容设备,0:people画面,1:content共享画面;
mediagroupid: 0 | 1;
// 设备唯一calluri,可以在【custom-layout】事件回调中获取;
calluri: string;
// 请求当前设备的分辨率数据:
// 1: 180P
// 2: 360P
// 3: 720P people最多请720P画面
// 4: 1080P content最多请1080P画面
resolution: IResolutionType;
// 0: low 低画面质量,帧率会自动降低到15帧接收;
// 1: normal 普通画面质量,会基于带宽信息自动在30/15帧切换;
// 2: high 高画面质量,会优先匹配高帧率高分辨率画面;
quality: IQualityType;
};
// 如上定义
type IResolutionType = 1 | 2 | 3 | 4 | 5;
// 如上定义
type IQualityType = 0 | 1 | 2;
兼容:v2.0.2+
AUTO 布局翻页接口。可通过 page-info
事件回调获取总的页码信息;
参数:
client.setPageInfo(currentPage)
兼容:v2.0.2+
获取本地的参会者数据,包含用户基本信息,会议状态信息
client.getSelfRoster(): IRoster
兼容:v2.1.1+
设置某个参会者(rosterId)为全屏画面,退出全屏时,可不填写参数;
/**
* 全屏请流
* 请全屏 设置对应的layout id
* 退出全屏 可不传参数
*
* @param { string } id rosterId
* @returns Promise<string> rosterId
*/
client.forceFullScreen(id = ''): Promise<string>;
绑定监听事件
client.on(keyName: string, listenerFunction: () => {}): void
解除绑定监听事件
client.off(keyName: string): void
订阅查看更多参会者数据,订阅后,会通过bulkRoster事件回调参会者变化数据;
兼容:v2.0.3+
client.subscribeBulkRoster(): Promise<boolean>
开启通话字幕功能;
兼容:v2.1.2+
client.startTranslation(): Promise<boolean>;
关闭通话字幕功能;
兼容:v2.1.2+
client.stopTranslation(): Promise<boolean>;
设置通话字幕本地说话的语言;
兼容:v2.1.2+
client.setTranslationLanguage(language: 'Chinese' | 'English'): Promise<boolean>;
开启云端录制;
兼容:v2.1.2+
client.startCloudRecord(): void;
停止云端录制;
兼容:v2.1.2+
client.stopCloudRecord(): void;
启动多分组能力,并可以开始进行多分组请流,即可以进行请求某一个参会终端的多路摄像头画面流;
兼容:v2.1.2+
client.startMonitorGroup(mediagrpIds: string[] | number[]): boolean;
停止多分组能力,销毁资源;
兼容:v2.1.2+
client.stoMonitorGroup(mediagrpIds: string[] | number[]): boolean;
发送自定义消息;
兼容:v2.1.3+
client.sendCustomMessage(config: ICustomMessageConfig): void;
/**
* 用户自定义消息
*
* @property { number } toPid - 消息的接收方pid,0表示广播消息、非0表示单点消息;
* @property { string } data - 消息内容,可以被JSON序列化的字符串;因业务数据可能会传输图片,需要进行base64编码,消息最大长度限制:1MB
*/
interface ICustomMessageConfig {
toPid: number;
data: string;
}
SDK功能控制开关
兼容:v3.8.0+
client.setFeatureConfig(config: IFeatureConfig): void;
/**
* SDK功能控制开关,用于内部是否启用某些功能的运行
*
* @property { boolean } enableMeetingShout 是否启用会控喊话场景,会控喊话场景需要指定mediaGroupId分组通道信息才可以正常接收远端声音;
* @property { boolean } enableV2States 是否启用小鱼数据上报功能,默认启用,设置为true;
* @property { boolean } enableCheckRecordPermission 是否启用录制权限查询功能,默认不启用,设置为false;
* @property { boolean } enableBandwidthSetting 是否启用查询企业带宽配置、允许请求高分辨率配置功能,默认不启用,设置为false;
* @property { boolean } enableMeetingInvite 是否启用查询小鱼会议邀请链接信息,默认不启用,设置为false;
* @property { boolean } enableMeetingOwner 是否启用查询会议Owner信息,默认不启用,设置为false;
* @property { boolean } enableAutoResizeLayout 是否启用自动布局下,当屏幕大小变化后计算最新的Layout数据,默认启用,设置为true;
* @property { boolean } enableLowResolution 是否启用低性能模式,降低发送和接收端的分辨率和质量,默认不启用,设置为false;
* @property { boolean } enableSpeakerInfo 是否启用推送实时讲话人信息,每秒2条消息推送,默认不启用,设置为false;
* @property { boolean } config.enableLayoutAvatar 是否启用获取参会者头像,默认不启用,设置为false;
* @property { boolean } enableMobileNotAuth 移动端是否支持无授权入会, 默认设置为false;
*/
interface IFeatureConfig {
enableMeetingShout?: boolean;
enableV2States?: boolean;
enableCheckRecordPermission?: boolean;
enableBandwidthSetting?: boolean;
enableMeetingInvite?: boolean;
enableMeetingOwner?: boolean;
enableAutoResizeLayout?: boolean;
enableLowResolution?: boolean;
enableSpeakerInfo?: boolean;
enableLayoutAvatar?: boolean;
enableMobileNotAuth?: boolean;
}
获取当前会议会控地址;
兼容:v3.8.0+
client.getConfMgmtUrl(): Promise<IConfMgmtUrl | null>;
/*
* 会控URL
*
* @property { string } pc - 会控桌面端URL
* @property { string } member - 参会者列表URL
* @property { string } side - 侧边栏会控URL
* @property { string } mobile - 会控APP端URL
* @property { string } professional - 专业会控URL
*/
export interface IConfMgmtUrl {
pc: string;
member: string;
side: string;
mobile: string;
professional: string;
}
通知会控打开/关闭摄像头结果
会控桌面端(pc)/会控APP端(mobile)/专业会控(professional)地址支持非会议主持人(或非会议Owner)主持会议,但需要输入会控密码;
侧边栏会控(side)暂时不支持非会议Onwer以外的角色主持会议,如需使用此方式,需要判断是否是会议Owner角色,判断方法是:
1、先监听user-info获取个人会议室信息
2、通过判断meetingNumber和入会的会议号是否一致判断是否是会议Owner角色;
兼容:v3.8.0+
client.sendVideoControlResult(
type: 'muteVideo' | 'unMuteVideo',
data: IVideoControlResult
): Promise<IReturnResult>;
/**
* 上报会控控制开启/关闭摄像头结果
*
* @property { boolean } agree - 是否同意开启/关闭摄像头
* no.camera.permission:终端未授权App摄像头权限
* reject.unmute.video:参会人拒绝开启摄像头
* voice.mode:终端在语音模式
* driving.mode:终端在驾驶模式
* '':同意为空即可
* @property { string } reason - 是否同意开启/关闭摄像头
* @property { string } requestId - 终端收到的muteVideoQuery/unMuteVideoQuery消息中的requestId
*/
interface IVideoControlResult {
agree: boolean;
reason: string;
requestId: string;
}
/**
* 返回结果内容
*
* @property { string } code - 结果码
* @property { string } msg - 结果说明
* @property { any } detail - 数据内容
*/
interface IReturnResult {
code: string;
msg: string;
detail: any;
}
会中修改本地名称
兼容:v3.9.9+
/**
* 修改参会者名称,暂只支持修改本地名称
*
* @param { string } newName - 新名称,支持2-40个字符,仅支持大小写字母、数字、汉字以及空格、特定的表达符号((-_--.))
*/
client.rename (newName: string): Promise<IReturnResult>;
// 新名词正则判断
const allowedCharactersRegex =
/[\u0041-\u005A\u0061-\u007A\u0030-\u0039\u4E00-\u9FA5\u002e\u002d\u005F\u00e4\u00d6\u00f6\u00dc\u00fc\u1e9e\u00df\u00d1\u00f1\u2014\s]/g;
/**
* 返回结果内容
*
* @property { string } code - 结果码
* @property { string } msg - 结果说明
* @property { any } detail - 数据内容
*/
interface IReturnResult {
code: string;
msg: string;
detail: any;
}
自动布局,用于主动更新Layout的位置和大小信息;
触发机制:当页面窗口变化/Container Dom大小变化时,可主动调用同时SDK更新Layout信息
建议:如果业务上自行监听窗口变化和Dom大小变化,建议通过featureConfig配置autoResizeLayout为false关闭内部的事件,避免重复计算;
兼容:v3.8.0+
client.updateLayoutSize(): void;
自动布局,切换移动端布局方向
触发机制:
业务层需要首先判断当前设备是PC端还是移动端,然后只有在移动端的情况下才调用该方法。
兼容:v3.9.1+
/**
* 切换布局方向
*
* @param { LayoutOrientationType } orientation - 布局方向: MOBILE_HORIZONTAL(横屏);MOBILE_VERTICAL(竖屏)
*/
client.setLayoutOrientation(orientation: LayoutOrientationType): Promise<IReturnResult>;
/**
* Layout 移动端布局方向
*
* @param NONE -1 - 默认布局(PC)
* @param MOBILE_HORIZONTAL 0 - 移动端横屏布局
* @param MOBILE_VERTICAL 1 - 移动端竖屏布局
*/
enum LayoutOrientationType {
NONE = -1,
MOBILE_HORIZONTAL = 0,
MOBILE_VERTICAL = 1
}
会控喊话功能,用于关联audio track与mediaGroupId通道,从而向特定通道发送音频数据;
兼容:v3.8.0+
1、调用此方法后,如果设置了非0/1的mediaGroupId通道信息,那么媒体网关仅会转发给相应的通道音视频数据,其他通道接收不到音频数据;
2、如果开启会控喊话配置,则在收到connected消息后,需要发送一条bindTrackGroup消息,并标记meidagroupId为-1,代表本地初始入会时,不再向其他通道转发声音数据;
/**
* trackType 控制发送通道类型,audio控制音频通道,video控制视频通道,暂时只支持audio通道
* mediagroupId 分组id,也称sessionId或者mediaGroupId,代表只向此分组通道发送音频数据
*/
client.bindTrackGroup(trackType: 'audio' | 'video', mediagroupId: number): boolean | IReturnResult;
interface IReturnResult {
code: string;
msg: string;
detail: any;
}
设置移动端摄像头方向,支持前置/后置摄像头;
兼容:v3.9.0+
/**
* 设置相机方向
*
* @param { IFacingMode } position 相机方向
* @returns { Promise<IFacingMode> } 最终切换的相机方向
*/
client.switchCamera(facingMode?: IFacingMode): Promise<IFacingMode>;
/**
* 手机相机方向
*
* @param FRONT - 前置摄像头
* @param BACK - 后置摄像头
*/
type IFacingMode = 'FRONT' | 'BACK';
设置会议级别焦点画面;
兼容:v3.9.5+
1、在自动布局模式下,会议中设置了主会场或者接收远端共享内容,则焦点画面不生效;
2、仅支持主持人角色调用此方法,其他角色调用会返回相应错误信息;
/**
* 设置会议级别焦点画面
*
* @param { string } rosterId - 指定焦点画面的rosterId
* @returns { Promise<IReturnResult> } - 操作结果
*/
client.startMeetingFocusView(rosterId:string): Promise<IReturnResult>;
/**
* 返回结果内容
*
* @property { string } code - 结果码
* @property { string } msg - 结果说明
* @property { any } detail - 数据内容
*/
export interface IReturnResult {
code: string;
msg: string;
detail: any;
}
取消会议级别焦点画面;
兼容:v3.9.5+
1、仅支持主持人角色调用此方法,其他角色调用会返回相应错误信息;
/**
* 取消会议级别焦点画面
*
* @param { string } rosterId - 取消焦点画面的rosterId
* @returns { Promise<IReturnResult> } - 操作结果
*/
client.stopMeetingFocusView(rosterId:string): Promise<IReturnResult>;
/**
* 返回结果内容
*
* @property { string } code - 结果码
* @property { string } msg - 结果说明
* @property { any } detail - 数据内容
*/
export interface IReturnResult {
code: string;
msg: string;
detail: any;
}
设置自动布局相关配置;
兼容:v3.9.5+
/**
* 设置布局相关配置
*
* @param { LayoutConfig } config - 配置参数
* @property { boolean? } config.isForceSharedLayout - 本地共享布局是否强制宫格布局,默认强制,设置为true;
* @property { number? } config.localSharedMaxViewCount - 本地共享时显示的最大画面数量,默认4画面,最大8画面
*/
client.setLayoutConfig(config: LayoutConfig);
/**
* 布局相关配置
*
* @property { boolean } isForceSharedLayout - 本地共享布局是否强制宫格布局
* @property { number } localSharedMaxViewCount - 本地共享时显示的最大画面数量
*/
export interface LayoutConfig {
isForceSharedLayout?: boolean;
localSharedMaxViewCount?: number;
}
实时参会者列表数据(最多 20 路) 如果是自定义布局,那么需要处理此数据,计算最新的 Layout 布局数据,然后通过 customLayoutSender() 方法请求 Layout 参会者成员的画面质量数据,通过 layout-result 状态回调返回请流结果数据并作展示。
兼容:v3.9.4+ 新增字段 isFocusScreen
兼容:v3.9.10+ id
更换成 key
client.on("roster", (e: IRoster[]) => {}): void;
interface IRoster {
// 设备类型
deviceType: string;
// 设备Id
endpointId: string;
// 名称
displayName: string;
// people or content标示,0代表people,1代表Content内容
mediagroupid: number;
// 成员pid值
participantId: number;
// 当前设备麦克风的状态
audioTxMute: boolean;
// 当前设备摄像头状态
videoTxMute: boolean;
// 忽略
audioRxMute: boolean;
// 忽略
videoRxMute: boolean;
// 忽略
videoMuteReason: number;
// 是否是主会场
isForceFullScreen: boolean;
// 是否是焦点画面 v3.9.4+新增
isFocusScreen: boolean;
// 忽略
isLastAdd: boolean;
// 是否是呼叫等待状态
onHold: boolean;
// 是否正在轮询显示
isPolling: boolean;
// 是否是content内容
isContent: boolean;
// 是否是Local设备
isLocal: boolean;
// 唯一id值 (v3.9.10+ 废弃,使用key)
id: string;
// 唯一值 (v3.9.10+ 新增)
key: string;
// 是否是activeSpeaker语音激励
isActiveSpeaker?: boolean;
}
会控通知本地端取消举手
client.on("cancel-handup", (e: boolean) => {}): void
退出会议消息,包含所有异常退会原因,建议监听;
client.on("disconnected", (e: IDisconnected)=> {}): void;
interface IDisconnected {
code: number;
msg: string;
detail: {
// 退会消息原因
message: string;
// 退会消息错误码
key: string;
};
}
异常错误消息
client.on("error", (e: IResult) => {}): void;
interface IResult {
// 错误码,详情见错误码表
code: number;
// 错误原因
msg: string;
// 错误数据内容
detail: Object;
}
呼叫会议状态,可能有呼叫中、呼叫失败、呼叫成功
client.on("call-status", (e: IResult) => {}): void;
interface IResult {
// 错误码,详情见错误码表
// 存在的状态:
// 10517:呼叫失败
// 10518:加入会议成功
// 10519:正在呼叫中,请等待
code: number;
// 错误原因
msg: string;
// 错误数据内容
detail: Object;
}
【AUTO 布局】参会成员布局列表数据;
此列表数据包含当前布局模式的参会人员状态、基本信息数据,当会议的状态产生变化时,会重新推送此消息。
兼容:
1、v3.8.0+支持上报参会者人物头像(avatar),需通过setFeatureConfig启用获取参会者头像,默认不启用;
2、v3.9.0+支持在后台配置上报名称头像(textAvatar),如未配置,默认使用名称头像;
3、v3.9.8支持上报pollingState、pollingId、pollingName字段;
4、v3.9.10+新增字段id
, 作为参会者唯一值,调用setVideoRenderer方法时,可传递此值;废弃pollingId
5、v3.9.10+ roster中的id变更为key值
client.on('layout', (e: ILayout[]) => ())
/**
* 布局对象
*
* @property { string } id - Layout ID, v3.9.10+ 新增
* @property { IRoster } roster 参会者基本信息、状态信息,例如:用户名、麦克风/摄像头状态、是否是主会场等信息
* @property { ILayoutState } state 当前参会者的画面状态信息,暂时未使用
* @property { any } rotate 当前参会者的旋转信息,用于设置video标签样式
* @property { { left: string; top: string; width: string; height: string } } positionStyle 当前参会者的位置样式
* @property { string } avatar 人物头像
* @property { string } textAvatar 名称头像
* @property { ExternalTemplateConfig } templateConfig 忽略
* @property { { width: number; height: number } } positionInfo 忽略
* @property { number[] } position 忽略
* @property { boolean } deal 忽略
* @property { number } index 忽略
* @property { number } resolution 忽略, 2.0.2以前的版本 自定义布局roster请流使用
* @property { number } quality 忽略, 2.0.2以前的版本 自定义布局roster请流使用
* @property { AutoState } pollingState 轮询多画面状态
* @property { string } pollingId - 多画面ID
* @property { string } pollingName - 多画面名称
*/
interface ILayout {
id: string;
roster: IRoster | null;
state?: ILayoutState;
rotate?: any;
positionStyle?: {
left: string;
top: string;
width: string;
height: string;
};
avatar?: string;
textAvatar?: string;
templateConfig?: ExternalTemplateConfig;
position?: number[];
positionInfo?: {
width: number;
height: number;
};
deal?: boolean;
index?: number;
resolution?: number;
quality?: number;
pollingState?: AutoState;
pollingId?: string;
pollingName?: string;
}
/**
* Roster:参会者的基本信息,包含基本信息,设备信息,画面信息等
*
* @property { string } key 内部Key,包含参会者endpointId、多分组通道信息,由一定规则生成;
* @property { IDeviceType } deviceType 设备类型
* @property { string } endpointId 设备id
* @property { string } displayName 参会者名称
* @property { number } mediagroupid 参会者画面类型,0:people画面,1:共享内容画面
* @property { number } participantId 参会者id
* @property { boolean } audioTxMute 参会者麦克风状态,true:开启,false:关闭
* @property { boolean } videoTxMute 参会者摄像头状态,true:开启,false:关闭
* @property { boolean } isForceFullScreen 参会者是否是主画面
* @property { number } videoMuteReason 视频关闭原因
* @property { boolean } isContent 参会者画面类型,同mediagroupid,true:是共享内容画面,false:people画面
* @property { boolean } isActiveSpeaker 参会者是否是语音激励,即当前会中说话声音最大的一个人
* @property { boolean } isLocal 是否是Local设备
* @property { boolean } audioRxMute ignore
* @property { boolean } videoRxMute ignore
* @property { boolean } onHold ignore
* @property { boolean } isLastAdd ignore
* @property { boolean } isPolling ignore
* @property { AutoState } pollingState 轮询多画面状态
* @property { string } pollingId - 多画面ID
* @property { string } pollingName - 多画面名称
*/
interface IRoster extends Partial<ILayoutRoster> {
key: string;
deviceType: IDeviceType;
endpointId: string;
displayName: string;
mediagroupid: number;
participantId: number;
audioTxMute: boolean;
videoTxMute: boolean;
audioRxMute: boolean;
videoRxMute: boolean;
videoMuteReason: number;
isForceFullScreen: boolean;
isLastAdd: boolean;
onHold: boolean;
isPolling: boolean;
isContent: boolean;
isActiveSpeaker: boolean;
isLocal?: boolean;
}
/**
* Layout Result布局结果中返回的基础数据
*
* @property { number } participantId 参会者id
* @property { 0 | 1 } mediagroupid 参会者画面类型,0:people画面,1:共享内容画面
* @property { string } remoteType 设备类型
* @property { string } remoteName 参会者名称
* @property { string } videoTrackId 当前参会者画面Track轨道id,用于在 VideoTrackList 中匹配stream数据
* @property { boolean } isAudioMute 参会者麦克风状态,true:开启,false:关闭
* @property { boolean } isVideoMute 参会者摄像头状态,true:开启,false:关闭
* @property { boolean } isActiveSpeaker 参会者是否是语音激励,即当前会中说话声音最大的一个人
* @property { number } LayoutVideoState 参会者画面的状态:请求中,正常,电话入会,视频暂停等
* @property { number } MuteReason 视频关闭原因
* @property { number } extUserId 参会者ID
* @property { string } calluri 参会者Url
* @property { number } ExpectHeight 期望分辨率
* @property { number } ExpectWidth 期望分辨率
* @property { number } feccOri ignore
*/
interface ILayoutRoster {
participantId: number;
mediagroupid: number;
remoteType: string;
remoteName: string;
videoTrackId: string;
isAudioMute: boolean;
isVideoMute: boolean;
isActiveSpeaker: boolean;
LayoutVideoState: number;
MuteReason: number;
extUserId: string;
calluri: string;
ExpectHeight: number;
ExpectWidth: number;
feccOri: number;
}
/**
* 自动轮询多画面状态
*
* @property NORMAL - 画面正常
* @property NO_JOINED - 未入会
* @property VIDEO_MUTE - 视频暂停
* @property NOT_FOUND - 未符合条件的终端
* @property NULL - 画面为空
*/
enum AutoState {
'NORMAL' = 'NORMAL',
'NO_JOINED' = 'NO_JOINED',
'VIDEO_MUTE' = 'VIDEO_MUTE',
'NOT_FOUND' = 'NOT_FOUND',
'NULL' = 'NULL'
}
【AUTO 布局】Layout 显示容器大小数据,配合自动布局方案使用
client.on('screen-info', (e: IScreenInfo) => {}): void;
interface screenInfo {
// 按照屏幕比例计算得到的Layout容器高度
rateHeight: number;
// 按照屏幕比例计算得到的Layout容器宽度
rateWidth: number;
// ...其他属性忽略
}
视频Track List数据,自动布局下不需要处理此监听数据,v2.0.0-v2.0.1版本自定义布局需要处理此数据,后续版本不需要处理;
提示:
client.on('video-track', (e: ICustomStreamTrack[]) => ());
interface ICustomMediaStream {
streams: MediaStream[];
track: MediaStreamTrack;
}
interface ICustomStreamTrack {
// track类型,是remote or local
status: string;
// track stream and track data
data: RTCTrackEvent | ICustomMediaStream;
// rest data
rest: {
streamId: string;
trackId: string;
track: MediaStreamTrack;
};
}
音频Track List数据,用于会议中播放所有远端参会者的声音,业务上需要默认全部播放,后续不再关注声音播放问题,由SDK控制通道数据;
不清楚怎么播放Track数据?可以参考React或者Vue Demo中的Audio组件的实现;
client.on('audio-track', (e: ICustomStreamTrack[]) => ());
interface ICustomMediaStream {
streams: MediaStream[];
track: MediaStreamTrack;
}
interface ICustomStreamTrack {
// track类型,是remote or local
status: string;
// track stream and track data
data: RTCTrackEvent | ICustomMediaStream;
// rest data
rest: {
streamId: string;
trackId: string;
track: MediaStreamTrack;
};
}
布局结果数据,自定义 custom
布局需要处理此数据,通过此数据可以进行 layout
和 video stream
的关联;
client.on('custom-layout', (e: ICustomLayoutObj[]) => ());
interface ICustomLayoutObj {
resolution: IResolutionType;
roster: IRoster;
rotate: any;
state: ILayoutState;
// 100/200是v2.0.2之前的数据格式,之后统一为0/1/2
quality: 0 | 1 | 2 | 100 | 200;
deal?: boolean;
position?: number[];
positionStyle?: { left?: string; top?: string; width?: string; height?: string };
positionInfo?: { width?: number; height?: number };
zIndex?: number;
// V3.8.0+ 支持上报参会者头像,需通过setFeatureConfig启用获取参会者头像,默认不启用。
avatar?: string;
}
// audioOnly: 语音通话中
// mute 视频暂停
// request 视频请求中
// normal 视频正常
// invalid 设备不可用
export type ILayoutState =
| 'MUTE'
| 'REQUEST'
| 'NORMAL'
| 'INVALID'
| 'AUDIO_TEL'
| 'AUDIO_ONLY'
| 'AUDIO_CONTENT';
/**
* Roster:参会者的基本信息,包含基本信息,设备信息,画面信息等
*
* @property { string } id 内部Key,包含参会者endpointId、多分组通道信息,由一定规则生成
* @property { IDeviceType } deviceType 设备类型
* @property { string } endpointId 设备id
* @property { string } displayName 参会者名称
* @property { number } mediagroupid 参会者画面类型,0:people画面,1:共享内容画面
* @property { number } participantId 参会者id
* @property { boolean } audioTxMute 参会者麦克风状态,true:开启,false:关闭
* @property { boolean } videoTxMute 参会者摄像头状态,true:开启,false:关闭
* @property { boolean } isForceFullScreen 参会者是否是主画面
* @property { number } videoMuteReason 视频关闭原因
* @property { boolean } isContent 参会者画面类型,同mediagroupid,true:是共享内容画面,false:people画面
* @property { boolean } isActiveSpeaker 参会者是否是语音激励,即当前会中说话声音最大的一个人
* @property { boolean } isLocal 是否是Local设备
* @property { boolean } audioRxMute ignore
* @property { boolean } videoRxMute ignore
* @property { boolean } onHold ignore
* @property { boolean } isLastAdd ignore
* @property { boolean } isPolling ignore
*/
interface IRoster extends Partial<ILayoutRoster> {
key: string;
deviceType: IDeviceType;
endpointId: string;
displayName: string;
mediagroupid: number;
participantId: number;
audioTxMute: boolean;
videoTxMute: boolean;
audioRxMute: boolean;
videoRxMute: boolean;
videoMuteReason: number;
isForceFullScreen: boolean;
isLastAdd: boolean;
onHold: boolean;
isPolling: boolean;
isContent: boolean;
isActiveSpeaker: boolean;
isLocal?: boolean;
}
/**
* Layout Result布局结果中返回的基础数据
*
* @property { number } participantId 参会者id
* @property { 0 | 1 } mediagroupid 参会者画面类型,0:people画面,1:共享内容画面
* @property { string } remoteType 设备类型
* @property { string } remoteName 参会者名称
* @property { string } videoTrackId 当前参会者画面Track轨道id,用于在 VideoTrackList 中匹配stream数据
* @property { boolean } isAudioMute 参会者麦克风状态,true:开启,false:关闭
* @property { boolean } isVideoMute 参会者摄像头状态,true:开启,false:关闭
* @property { boolean } isActiveSpeaker 参会者是否是语音激励,即当前会中说话声音最大的一个人
* @property { number } LayoutVideoState 参会者画面的状态:请求中,正常,电话入会,视频暂停等
* @property { number } MuteReason 视频关闭原因
* @property { number } extUserId 参会者ID
* @property { string } calluri 参会者Url
* @property { number } ExpectHeight 期望分辨率
* @property { number } ExpectWidth 期望分辨率
* @property { number } feccOri ignore
*/
interface ILayoutRoster {
participantId: number;
mediagroupid: number;
remoteType: string;
remoteName: string;
videoTrackId: string;
isAudioMute: boolean;
isVideoMute: boolean;
isActiveSpeaker: boolean;
LayoutVideoState: number;
MuteReason: number;
extUserId: string;
calluri: string;
ExpectHeight: number;
ExpectWidth: number;
feccOri: number;
}
会议成员屏幕旋转信息,用于处理横竖屏切换显示;
自定义 custom
布局需要处理此数据;
client.on('rotation-change', (e: IRotationInfo[]) => ())
interface IRotationInfoItem {
height: number;
width: number;
participantId: number;
// 数字0,1,2,3,其中:
// 2顺时针旋转180度、3顺时针旋转270度、其他的数值可以不需要处理
rotation: number;
mediagroupid: number;
}
interface IRotationInfo {
content: IRotationInfoItem[];
people: IRotationInfoItem[];
total: IRotationInfoItem[];
}
本地麦克风状态
client.on('audio-status', (e: IMeetingAudioStatus) => {});
type IMeetingAudioStatus = {
// muteAudio:本地麦克风静音状态
// unmuteAudio:本地麦克风非静音状态
status: 'muteAudio' | 'unmuteAudio';
}
client.on('video-status', (e: IMeetingVideoStatus) => {}): void;
type IMeetingVideoStatus = {
// muteVideo:本地摄像头处于关闭状态
// unmuteVideo:本地摄像头处于开启状态
status: 'muteVideo' | 'unmuteVideo';
}
当前正在分享 content 的用户详细信息
// IRoster接口类型见 roster 事件
client.on('content', (e: { data: IRoster }) => {}): void
兼容:v2.0.1 版本之前,之后以 conf-change-info 事件为准
当前正在分享 content 的用户 pid 值,可以通过会控指定允许分享content的人;
client.on('content-pid', (e: string) => {}): void
接收会议控制消息,包含麦克风静音/非静音、是否强制静音、主会场设备、对话模式等状态和信息;
兼容:
client.on('meeting-control', (e: IMeetingControl) => {}): void;
interface IMeetingControl {
// 会控是否强制静音此设备,true代表是强制静音,false代表接触强制静音
// 强制静音后,建议将麦克风图标设置为举手发言状态,配合SDK API实现举手发言/取消举手/结束发言等逻辑;
disableMute: boolean;
// 会控控制麦克风状态,unmuteAudio代表取消麦克风静音,muteAudio代表麦克风静音;
muteOperation: 'unmuteAudio' | 'muteAudio' | '';
// 会控主会场/主画面设备calluri字段
chairmanUri: string;
// v2.1.1+支持,是否禁止收听远端声音,即控制当前参会终端禁止接收会中其他参会者声音;
// 如何开启禁止收听功能:
// 1、通过会控界面操作开启/关闭参会者接收声音开关
// 2、通过小鱼Server API「禁止收听」操作会控禁止参会者收听远端音频
isMuteSpeaker: IMuteSpeaker;
// v2.1.1+支持,是否会控禁止分享Content内容;
contentIsDisabled: boolean;
// v2.1.2+支持,是否会控禁止云录制功能;
recordIsDisabled: boolean;
// v3.9.3+支持,是否开启了对话模式
conferenceMode: ConferenceMode;
// 轮询多画面控制Json字符串
customizedLayout: string;
}
/**
* 会控禁止收听远端参会者声音状态
*
* @value 'keep' - 保持上次的状态
* @value 'on' - 禁止收听
* @value 'off' - 取消禁止收听
*/
type IMuteSpeaker = 'keep' | 'on' | 'off';
/**
* 会议模式
*
* @param DIALOG - 对话模式
* @param NORMAL - 非对话模式
*/
enum ConferenceMode {
DIALOG = 'dialog',
NORMAL = 'normal'
}
字幕、点名消息
client.on('sub-title', (e: ISubTitleContent) => {}): void;
interface ISubTitleContent {
// 字体
fontFamily?: string;
// 字体颜色
fontRGB?: string;
// 是否滚动 1-滚 0-固定
scroll?: string;
action?: string; // push、cancel
location?: string; // 位置
fontSize?: string; // 字体大小
backgroundAlpha?: string; // 背景色透明度
scrollSpeed?: string; // 滚动速度
content: string; // 内容
backgroundRGB?: string; // 背景色
}
当前会议总人数
client.on('participants-count', (e: IParticipantCount) => {}): void;
interface IParticipantCount {
participantsNum: number;
}
语音激励成员数据(正在说话的人)
client.on("speaker-info", (e: IScreenInfo) => {}): void;
interface ISpeakerInfo {
// 设备类型Id
endpointId: string;
// 成员id
pid: number;
}
会议呼叫等待、等候室状态
client.on('onhold', (e: boolean) => {}): void
上报会议质量数据、参会者接收和发送质量数据、音/视频发送质量数据。如果开启调试模式,每 2s 会推送一条 Internels 数据;
质量数据在Chrome系列浏览器最为全面,在Safari和火狐浏览器下,可能部分数据不会返回;
client.on('meeting-stats', (e: IInternels) => ())
/**
* Internels 统计数据
*
* @property { number } bytesReceived 接收的字节总数
* @property { number } bytesReceivedSecond 每秒接收字节数
* @property { number } bytesSent 发送的字节总数
* @property { number } bytesSentSecond 每秒发送字节数
* @property { number } jitterSent 发送的抖动(ms)
* @property { number } jitterReceived 接受的抖动(ms)
* @property { number } roundTripTime 往返延时 (ms)
* @property { number } fractionLostSent 视频发送的丢包率
* @property { number } fractionLostReceived 视频接受的丢包率
* @property { string } mimeType 视频类型
* @property { number } timestamp 时间戳
* @property { [prop: string]: IReceiver } receiver 所有接收视频的列表数据
* @property { [prop: string]: ISender } sender 所有发送视频的列表数据
* @property { [prop: string]: IReceiver } audioReceiver 所有接收音频的列表数据
* @property { [prop: string]: ISender } audioSender 所有发送音频的列表数据
* @property { number } audioSendLost 音频发送的丢包率,v2.1.2+支持
* @property { number } audioRecvLost 音频接受的丢包率,v2.1.2+支持
*/
interface IInternels {
bytesReceived: number;
bytesReceivedSecond: number;
bytesSent: number;
bytesSentSecond: number;
jitterSent: number;
jitterReceived: number;
audioSendJitter: number;
roundTripTime: number;
fractionLostSent: number;
fractionLostReceived: number;
mimeType: string;
timestamp: number;
receiver: {
[prop: string]: IReceiver;
};
sender: {
[prop: string]: ISender;
};
audioReceiver: {
[prop: string]: IReceiver;
};
audioSender: {
[prop: string]: ISender;
};
audioSendLost?: number;
audioRecvLost?: number;
}
/**
* 接收器 Receiver 统计数据
*
* @property { number } bytesReceived 接收总量
* @property { number } bytesReceivedSecond 每秒接收数据
* @property { number } frameHeight 解码帧的height
* @property { number } frameWidth 解码帧的width
* @property { number } framesDecoded frame编码量
* @property { number } framesDecodedSecond 每秒frame编码量
* @property { number } framesReceived frame接收量
* @property { number } framesReceivedSecond 每秒frame接收量
* @property { boolean } isContent 是否是分享content
* @property { boolean } isSupport 忽略
* @property { number } jitterBufferDelay 音频样本或视频帧从接收到退出抖动缓冲区所花费的时间总和,以秒为单位
* @property { number } keyFramesDecoded 代表关键帧的总数
* @property { number } nackCount 计算此接收器发送的否定确认(NACK)数据包的总数
* @property { string } name 与会者昵称
* @property { number } packetsReceived 此传输上收到的数据包总数
* @property { number } packetsReceivedSecond 此传输上每秒收到的数据包数量
* @property { number } packetsLost 此传输上丢失的数据包总数
* @property { number } packetsLostSecond 此传输上每秒丢失的数据包数量
* @property { number } pliCount 接收器发送的图片丢失指示(PLI)数据包的总数
* @property { number } timestamp 时间戳
* @property { string } type 与会者type
* @property { number } expResolution 当前通道期望流分辨率
* @property { string } status 状态
* @property { number } framesPerSecond 此接收器解码的帧的 QP 值的总和
* @property { string } ssrc 同步源 (ssrc) 标识符是每个 [RFC3550] 的无符号整数值,用于标识此 stats 对象正在描述的 RTP 数据包流;
* 对于出站和入站本地,ssrc 描述了分别由这些端点发送和接收的轨道的统计信息;
* 对于远程入站和远程出站,ssrc 描述了由远程端点接收和发送到远程端点的轨道的统计信息;
* @property { number } jitter 视频接收抖动
* @property { string } endpointId 参会者的callUri
* @property { string } participantId participantId
* @property { number } totalSamplesReceived 总的接受采样点
* @property { number } insertedSamplesForDeceleration
* @property { number } removedSamplesForAcceleration
*/
interface IReceiver {
bytesReceived: number;
bytesReceivedSecond: number;
frameHeight: number;
frameWidth: number;
framesDecoded: number;
framesDecodedSecond: number;
framesReceived: number;
framesReceivedSecond: number;
isContent: boolean;
isSupport: boolean;
jitterBufferDelay: number;
keyFramesDecoded: number;
nackCount: number;
name: string;
packetsReceived: number;
packetsReceivedSecond: number;
packetsLost: number;
packetsLostSecond: number;
pliCount: number;
timestamp: number;
type: string;
expResolution: number;
status: string;
framesPerSecond: number;
framesDropped: number;
ssrc: string;
jitter: number;
endpointId?: string;
participantId?: number;
mimeType?: string;
audioLevel?: number; // 音频 audioLevel 值在[0, 1]之间,正常说话应该在0.1以上
insertedSamplesForDeceleration?: number;
insertedSamplesForDecelerationSecond?: number;
totalSamplesReceived?: number;
totalSamplesReceivedSecond?: number;
removedSamplesForAcceleration?: number;
removedSamplesForAccelerationSecond?: number;
ExpectWidth?: number;
ExpectHeight?: number;
}
/**
* 发送器 Sender 统计数据
*
* @property { number } bytesSent 此RTCIceTransport上发送的有效负载字节总数
* @property { number } bytesSentSecond 每秒发送有效负载字节数
* @property { number } frameHeight 编码帧的高度
* @property { number } frameWidth 编码帧的宽度
* @property { number } framesEncoded 此RTP媒体流成功编码的帧总数
* @property { number } framesEncodedSecond 每秒成功编码的帧数
* @property { number } framesSent 此RTP流上发送的帧总数
* @property { number } framesSentSecond 每秒发送的帧数
* @property { number } hugeFramesSent 此RTP流发送的huge帧的总数
* @property { string } status 忽略
* @property { number } keyFramesEncoded 此RTP媒体流编码的关键帧总数
* @property { number } packetsSent 此传输发送的数据包总数
* @property { number } packetsSentSecond 此传输每秒发送的数据包数
* @property { number } timestamp 时间戳
* @property { string } type 发送器类型
* @property { number } expBandwidth 期望带宽
* @property { string } string 分辨率
* @property { number } pliCount 计算此发送方收到的图片丢失指示 (PLI) 数据包的总数
* @property { number } firCount 接收方已向发送方发送的完整帧内请求 (FIR) 数据包的数量
* @property { number } nackCount 计算此发送方收到的否定确认 (NACK) 数据包的总数
* @property { string } ssrc 标识此 stats 对象正在描述的 RTP 数据包流;
* 对于出站和入站本地,ssrc 描述了分别由这些端点发送和接收的轨道的统计信息;
* 对于远程入站和远程出站,ssrc 描述了由远程端点接收和发送到远程端点的轨道的统计信息;
* @property { number } packetsLost 丢包总数
* @property { boolean } isContent 是否是分享content
* @property { boolean } jitter jitter
* @property { boolean } roundTripTime 往返延时
*/
interface ISender {
bytesSent: number;
bytesSentSecond: number;
frameHeight: number;
frameWidth: number;
framesEncoded: number;
framesEncodedSecond: number;
framesSent: number;
framesSentSecond: number;
hugeFramesSent: number;
status: string;
keyFramesEncoded: number;
packetsSent: number;
packetsSentSecond: number;
timestamp: number;
type: string;
expBandwidth: number;
resolution: string;
pliCount: number;
firCount: number;
nackCount: number;
ssrc: string;
mimeType: string;
audioLevel?: number;
packetsLost: number;
packetsLostSecond: number;
isContent?: boolean;
jitter?: number;
roundTripTime?: number;
}
针对 webrtc 的 internels 详细数据解释,可参考:
麦克风、摄像头权限状态
client.on("permission", (e: ICurrentPermission) => {}): void;
// v3.9.0+ 废弃此类型
// granted:已经授予权限
// denied:权限拒绝
// prompt:请求授权中
type TPermissionType = 'granted' | 'denied' | 'prompt' | '';
interface ICurrentPermission {
microphone: TPermissionType;
camera: TPermissionType;
}
// v3.9.0+ 类型更改
/**
* 采集权限状态,v3.9.0+新增
*
* @param GRANTED granted - 已授权
* @param DENIED denied - 已拒绝
* @param PROMPT prompt - 询问中
* @param UNKNOWN unknown - 未知
* @param FAILED failed - 失败
*/
enum PermissionType {
'GRANTED' = 'granted',
'DENIED' = 'denied',
'PROMPT' = 'prompt',
'UNKNOWN' = 'unknown',
'FAILED' = 'failed'
}
interface ICurrentPermission {
microphone: PermissionType;
camera: PermissionType;
}
初始入会时,返回当前选中的输入&输出设备数据
client.on("currentDevice", (e: ICurrentDevice) => {}): void;
type TCurrentSelectedDevice = {
deviceId: string;
groupId: string;
label: string;
};
type ICurrentDevice = {
audioInput: TCurrentSelectedDevice;
videoInput: TCurrentSelectedDevice;
audioOutput: TCurrentSelectedDevice;
}
设备变动时,返回变动后的输入&输出设备列表数据以及需要切换到最新的输入输出设备数据
client.on('device', async (e: IDeviceManagerChangeValue) => {}): void;
interface IDeviceManagerChangeValue {
// 设备列表发生变动时,Diff出来的新设备数据,一般情况下直接切换使用最新设备数据即可
nextDevice: {
audioInput: TCurrentSelectedDevice;
videoInput: TCurrentSelectedDevice;
audioOutput: TCurrentSelectedDevice;
};
// 所有输出/输出设备列表数据
detail: {
audioInputList: TDevice[];
audioOutputList: TDevice[];
videoInList: TDevice[];
};
};
type TDevice = {
deviceId: string;
kind: string;
type: string;
direction: 'audioinput' | 'output' | 'input';
label: string;
groupId: string;
};
export type TCurrentSelectedDevice = {
deviceId: string;
groupId: string;
label: string;
}
获取所有参会者成员信息,用于信息展示,增量推送数据
兼容: v2.0.3+
client.on('bulkRoster', async (e: IBulkRoster) => {}): void;
interface IBulkRoster {
// 数据类型,0表示全量数据,1表示增量数据
bulkRosterType: 0 | 1;
// 新增的roster信息
addRosterInfo: IRoster[];
// 变化的roster信息
changeRosterInfo: IRoster[];
// 被删除的roster信息
deleteRosterInfo: { participantId: string }[];
}
查看会议室信息
client.on('conference-info', (e: IConferenceInfo) => {}): void;
export interface IConferenceInfo {
// 最终进入的真实会议号
callNumber: string;
// 呼叫号码真实url
callUrl?: string;
// 号码id
deviceId?: string;
// 号码类型
deviceType?: string;
// 云会议号名称
displayName?: string;
// 呼叫的号码
number?: string;
// 会议号类型
numberType?: string;
// 会议配置
confAuxProperties?: IConfAuxProperties;
// 头像
avatar?: string;
// 需通过setFeatureConfig启用查询小鱼会议邀请链接信息,默认不启用
// v3.8.0+ 会议分享信息,包含会议邀请链接、电话,WebRTC、终端等端的入会方式;
inviteInfo?: InviteInfo;
// v3.8.0+ 当前会议ID
meetingId?: string;
}
/**
* 会议分享信息
*
* @property { string } displayName - 会议室名称
* @property { boolean } inEnterprise - 所属会议号是否在企业中
* @property { string } inviteAppUrl - 微信邀请链接
* @property { string } inviteUrl - 云会议室邀请链接
* @property { string } invokSchema - 小鱼客户端Scheme获取地址
* @property { string } linkNumber - 电话入会号码
* @property { string } mobileWebrtcVisibleSetting - 移动端是否显示WebRTC入会
* @property { string } number - 会议号
* @property { string } password - 入会密码
* @property { string } pstnNumber - 电话呼叫号码
* @property { string } shareUrl - 邀请链接详情页地址
* @property { string } userAvatar - 管理员头像
* @property { string } userName - 管理员名称
* @property { string } userProfileId - 用户ID
* @property { string } voiceNumber - 电话呼叫时的会议号
* @property { string } webrtcSetting - PC端是否显示WebRTC入会
* @property { string } webrtcUrl - WebRTC入会地址
*
*/
interface InviteInfo {
displayName: string;
inEnterprise: boolean;
inviteAppUrl: string;
inviteUrl: string;
invokSchema: string;
linkNumber: string;
mobileWebrtcVisibleSetting: boolean;
number: string;
password: string;
pstnNumber: string;
shareUrl: string;
userAvatar: string;
userName: string;
userProfileId: string;
voiceNumber: string;
webrtcSetting: boolean;
webrtcUrl: string;
}
自动布局时上报参会者分页数据
client.on('page-info', (e: IPageInfo) => {}): void;
interface IPageInfo {
// 每一页显示的画面数量
pageSize: number;
// 当前是第几页,默认是0开始
currentPage: number;
// 总页数
totalPage: number;
}
会议进行中参会者出/入会消息通知;
client.on('in-out-reminder', (e: IReminder[]) => {}): void;
interface IReminder {
// 用户名称
displayName: string;
// 出入会状态,in:加入会议,out:退出会议
action: 'in' | 'out';
// 用户id
userId?: string;
}
会议人员数量/Content 数量/主会场数量发生变化事件 自定义布局时,需要处理此事件,收到此事件后,需要基于人员数量进行请流操作
兼容:v2.0.3+ 开始支持totalEpCount
属性,返回会议总人数,用于信息展示;
client.on('conf-change-info', (e: IConfInfo) => {}): void;
interface IConfInfo {
// 当前会议参会者总人数,不包含共享内容设备数量
participantCount: number;
// 当前会议参会者总人数,包含共享内容、指挥调度客户端等设备数量
totalEpCount: number;
// 当前会议主会场/主画面设备的callUrl,没有为''
chairManUrl: string;
// 当前会议共享内容设别的callUrl,没有为''
contentUri: string;
// 当前会议语音激励者的callUrl,没有为''
actSpkUri: string;
// 多分组通人数信息,默认上报0和1分组,分别代表People通道和Content通道
mediaGroupInfo: IMediaGroupInfo[];
}
interface IMediaGroupInfo {
// 通道参会者数量
endpointCount: number;
// 通道
mediagroupid: number;
}
在自动布局下,调用forceFullScreen方法后,上报全屏对象的roster id信息,退出全屏则为空;
兼容:v2.1.1+
client.on('force-full-screen', (e: string) => {}): void;
实时通话字幕内容;
兼容:2.1.2+
client.on('translation-content', (data: ITranslationContent) => {});
/**
* 通话字幕内容
*
* @property { number } pid 当前说话的终端
* @property { string } src 原文
* @property { string } target 译文
* @property { number } seTime 发送时间
* @property { number } startTime 开始时间
* @property { number } endTime 结束时间
* @property { boolean } isEnd 一句话是否结束
* @property { boolean } isActive 活跃标志,收三路,同时只有一路active
* @property { string } url 终端calluri
* @property { string } dn 显示名称
* @property { string } meetingId 会议号
* @property { string } srcLang 原语言,zh表示中文,en表示英文
* @property { string } targetLang 译文语言,zh表示中文,en表示英文
*/
interface ITranslationContent {
pid: number;
src: string;
target: string;
seTime: number;
startTime: number;
endTime: number;
isEnd: boolean;
isActive: boolean;
url: string;
dn: string;
meetingId: string;
srcLang: string;
targetLang: string;
}
会议录制权限通知;
兼容:v2.1.2+
client.on('record-permission', (e: IRecordPermission) => {});
/**
* 录制权限
*
* @property { boolean } authorize 权限
* @property { string } recordingUrl 云会议室URI
* @property { string? } developerMessage 云会议室的所属用户名称
* @property { number? } errorCode 错误码
* @property { string? } userMessage 错误信息
*/
interface IRecordPermission {
authorize: boolean;
recordingUrl: string;
developerMessage?: string;
errorCode?: number;
userMessage?: string;
}
远端(或会控)录制状态通知
兼容:v2.1.2+
兼容:v3.9.6+ 版本开始支持 上报 recordInfo
字段
client.on('record-status-notification', (e: IRecordStatusNotification) => {});
/**
* 远端(或会控)录制状态通知;如果存在录制,则本地不可以进行录制
*
* @property { boolean } isStart true:存在录制;false:不存在录制
* @property { string } uri 录制的displayName,即callUri的名称,当是" "时,取会议室名称
* @property { string } callUri 谁开始/停止的录制
* @property { string } callerUri
* @property { string } status RECORDING_STATE_PAUSED(录制暂停)、RECORDING_STATE_ACTING(录制恢复)
* @property { boolean } isLocal 是否是local开启的录制
* @property { IRecordInfo } recordInfo - 录制文件相关信息
*/
interface IRecordStatusNotification {
isStart: Boolean;
uri: string;
callUri: string;
callerUri: string;
status: string;
isLocal: boolean;
recordInfo: IRecordInfo;
}
/**
* 录制相关信息
* 3.9.6+增加
*
* @property { string } recordSessionId - sessionId
*/
interface IRecordInfo {
recordSessionId: string;
}
本地录制状态上报
兼容:v2.1.2+
兼容:v3.9.6+ 版本开始 支持 上报 recordInfo
字段
client.on('recording-state-changed', (e: IRecordingStateChanged) => {});
/**
* 本地录制状态上报
*
* @property { string } reason 结果Reason,成功STATE:200
* @property { RecordingState } state 结果状态:
* @property { boolean } isRecorded 本地录制相关,暂时不用
* @property { string } controlUri
* @property { string } reasonText 提示语
* @property { IRecordInfo } recordInfo - 录制文件相关信息
*/
interface IRecordingStateChanged {
reason: string;
state: RecordingState;
isRecorded: boolean;
controlUri: string;
reasonText: string;
recordInfo: IRecordInfo;
}
/**
* 录制相关信息
* 3.9.6+增加
*
* @property { string } recordSessionId - sessionId
*/
interface IRecordInfo {
recordSessionId: string;
}
/**
* 录制状态
*
* @param RECORD_STATE_IDLE 停止成功
* @param RECORD_STATE_STARTING 开启录制
* @param RECORD_STATE_STARTED 开启成功
* @param RECORD_STATE_STOPING 停止录制
*/
enum RecordingState {
RECORD_STATE_IDLE = "RECORD_STATE_IDLE",
RECORD_STATE_STARTING = "RECORD_STATE_STARTING",
RECORD_STATE_STARTED = "RECORD_STATE_STARTED",
RECORD_STATE_STOPING = "RECORD_STATE_STOPING"
}
多分组通道信息
兼容:v2.1.2+
client.on('multi-group-info', (e: IMultiGroupInfo) => {});
/**
* @param { string } endpointId 拥有多分组的参会者/终端id
* @param { string[] | number[] } mediagrps 多路分组通道信息,启动通道时需要传递此值
*/
interface IMultiGroupInfo {
endpointId: string,
mediagrps: string[] | number[]
}
接收远端推送的自定义消息
兼容:v2.1.3+
client.on('custom-message-recv', (e: IReceiveCustomMessage) => {});
/**
* 接收到自定义消息
*
* @property { string } type - 消息Type
* @property { number } fromPid - 消息的发送方pid
* @property { number } toPid - 消息的接收方pid,0表示广播消息、非0表示单点消息;
* @property { string } data - 消息内容,可以被JSON序列化的字符串;
*/
interface IReceiveCustomMessage {
type: string;
fromPid: number;
toPid: number;
data: string;
}
登录成功后,SDK推送用户和个人云会议室信息数据;
需要注意的是,通过小鱼账号登录方式才支持获取个人云会议室信息,其他登录方式返回的个人云会议室信息为空;
兼容:v3.8.0+
client.on('user-info', (e: IExportUserInfo) => {});
/**
* 个人云会议室信息
* 默认只保存了部分信息
*
* @property { string? } meetingControlPassword 会控密码
* @property { string? } meetingNumber 个人云会议室号码
* @property { string? } password 入会密码
*/
interface ICloudRoomConfig {
meetingControlPassword: string;
meetingNumber: string;
password: string;
}
/**
* SDK登录用户信息
*
* @property { string? } callUri 用户类型ID
* @property { string } securityKey 安全码
* @property { string } access_token Token
* @property { string } refresh_token 刷新Token
* @property { number } id 用户ID
* @property { string } displayName 登录用户名
* @property { string } cellPhone 呼叫号码
* @property { string } extUserId 第三方用户ID
*/
interface ILoginInfo {
callUri?: string;
securityKey: string;
access_token: string;
refresh_token?: string;
id: number;
displayName?: string;
cellPhone?: string;
extUserId?: string;
}
/**
* 用户和对应个人云会议室信息数据
*/
interface IExportUserInfo extends ILoginInfo {
cloudRoomInfo: ICloudRoomConfig || null;
}
每隔2s推送一次实时讲话人信息
需要通过设置setFeatureConfig中的enableSpeakerInfo属性为true启用推送实时讲话人信息;
兼容:v3.8.0+
client.on('speakers-info', (e: SpeakersInfo) => {});
/**
* 讲话者信息
*
* @property { string } alias - 别名id
* @property { string } name - 讲话者名称
* @property { string } pid - pid
*
*/
interface SpeakersInfoObj {
alias: string;
name: string;
pid: number;
}
/**
* 实时讲话人消息体
*
* @property { speakersInfoObj[] } speakersInfo - 讲话者信息
*/
interface SpeakersInfo {
speakersInfo: SpeakersInfoObj[];
}
会控开启/关闭摄像头消息、提示消息
兼容:v3.8.0+
client.on('meeting-control-video', (e: IMCVideoEvent) => {});
/**
* 会控开启/关闭摄像头消息、Toast提示消息
*/
type IMCVideoEvent = controlVideoQuery | unMuteVideoQueryToast;
/**
* 主持端得到远端开启摄像头结果的提示消息体
*
* @property { string } message - 消息体,需要解析,详细内容如下:
* no.camera.permission: 终端未授权App摄像头权限
* reject.unmute.video: 参会人拒绝开启摄像头
* voice.mode: 终端在语音模式
* driving.mode: 终端在驾驶模式
* unmute.video.timeout: 超时
* @property { string } di - 终端的deviceUri
* @property { string } dn - 终端的名称
*/
interface unMuteVideoQueryToastValue extends videoQueryBase {
message: string;
di: string;
dn: string;
}
/**
* 会控推送开启/关闭摄像头消息体
*
* @property { string } key - 消息key,值为:'unMuteVideoQuery' | 'muteVideoQuery'
* @property { videoQueryBase } value - 消息详细内容
*
*/
interface controlVideoQuery {
key: queryType;
value: videoQueryBase;
}
/**
* 会控开关摄像头事件基础消息体
*
* @property { string } confUri - 会议号
* @property { string } encryption - 加密信息
* @property { boolean } force - 是否强制开启摄像头
* @property { string } meetingId - 会议ID
* @property { string } requestId - 事件ID
* @property { string } uri - 事件接收侧用户ID
*
*/
interface videoQueryBase {
confUri: string;
encryption: string;
force: boolean;
meetingId: string;
requestId: string;
uri: string;
}
监听本地端网络质量等级,用于给本地提示和通知远端网络等级信息;
兼容:v3.9.0+
client.on('networkLevel', (e: NetworkQualityLevel) => {});
/**
* 网络质量信号等级
*
* @param Bad 1 - 非常差
* @param Poor 2 - 差
* @param Good 3 - 一般
* @param Excellent 4 - 很好
*/
enum NetworkQualityLevel {
Bad = 1,
Poor,
Good,
Excellent
}
会中监听远端参会者网络质量等级,每隔5s推送一次数据;
兼容:v3.9.0+
client.on('networkParamet', (e: INetworkParameter) => {});
/**
* 远端网络质量信号等级
*
* @property { string } fromCallUri - 远端的callUri
* @property { number } fromPid - 远端的pid
* @property { NetworkQualityLevel } - networkLevel 网络质量信号等级
* @property { string } toCallUri - local callUri
*
*/
export interface INetworkParameter {
fromCallUri: string;
fromPid: number;
networkLevel: NetworkQualityLevel;
toCallUri: string;
}
/**
* 网络质量信号等级
*
* @param Bad 1 - 非常差
* @param Poor 2 - 差
* @param Good 3 - 一般
* @param Excellent 4 - 很好
*/
enum NetworkQualityLevel {
Bad = 1,
Poor,
Good,
Excellent
}
监听焦点画面信息,可通过侧边栏会控对终端设置/取消焦点画面;
兼容:v3.9.4+
client.on('focus-view', (e: IRoster | null) => {});
interface IRoster {
// 设备类型
deviceType: string;
// 设备Id
endpointId: string;
// 名称
displayName: string;
// people or content标示,0代表people,1代表Content内容
mediagroupid: number;
// 成员pid值
participantId: number;
// 当前设备麦克风的状态
audioTxMute: boolean;
// 当前设备摄像头状态
videoTxMute: boolean;
// 忽略
audioRxMute: boolean;
// 忽略
videoRxMute: boolean;
// 忽略
videoMuteReason: number;
// 是否是主会场
isFocusScreen: boolean;
// 是否是焦点画面 v3.9.4+
isFocusScreen: boolean;
// 忽略
isLastAdd: boolean;
// 是否是呼叫等待状态
onHold: boolean;
// 是否正在轮询显示
isPolling: boolean;
// 是否是content内容
isContent: boolean;
// 是否是Local设备
isLocal: boolean;
// 唯一id值
id: string;
// 是否是activeSpeaker语音激励
isActiveSpeaker?: boolean;
}
【AUTO布局】监听当前布局模式;
兼容:v2.1.2+
client.on('template-mode', (templateMode: IMode) => {});
/**
* 布局模式
*
* @param SPEAKER - 演讲者模式,即 1大N小 画面模式
* @param GALLERY - 画廊模式,即 宫格布局
*
* content布局
* @param MULTI_PIC_CONTENT_HIGH_PRIORITY - 缩略视图, Content是大窗口
* @param MULTI_PIC_ACTIVE_HIGH_PRIORITY - 缩略共享, ActiveSpeaker是大窗口
* @param TWO_PIC_PIP - 共享视图, 画中画模式(picture in picture)
* @param CONTENT_ONLY - 共享全视图, 只显示Content
* @param TWO_PIC_SYMMETRIC - 共享+演讲, 对称显示content和speaker(side by side)
*/
type IMode = "SPEAKER" | "GALLERY" | "MULTI_PIC_CONTENT_HIGH_PRIORITY" | "MULTI_PIC_ACTIVE_HIGH_PRIORITY" | "TWO_PIC_PIP" | "CONTENT_ONLY" | "TWO_PIC_SYMMETRIC"
监听和获取轮询多画面状态;
详细功能说明参考文档:轮询多画面
兼容:v3.9.8
client.on('layout-state', (state: LayoutState) => {});
/**
* Layout状态,当前仅支持上报轮询多画面状态
*
* @property { boolean } isPolling - 是否增在轮询中,true代表正在轮询中,false代表结束/暂停轮询状态
*/
interface LayoutState {
isPolling: boolean;
}
监听会控消息,包含联席主持人、改名权限等,增量推送消息;
兼容:v3.9.9
client.on('notification', (e: Notification) => {});
/**
* 联席主持人/改名权限 等消息
*
* @property { number } subType - 消息类型
* @property { NotificationContent } content - 消息详细内容
* @property { string } requestId - 消息ID
*/
export interface Notification {
subType: number;
content: NotificationContent;
requestId: string;
}
/**
* 信令上报的消息
*
* @property { CoChair } coChair - 是否是联席主持人
* @property { EnableRename } enableRename - 是否有改名权限
* @property { string } meetingId - 会议ID
*/
export interface NotificationContent {
coChair?: CoChair;
enableRename?: EnableRename;
meetingId?: string;
}
/**
* 是否有改名权限
*
* @param ON - 是
* @param OFF - 否
*/
export enum EnableRename {
ON = 'on',
OFF = 'off'
}