zby-live-sdk
Version:
This is a live SDK for weclassroom.
1,802 lines • 64.9 kB
JavaScript
import dataReport from '../network/dataReport.js';
import defaultApi from '../default';
import NOTICE from '../notice';
import { deviceListReport } from './device.js';
import util from '../util/util';
import { compareS } from '../util/sessionStorage.js';
// 扩展标识
const extensionId = 'trtc_ext';
// 端提供的 API 入口
const EM = window.EM;
// 是否执行过 TRTC 的 AddListener 的标志
let hasAddListener = false;
// 监听id
let EMListenerId = 0;
//静音推流时,音量值是否上抛上层标志 false=没有声音不往上层通知/true=有声音有上层通知
let isNoticeMicVolumeTRTC = false;
// rtc小班课=0;rtc大班课=1
const classType = 0;
// 维护的一份拉流的 streamId 与本地预览通道的映射表
let streamIdToPreviewId = {};
let previewIdToStreamId = {};
// 拉流的播放通道初始化从 0 开始依次递增至99(共100路流),-1 为推流的本地视频预览
// const uiChnIndexs = new Array(50).fill(0).map((a, b) => b + 1).reverse();
const uiChnIndexs = new Array(100).fill(0).map((a, b) => b).reverse();
// 维护的一份当前正在使用的音频设备的 deviceId 的列表
let usingAudioDeviceId = {
speaker: '',
microphone: ''
};
// 心跳
let heartBeatDataReportObj = {};
let heartBeatDataReportTimer = null;
let isFirstHeartBeatReport = false;
let streamIdRtcPlayerInfo = {};
let streamIdRtcPlayerInfo1 = {};
//记录底层推流回调的值
let dataTrtcCapture = {};
let qualityLocalArr = [];
let qualityRemoteArr = [];
const callMethod = (name, args) => {
// EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
if (EM) {
return new Promise((resolve, reject) => {
// let noneCamera = (name === 'SetVideoDevice' && !args.pszDeviceID);
// let noneMicrophone = (name === 'SetAudioDevice' && args.deviceType === 0 && !args.pszDeviceID);
// let noneSpeaker = (name === 'SetAudioDevice' && args.deviceType === 1 && !args.pszDeviceID);
// if (noneCamera || noneMicrophone || noneSpeaker) {
// return resolve();
// }
EM.CallMethod(
extensionId,
name,
JSON.stringify({...args, classType}),
(code, msg) => {
defaultApi.writeLog(`${name} Code: ${code}\nMessage: ${msg}\nParams: ${JSON.stringify({...args, classType})}`);
resolve({
code,
msg
});
}
);
});
}
};
const loadTrtc = (extensionVersion) => {
// EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
if (EM) {
return new Promise((resolve, reject) => {
removerListener();
console.log('jjjjjjj3',extensionId,extensionVersion);
EM.Load(
extensionId,
extensionVersion,
false,
(code, msg) => {
console.log('jjjjjjj4')
defaultApi.writeLog(`loadTrtc Code: ${code}\nMessage: ${msg}`);
addListener();
resolve();
}
);
});
}
};
//卸载监听
const removerListener = () => {
hasAddListener = false;
defaultApi.writeLog(`TRTC::action--removerListener EMListenerId:${EMListenerId}`);
EM.RemoverListener(extensionId, EMListenerId, (ec, content) => {});
EMListenerId = 0;
};
//加载监听
/**
* @function 添加扩展监听机制
* @param userId:Number 用户 id,必选
* @param userName:String 用户名,必选
* @param roomId:String 频道(房间) id,必选
* @param nNetType:Number 网络类型,可选,默认为 1
* @return void
*/
const addListener = () => {
// EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
if (EM && !hasAddListener) {
hasAddListener = true;
EM.AddListener(extensionId, (event, data) => {
if (data && data.indexOf(extensionId) > -1) {
try {
EMListenerId = JSON.parse(data)[extensionId];
defaultApi.writeLog(`TRTC::addListener-- EMListenerId: ${EMListenerId}`);
} catch (error) {}
}
if (!event || !data) {
return;
}
let _data = JSON.parse(data);
switch (event) {
//推流相关
//直播推流器错误通知,推流器出现错误时,会回调该通知
case 'onLocalError':
defaultApi.writeLog(`TRTC::addListener-- onLocalError: ${JSON.stringify(_data)}`);
NOTICE.pushStreamError({
errorStreamType:_data.streamType,
code: _data.code,
errorMsg: _data
})
dataReport.pushStreamError({
errorStreamType:_data.streamType,
code: _data.code
});
break;
//直播推流器警告通知
case 'onLocalWarning':
defaultApi.writeLog(`TRTC::addListener-- onLocalWarning: ${JSON.stringify(_data)}`);
NOTICE.pushStreamWarning({
warnStreamType:_data.streamType,
code: _data.code
})
dataReport.pushStreamWarning({
warnStreamType:_data.streamType,
code: _data.code
});
break;
//首帧音频推送完成的回调通知
case 'onSendLocalFirstAudioFrame':
defaultApi.writeLog(`TRTC::addListener-- onSendLocalFirstAudioFrame: ${JSON.stringify(_data)}`);
break;
//首帧视频推送完成的回调通知
case 'onSendLocalFirstVideoFrame':
defaultApi.writeLog(`TRTC::addListener-- onSendLocalFirstVideoFrame: ${JSON.stringify(_data)}`);
NOTICE.pushFlowSuccess({code:0,publish_streamid: _data.strStreamId});
dataReport.publishResult({
code: '0',
// publish_streamid: window.zbyAVSDK_init_params.trtc.streamId,
});
break;
//麦克风采集音量值回调
case 'onLocalMicrophoneVolumeUpdate':
// defaultApi.writeLog(`TRTC::addListener-- onLocalMicrophoneVolumeUpdate: ${JSON.stringify(_data)}`);
if (isNoticeMicVolumeTRTC) {
NOTICE.captureMicVolumeChanged({
volume: Math.round(_data.volume)
});
}
// heartBeatDataReportObj.volume.push(Math.round(_data.pCaptureSoundLevel[0].soundLevel));
heartBeatDataReportObj.volume = heartBeatDataReportObj.volume + Math.round(_data.volume) + ',';
break;
break;
//推流器连接状态回调通知。推流器连接状态 0 与服务器断开连接/1 正在连接服务器/2 连接服务器成功/3 重连服务器中
case 'onLocalConnectStatusUpdate':
defaultApi.writeLog(`TRTC::addListener-- onLocalConnectStatusUpdate: ${JSON.stringify(_data)}`);
dataReport.localConnectStatus({
connectStatuStreamType:_data.streamType,
state: _data.state
});
break;
//网络质量的实时统计回调
// 统计回调每间隔2秒抛出一次,用于通知 SDK 感知到的当前网络的质量。
// * SDK 会使用一组内嵌的自研算法对当前网络的延迟高低、带宽大小以及稳定情况进行评估,并计算出一个的评估结果:
// * 如果评估结果为 1(Excellent) 代表当前的网络情况非常好,如果评估结果为 6(Down)代表当前网络无法支撑 SDK 的正常使用。
// * @param quality 网络状态。0未检测;1当前网络非常好;2当前网络比较好;3当前网络一般;4当前网络较差;5当前网络很差;6当前网络不满足 TRTC 的最低要求
case 'onLocalNetworkQuality':
// defaultApi.writeLog(`TRTC::addListener-- onLocalNetworkQuality: ${_data.quality}`);
if(_data.quality == 4 || _data.quality == 5 || _data.quality == 6) {
NOTICE.localNetworkQuality({code: _data.quality});
dataReport.localNetworkQuality({
code: _data.quality,
// publish_streamid: window.zbyAVSDK_init_params.trtc.streamId,
});
}
qualityLocalArr.push(_data.quality);
break;
//直播推流器统计数据回调 number类型
//appCpu 当前 App 的 CPU 使用率(%)
// systemCpu 当前系统的 CPU 使用率(%)
// width 视频宽度
// height 视频高度
// fps 帧率(fps)
// audioBitrate 视频码率(Kbps)
// videoBitrate 音频码率(Kbps)
// case 'onLocalStatisticsUpdate':
// defaultApi.writeLog(`TRTC::addListener-- onLocalStatisticsUpdate: ${_data}`);
// break;
//拉流相关
//远端流错误通知,拉流出现错误时,会回调该通知
case 'onRemoteError':
defaultApi.writeLog(`TRTC::addListener-- onRemoteError: ${JSON.stringify(_data)}`);
NOTICE.pullStreamError({
strErrorStreamId: _data.strStreamId,
code:_data.code
})
//是否需要数据上报?@yuqian
break;
//远端流警告通知,拉流出现警告时,会回调该通知。
case 'onRemoteWarning':
defaultApi.writeLog(`TRTC::addListener-- onRemoteWarning: ${JSON.stringify(_data)}`);
NOTICE.pullStreamWarning({
strWarnStreamId: _data.strStreamId,
code:_data.code
})
//是否需要数据上报?@yuqian
break;
//拉到音频首帧
case 'onRemoteAudioStatus':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteAudioStatus: ${_data}`);
console.log('onRemoteAudioStatus',_data);
try{
NOTICE.firstAudioSize({
streamId: _data.strStreamId,
userId: util.getUidByStreamId(_data.strStreamId)
});
dataReport.firstAudioSize({
pull_streamid: _data.strStreamId,
pull_uid: util.getUidByStreamIdDr(_data.strStreamId),
code:'0'
});
} catch (e) { };
break;
//远端流音量大小
case 'onRemoteAudioVolume':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteAudioVolume: ${JSON.stringify(_data)}`);
let cbData = {
streamId: _data.strStreamId,
volume: _data.volume
}
NOTICE.playerVolumeChanged(cbData);
NOTICE.volumeChange(cbData);
// currStreamIdRtcPlayerInfo && currStreamIdRtcPlayerInfo.volume.push(Math.round(item.soundLevel));
// streamIdRtcPlayerInfo[_data.strStreamId] && streamIdRtcPlayerInfo[_data.strStreamId].volume.push(Math.round(item.soundLevel));
if(streamIdRtcPlayerInfo[_data.strStreamId]) {
streamIdRtcPlayerInfo[_data.strStreamId].volume = streamIdRtcPlayerInfo[_data.strStreamId].volume + Math.round(_data.volume)+ ',';
}
break;
// //远端流收到首帧音频
// case 'onRemoteAudioStart':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteAudioStart: ${_data}`);
// break;
// //远端流停止推送音频
// case 'onRemoteAudioStop':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteAudioStop: ${_data}`);
// break;
//mute 视频状态,true:远端开始推流,并拉流收到首帧;false:远端停止推流。
case 'onRemoteVideoStatus':
defaultApi.writeLog(`TRTC::addListener-- onRemoteVideoStatus: ${JSON.stringify(_data)}`);
console.log('onRemoteVideoStatus',_data);
try{
NOTICE.pullFlowResult({code:0,pull_streamid: _data.strStreamId});
NOTICE.firstVideoSize({
streamId: _data.strStreamId,
// userId: _data.strStreamId.split('_').length == 5 ? _data.strStreamId : util.getUidByStreamId(_data.strStreamId)
userId: util.getUidByStreamId(_data.strStreamId)
});
dataReport.firstVideoSize({
pull_streamid: _data.strStreamId,
pull_uid: util.getUidByStreamIdDr(_data.strStreamId),
code:'0'
});
} catch (e) { };
break;
//sei
case 'onRecvSEIMsg':
// defaultApi.writeLog(`TRTC::addListener-- onRecvSEIMsg: ${_data}`);
break;
//网络质量的实时统计回调
// * 该统计回调每间隔2秒抛出一次,用于通知 SDK 感知到的当前网络的质量。
// * SDK 会使用一组内嵌的自研算法对当前网络的延迟高低、带宽大小以及稳定情况进行评估,并计算出一个的评估结果:
// * 如果评估结果为 1(Excellent) 代表当前的网络情况非常好,如果评估结果为 6(Down)代表当前网络无法支撑 SDK 的正常使用。
// *
// * @param strStreamId 流ID,表示远端用户信息。
// * @param quality 网络状态。0未检测;1当前网络非常好;2当前网络比较好;3当前网络一般;4当前网络较差;5当前网络很差;6当前网络不满足 TRTC 的最低要求
case 'onRemoteNetworkQuality':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteNetworkQuality: ${_data}`);
if(_data.quality == 4 || _data.quality == 5 || _data.quality == 6) {
NOTICE.remoteNetworkQuality({code: _data.quality});
dataReport.remoteNetworkQuality({
code: _data.quality,
// publish_streamid: window.zbyAVSDK_init_params.trtc.streamId,
});
}
qualityRemoteArr.push(_data.quality);
break;
// 转推 CDN 上发布音视频流的事件回调
// * @param state 0转推成功,1表示失败
// * @param err 0表示成功,其余值表示失败
// * @param errMsg 具体错误原因
case 'onRtmpStreamingStateChanged':
defaultApi.writeLog(`TRTC::addListener-- onRtmpStreamingStateChanged: ${JSON.stringify(_data)}`);
break;
//* 本地麦克风设备的通断状态发生变化(仅适用于桌面系统)
// * @param deviceId 设备 ID
// * @param state 通断状态,0:设备已添加;1:设备已被移除;2:设备已启用。
case 'onMicphoneDeviceChanged':
defaultApi.writeLog(`TRTC::addListener-- onMicphoneDeviceChanged: ${JSON.stringify(_data)}`);
setMicrophoneDevice({deviceId: _data.state ==1 ? '' : _data.deviceId, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceId});
break;
//* 本地摄像头设备的通断状态发生变化(仅适用于桌面系统)
// * @param deviceId 设备 ID
// * @param state 通断状态,0:设备已添加;1:设备已被移除;2:设备已启用。
case 'onVideoDeviceChanged':
defaultApi.writeLog(`TRTC::addListener-- onVideoDeviceChanged: ${JSON.stringify(_data)}`);
setVideoDevice({deviceId: _data.state ==1 ? '' : _data.deviceId, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceId});
break;
//扬声器热插拔
case 'onSpeakerDeviceChanged':
defaultApi.writeLog(`TRTC::addListener-- onSpeakerDeviceChanged: ${JSON.stringify(_data)}`);
setSpeakerDevice({deviceId: _data.state ==1 ? '' : _data.deviceId, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceId});
break;
//推流的统计数据。5秒一个周期
case 'onLocalStatistics':
// defaultApi.writeLog(`TRTC::addListener-- onLocalStatistics: ${_data}`);
console.log('onLocalStatistics',JSON.parse(_data.json));
NOTICE.pushLossAndDelay({
// userId: util.getUidByStreamId(_data.strStreamId),
delay:_data.rtt,
lostrate:_data.packetLoss
});
heartBeatDataReportCalc(event, _data);
break;
//拉流的统计数据。5秒一个周期
case 'onRemoteStatistics':
// defaultApi.writeLog(`TRTC::addListener-- onRemoteStatistics: ${_data}`);
console.log('onRemoteStatistics',JSON.parse(_data.json));
try {
NOTICE.playLossAndDelay({
userId: util.getUidByStreamId(_data.streamId),
delay:_data.rtt,
lostrate:_data.packetLoss
});
}catch(e){}
heartBeatDataReportCalc(event, _data);
break;
case 'onStatisticsUpdate':
// defaultApi.writeLog(`TRTC::addListener-- onStatisticsUpdate: ${JSON.stringify(_data)}`);
// console.log('onStatisticsUpdate',JSON.parse(_data.json).local);
// console.log('onStatisticsUpdate',JSON.parse(_data.json));
// heartBeatDataReportCalc(event, _data);
break;
}
if (zbysdk.openListenerLog) {
console.log(`[zby-live-sdk]--TRTC::Listener:: event: ${event}, data: ${data}`);
}
});
}
};
//初始化相关
const init = async (args) => {
defaultApi.writeLog(`avsdk TRTC::init ${JSON.stringify(args)}`);
const usedDevices = window.zbyAVSDK_device_checker_init;
const {devices} = args;
const _devices = {
camera: (devices && devices.camera) || (usedDevices && usedDevices.camera && usedDevices.camera.use) || '',
microphone: (devices && devices.microphone) || (usedDevices && usedDevices.microphone && usedDevices.microphone.use) || '',
speaker: (devices && devices.speaker) || (usedDevices && usedDevices.speaker && usedDevices.speaker.use) || ''
};
await loadTrtc(args.extensionVersion);
await startEngine(args.appId,args.userId, args.usersign);
if(args.role === 'teacher' && args.mode === 1){
//坐立模式开启外部采集器,站立关闭外部采集器,只有小组课坐立模式才会调用,通过这个把rtmp数据给到zego或者rtc(头像),开启了外部采集,zego不会再本地采集数据
await setEnableExternVideoCapture(true);
}
//小班课 需要加载采集插件的输入数据,为了拼接zego头像
if (args.classMode === 1 || args.classMode === 2) {
defaultApi.writeLog('loadCollectionInputEntry')
loadCollectionInputEntry();
};
await setCameraEncodeBiarate(args.encodeCaptureBitrate);
await setCameraEncodeFps(args.encodeCaptureFps);
await setCameraCaptureResolution(args.previewResolutionWidth, args.previewResolutionHeight);
await setCameraEncodeResolution(args.encodedResolutionWidth, args.encodedResolutionHeight);
// await setCameraEncodeBiarate(args.screenSameBitrate,1);
// await setCameraEncodeFps(args.screenSameFps, 1);
// await setCameraCaptureResolution(args.screenSameResolutionWidth, args.screenSameResolutionHeight, 1);
// await setCameraEncodeResolution(args.screenSameResolutionWidth, args.screenSameResolutionHeight, 1);
// await setCameraEncodeBiarate(500000);
// await setCameraEncodeFps(15);
// await setCameraCaptureResolution(640, 480);
// await setCameraEncodeResolution(320, 240);
await setDefaultDevice(_devices,'default');
await setMicphoneVolumInterval(500);
window.current_sdk_type = 'trtc';
defaultApi.writeLog('trtc init finished current_sdk_type : trtc');
};
/**
* @function 初始化引擎
* @param appid:String TRTC 秘钥,必选
* @param userid:String
* @param usersign:String
* @return Promise | void
*/
const startEngine = (appid, userid, usersign) => {
defaultApi.writeLog(`avsdk TRTC::StartEngine appid: ${appid} userid: ${userid} usersign: ${usersign}`);
return callMethod('StartEngine', {
appid,
userid:userid + '',
usersign
});
};
const setEnableExternVideoCapture = (enable) => {
defaultApi.writeLog(`avsdk TRTC::EnableExternVideoCapture`);
return callMethod('EnableExternVideoCapture', {
enable
});
};
/**
* @function 销毁引擎
* @return Promise | void
*/
const destroyEngine = () => {
return callMethod('DestroyEngine', {});
};
//设置采集分辨率
const setCameraCaptureResolution = (width, height) => {
return callMethod('SetCameraCaptureResolution',{width, height});
}
//设置编码分辨率
const setCameraEncodeResolution = (width, height) => {
return callMethod('SetCameraEncodeResolution',{width, height})
}
//设置编码帧率
const setCameraEncodeFps = (fps) => {
return callMethod('SetCameraEncodeFps',{fps})
}
//设置编码码率
const setCameraEncodeBiarate = (bitrate) => {
return callMethod('SetCameraEncodeBiarate',{bitrate})
}
//获取指定摄像头的支持的分辨率
const getCameraResolution = (deviceId) => {
return callMethod('GetCameraResolution',{deviceId})
}
/**
* @function 设置默认的硬件设备,包括摄像头、麦克风以及扬声器
* @return Promise
*/
export const setDefaultDevice = async (devices, operationType) => {
// 设置默认的摄像头
if (devices && devices.camera) {
if (zbyAVSDK_device_checker_init.camera.list.length == 0) {
await getCameraDeviceListTrtc();
}
await setVideoDevice({deviceId: devices.camera, operationType:`${operationType}_1`});
} else {
const cameraData = await getCameraDeviceListTrtc();
if (cameraData.length) {
let hasSetCamera = false;
for (let item of cameraData) {
if (item.isDefault) {
await setVideoDevice({deviceId: item.deviceId, operationType:`${operationType}_2`});
hasSetCamera = true;
break;
}
}
if (!hasSetCamera) {
await setVideoDevice({deviceId: cameraData[0].deviceId, operationType:`${operationType}_3`});
}
}
}
// 设置默认的麦克风
if (devices && devices.microphone) {
if (zbyAVSDK_device_checker_init.microphone.list.length == 0) {
await getMicrophoneDeviceListTrtc();
}
console.log('pp2');
await setMicrophoneDevice({deviceId: devices.microphone, operationType:`${operationType}_1`});
} else {
console.log('pp3');
const microPhoneData = await getMicrophoneDeviceListTrtc();
try {
if (microPhoneData.length) {
let hasSetMicrophone = false;
for (let item of microPhoneData) {
if (item.isDefault) {
await setMicrophoneDevice({deviceId: item.deviceId, operationType:`${operationType}_2`});
hasSetMicrophone = true;
break;
}
}
if (!hasSetMicrophone) {
await setMicrophoneDevice({deviceId: microPhoneData[0].deviceId, operationType:`${operationType}_3`});
}
}
} catch (e){
console.log(e);
}
}
// 设置默认的扬声器
if (devices && devices.speaker) {
await setSpeakerDevice({deviceId: devices.speaker, operationType:`${operationType}_1`});
} else {
const speakerData = await getSpeakerDeviceListTrtc();
if (speakerData.length) {
let hasSetSpeaker = false;
for (let item of speakerData) {
if (item.isDefault) {
await setSpeakerDevice({deviceId: item.deviceId, operationType:`${operationType}_2`});
hasSetSpeaker = true;
break;
}
}
if (!hasSetSpeaker) {
await setSpeakerDevice({deviceId: speakerData[0].deviceId, operationType:`${operationType}_3`});
}
}
}
};
//麦克风相关
/**
* @function 开启麦克风
* @param intervalMs: Number
* @return Promise | void
*/
const startMicrophone = (intervalMs = 500) => {
return callMethod('StartMicrophone', {intervalMs});
}
/**
* @function 关闭麦克风
* @return Promise | void
*/
const stopMicrophone = () => {
return callMethod('StopMicrophone', {});
}
const openOrCloseMicrophone = async (operation) => {
isNoticeMicVolumeTRTC = operation;
if(operation) {
await startMicrophone();
} else {
await stopMicrophone();
}
}
/**
* @function 设置麦克风音量大小回调周期
* @param intervalMs: Number
* @return Promise | void
*/
const setMicphoneVolumInterval = (intervalMs) => {
return callMethod('SetMicphoneVolumInterval',{intervalMs});
};
/**
* @function 获取麦克风设备列表
* @return Promise | void
*/
const getMicrophoneDeviceList = () => {
return callMethod('GetMicrophoneDeviceList', {});
}
/**
* @function 获取麦克风列表
* @return Promise | void
*/
const getMicrophoneDeviceListTrtc = async () => {
console.log('getMicrophoneDeviceListTrtc_microphoneListArr_trtc_ii');
let microphoneListArr = JSON.parse(JSON.parse((await getMicrophoneDeviceList()).msg).DeviceList);
console.log('getMicrophoneDeviceListTrtc_microphoneListArr_trtc_iii',microphoneListArr);
let microphoneList = [];
for (let i = 0, len = microphoneListArr.length; i < len; i++) {
microphoneList.push({
deviceId: microphoneListArr[i].id,
deviceName: microphoneListArr[i].name,
isDefault: microphoneListArr[i].default
});
deviceListReport.micList[microphoneListArr[i].szDeviceId] = microphoneListArr[i].szDeviceName;
}
if (!window.zbyAVSDK_device_checker_init) {
window.zbyAVSDK_device_checker_init = {};
}
if (!window.zbyAVSDK_device_checker_init.microphone) {
window.zbyAVSDK_device_checker_init.microphone = {};
}
window.zbyAVSDK_device_checker_init.microphone.hasTest = true;
window.zbyAVSDK_device_checker_init.microphone.list = microphoneList;
console.log('getMicrophoneDeviceListTrtc_microphoneListArr_trtc',microphoneList);
return microphoneList;
}
/**
* @function 设置指定音频(当前麦克风)设备
* @param deviceId:String 音频设备 id,必选
* @return Promise | void
*/
const setCurrentMicrophoneDevice = (deviceId) => {
window.zbyAVSDK_device_checker_init.microphone.use = deviceId;
return callMethod('SetCurrentMicrophoneDevice', {
deviceId
});
}
/**
* @function 指定麦克风设备
* @param deviceId:String 麦克风设备 id,必选
* @param operationType:String 操作类型,可选
* @return Promise | void
*/
const setMicrophoneDevice = async (args) => {
console.log('getMicrophoneDeviceListTrtc_microphoneListArr_trtc_i');
let {deviceId, operationType, deviceState, changedDeviceId} = args;
let deviceName = '';
let microPhoneData;
if (!deviceId) {
microPhoneData = await getMicrophoneDeviceListTrtc();
if (microPhoneData.length) {
let hasGetMicrophone = false;
for (let item of microPhoneData) {
if (item.isDefault) {
deviceId = item.deviceId;
deviceName = item.deviceName;
hasGetMicrophone = true;
break;
}
}
if (!hasGetMicrophone) {
deviceId = microPhoneData[0].deviceId;
deviceName = microPhoneData[0].deviceName;
}
} else {
deviceId = '';
}
if (deviceId === '') {
NOTICE.noDevice({
deviceType: 'microphone'
});
}
}
try {
dataReport.setDevice({
device_type:2,
device_id:deviceId,
device_name:deviceListReport.micList[deviceId],
operationType,
fore_state: operationType == 'hotPlug' ? +deviceState+1 : '-'
});
window.zbyAVSDK_device_checker_init.microphone.name = deviceListReport.micList[deviceId];
} catch (e) {};
await setCurrentMicrophoneDevice(deviceId);
if (operationType == 'hotPlug' || operationType == 'deviceError') {
if(!microPhoneData){
microPhoneData = await getMicrophoneDeviceListTrtc();
deviceName = deviceListReport.micList[deviceId];
}
NOTICE[operationType]({
deviceType: 'microphone',
useDeviceId: deviceId,
useDeviceName: deviceName,
deviceList: microPhoneData,
deviceState,
changedDeviceId
});
}
}
/**
* @function 获取当前麦克风的音量
* @return Promise | void
*/
const getCurrentMicrophoneVolume = () => {
return callMethod('GetCurrentMicrophoneVolume', {}).then(ret => {
let volume = 0;
try {
volume = JSON.parse(ret.msg).microphoneVolume;
} catch (e) {
console.error(`zby-live-sdk: getCurrentMicrophoneVolume ret: ${ret}. error: ${e}`);
}
return volume;
});
}
/**
* @function 设置当前麦克风的音量
* @param volume : number 音量值
* @return Promise | void
*/
const setCurrentMicrophoneVolume = (volume) => {
return callMethod('SetCurrentMicrophoneVolume', {volume});
}
/**
* @function 获取当前麦克风ID
* @return Promise | void
*/
const getCurrentMicrophoneId = (volume) => {
return callMethod('GetCurrentMicrophoneId', {volume});
}
//摄像头相关
/**
* @function 打开摄像头
* @param width: Number
* @param height: Number
* @return Promise | void
*/
const startCamera = (width,height) => {
return callMethod('StartCamera', {width,height});
}
/**
* @function 关闭摄像头
* @return Promise | void
*/
const stopCamera = () => {
return callMethod('StopCamera', {});
}
const openOrCloseCamera = async (operation) => {
console.log('openCa',operation);
if(operation){
await startCamera();
} else {
await stopCamera();
}
}
/**
* @function 获取摄像头列表
* @return Promise | void
*/
const getCameraDeviceList = () => {
return callMethod('GetCameraDeviceList', {});
}
/**
* @function 获取摄像头列表
* @return Promise | void
*/
export const getCameraDeviceListTrtc= async () => {
let videoListArr = JSON.parse(JSON.parse((await getCameraDeviceList()).msg).DeviceList);
console.log('GetCameraDeviceList_cameraList_trtc_iiii',videoListArr);
let videoList = [];
for (let i = 0, len = videoListArr.length; i < len; i++) {
videoList.push({
deviceId: videoListArr[i].id,
deviceName: videoListArr[i].name,
isDefault: videoListArr[i].default
});
deviceListReport.cameraList[videoListArr[i].szDeviceId] = videoListArr[i].szDeviceName;
}
if (!window.zbyAVSDK_device_checker_init) {
window.zbyAVSDK_device_checker_init = {};
}
if (!window.zbyAVSDK_device_checker_init.camera) {
window.zbyAVSDK_device_checker_init.camera = {};
}
window.zbyAVSDK_device_checker_init.camera.hasTest = true;
window.zbyAVSDK_device_checker_init.camera.list = videoList;
console.log('GetCameraDeviceList_cameraList_trtc',videoList);
return videoList;
};
/**
* @function 设置指定视频(当前摄像头)设备
* @param deviceId:String 视频设备 id,必选
* @return Promise | void
*/
const setCurrentCameraDevice = (deviceId) => {
window.zbyAVSDK_device_checker_init.camera.use = deviceId;
return callMethod('SetCurrentCameraDevice', {
deviceId
});
}
/**
* @function 指定使用的摄像头
* @param deviceId:String 摄像头 id,必选
* @param operationType:String 操作类型,可选
* 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
* 不传即是普通的设置摄像头设备的行为
* @return Promise | void
*/
const setVideoDevice = async (args) => {
defaultApi.writeLog(`${JSON.stringify(args)}----setVideoDevice-trtc----`);
let {deviceId, operationType, deviceState, code, changedDeviceId} = args;
let deviceName = '';
let cameraData;
if (!deviceId) {
cameraData = await getCameraDeviceListTrtc();
// console.log('hsghsghsg0',cameraData);
if (cameraData.length) {
let hasGetCamare = false;
// console.log('hsghsghsg1',hasGetSpeaker);
for (let item of cameraData) {
if (item.isDefault) {
deviceId = item.deviceId;
deviceName = item.deviceName;
hasGetCamare = true;
break;
}
}
// console.log('hsghsghsg2',hasGetSpeaker);
if (!hasGetCamare) {
deviceId = cameraData[0].deviceId;
deviceName = cameraData[0].deviceName;
// console.log('hsghsghsg91',deviceId);
}
} else {
deviceId = '';
}
// console.log('hsghsghsg1',deviceId);
if (deviceId === '') {
NOTICE.noDevice({
deviceType: 'camera'
});
}
}
window.zbyAVSDK_device_checker_init.camera.use = deviceId;
window.zbyAVSDK_device_checker_init.camera.name = deviceListReport.cameraList[deviceId];
try {
dataReport.setDevice({
device_type: 1,
device_id:deviceId,
device_name:deviceListReport.cameraList[deviceId],
operationType,
fore_state: operationType == 'hotPlug' ? deviceState+1 : '-'
});
} catch (e) {};
await setCurrentCameraDevice(deviceId);
if (operationType == 'hotPlug' || operationType == 'deviceError') {
if(!cameraData){
cameraData = await getCameraDeviceListTrtc();
deviceName = deviceListReport.cameraList[deviceId];
}
NOTICE[operationType]({
deviceType: 'camera',
useDeviceId: deviceId,
useDeviceName: deviceName,
deviceList: cameraData,
messge: code,
deviceState,
changedDeviceId
});
}
try {
NOTICE.useredCamera({
deviceId,
deviceName
});
} catch (e){ };
};
/**
* @function 获取当前摄像头ID
* @return Promise | void
*/
const GetCurrentCameraId = () => {
return callMethod('GetCurrentCameraId', {});
}
//扬声器相关
/**
* @function 获取扬声器列表
* @return Promise | void
*/
const getSpeakerDeviceList = () => {
return callMethod('GetSpeakerDeviceList', {});
}
/**
* @function 获取扬声器列表
* @return Promise | void
*/
const getSpeakerDeviceListTrtc = async () => {
let speakerListArr = JSON.parse(JSON.parse((await getSpeakerDeviceList()).msg).DeviceList);
console.log('getSpeakerDeviceList_speakerListArr_trtc_ii',speakerListArr);
let speakerList = [];
for (let i = 0, len = speakerListArr.length; i < len; i++) {
speakerList.push({
deviceId: speakerListArr[i].id,
deviceName: speakerListArr[i].name,
isDefault: speakerListArr[i].default
});
deviceListReport.speakerList[speakerListArr[i].szDeviceId] = speakerListArr[i].szDeviceName;
}
if (!window.zbyAVSDK_device_checker_init) {
window.zbyAVSDK_device_checker_init = {};
}
if (!window.zbyAVSDK_device_checker_init.speaker) {
window.zbyAVSDK_device_checker_init.speaker = {};
}
window.zbyAVSDK_device_checker_init.speaker.hasTest = true;
window.zbyAVSDK_device_checker_init.speaker.list = speakerList;
console.log('getSpeakerDeviceList_speakerListArr_trtc_iii',speakerList);
return speakerList;
};
/**
* @function 设置指定音频(当前扬声器)设备
* @param deviceId:String 音频设备 id,必选
* @return Promise | void
*/
const setCurrentSpeakerDevice = (deviceId) => {
window.zbyAVSDK_device_checker_init.speaker.use = deviceId;
return callMethod('SetCurrentSpeakerDevice', {
deviceId
});
}
/**
* @function 指定扬声器
* @param deviceId:String 扬声器 id,必选
* @param operationType:String 操作类型,可选
* 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
* 不传即是普通的设置扬声器设备的行为
* @return Promise | void
*/
const setSpeakerDevice = async (args) => {
defaultApi.writeLog(`${JSON.stringify(args)}----setSpeakerDevice-trtc----`);
console.log('hsghsghsg999',args);
let {deviceId, operationType, deviceState, code, changedDeviceId} = args;
let deviceName = '';
let speakerData;
if (!deviceId) {
speakerData = await getSpeakerDeviceListTrtc();
console.log('hsghsghsg0',speakerData.length);
if (speakerData.length) {
let hasGetSpeaker = false;
console.log('hsghsghsg1',hasGetSpeaker);
for (let item of speakerData) {
if (item.isDefault) {
deviceId = item.deviceId;
deviceName = item.deviceName;
hasGetSpeaker = true;
break;
}
}
console.log('hsghsghsg2',hasGetSpeaker);
if (!hasGetSpeaker) {
deviceId = speakerData[0].deviceId;
deviceName = speakerData[0].deviceName;
console.log('hsghsghsg91',deviceId);
}
} else {
deviceId = '';
}
if (deviceId === '') {
NOTICE.noDevice({
deviceType: 'speaker'
});
}
}
console.log('hsghsghsg999',deviceId);
try {
dataReport.setDevice({
device_type:3,
device_id:deviceId,
device_name:deviceListReport.speakerList[deviceId],
operationType,
fore_state: operationType == 'hotPlug' ? deviceState+1 : '-'
});
window.zbyAVSDK_device_checker_init.speaker.name = deviceListReport.speakerList[deviceId];
} catch (e) {
console.log(e);
};
console.log('hsghsghsg99911',deviceId);
usingAudioDeviceId.speaker = deviceId;
await setCurrentSpeakerDevice(deviceId);
if (operationType == 'hotPlug' || operationType == 'deviceError') {
if(!speakerData){
speakerData = await getSpeakerDeviceListTrtc();
deviceName = deviceListReport.speakerList[deviceId];
}
console.log('hsghsghsg99911',deviceId);
NOTICE[operationType]({
deviceType: 'speaker',
useDeviceId: deviceId,
useDeviceName: deviceName,
deviceList: speakerData,
message: code,
deviceState,
changedDeviceId
});
}
console.log('hsghsghsg999112',deviceId);
};
/**
* @function 获取当前扬声器的音量
* @return Promise | void
*/
const getCurrentSpeakerVolume = () => {
return callMethod('GetCurrentSpeakerVolume', {});
}
/**
* @function 获取当前扬声器ID
* @return Promise | void
*/
const getCurrentSpeakerId = () => {
return callMethod('GetCurrentSpeakerId', {});
}
/**
* @function 设置当前扬声器音量
* @param volume : number 音量值
* @return Promise | void
*/
const setCurrentSpeakerVolume = (volume) => {
return callMethod('SetCurrentSpeakerVolume', {volume});
}
/**
* @function 打开系统声音采集
* @return Promise | void
*/
const startSystemAudioLoopback = () => {
return callMethod('StartSystemAudioLoopback', {});
}
/**
* @function 关闭系统声音采集
* @return Promise | void
*/
const stopSystemAudioLoopback = () => {
return callMethod('StopSystemAudioLoopback', {});
}
//采集扬声器声音
const setAudioSpeakerCapture = (speaker) => {
if(speaker) {
return startSystemAudioLoopback();
} else {
return stopSystemAudioLoopback();
}
}
//sei
/**
* @function sei消息
* @param data: String 数据
* @param dataSize: Number 数据长度
* @param repeatCount: Number 发送次数
* @return Promise | void
*/
const sendSEIMsg = (data,dataSize,repeatCount) => {
if (typeof dataSize === 'undefined') {
dataSize = data.length;
};
if (typeof repeatCount === 'undefined') {
repeatCount = 1;
}
return callMethod('SendSEIMsg', {data,dataSize,repeatCount});
}
//采集相关
/**
* @function 开始屏幕采集
* @return Promise | void
*/
const startScreenCapture = () => {
return callMethod('StartScreenCapture', {});
}
/**
* @function 停止屏幕采集
* @return Promise | void
*/
const stopScreenCapture = () => {
return callMethod('StopScreenCapture', {});
}
//推拉流相关
/**
* @function 开启本地或者远程的视频视图
* @param isLocal:Boolean 是否是本地的视频预览,必选
* @param streamId:String 要拉取的视频流的 id,可选,只有拉取远程的视频流的时候才是必选的
* @param domId:String <video> 标签的 id,可选
* 如果传了 domId,就把视频绑定到对应的 <video> 标签上
* @return Promise 可从 Promise 中获取 src,Promise.then((src) => {})
*/
const startLocalOrRemotePreview = async (isLocal, streamId, domId, isTeacherNewWindowPreview) => {
defaultApi.writeLog(`${streamId}----streamId-trtc---- ${isLocal}`);
let isUpdateChromeVersion = await util.getChromeVersion();
// 预览本地视频的话,流 id 从全局配置中获取
// if (isLocal) {
// streamId = isInRoom ? (window.zbyAVSDK_init_params && window.zbyAVSDK_init_params.trtc.streamId)
// : 'deviceCheckerInit';
// }
const externalConstraints = {
audio: false,
video: {
mandatory: {
chromeMediaSource: 'external',
chromeMediaSourceId: `ems://trtc_ext/${isLocal || isTeacherNewWindowPreview ? -3 : streamId}`
}
}
};
console.log('externalConstraints',externalConstraints);
return new Promise((resolve, reject) => {
const handleExternalSuccess = (stream) => {
defaultApi.writeLog(`${stream}----stream-trtc----`);
stream.oninactive = () => {
defaultApi.writeLog('Stream inactive');
};
const src = isUpdateChromeVersion? stream : window.URL.createObjectURL(stream);
console.log('内核升级', isUpdateChromeVersion,domId,src);
if (domId && document.querySelector(domId)) {
if(isUpdateChromeVersion) {
document.querySelector(domId).srcObject = src;
console.log('内核升级1',domId, document.querySelector(domId),document.querySelector(domId).srcObject,src);
} else {
console.log('内核升级2');
document.querySelector(domId).src = src;
}
}
defaultApi.writeLog(`setVidoeSrc, streamId:${streamId}, domId: ${domId}, src: ${src}`);
resolve(src);
};
const handleExternalError = (error) => {
if (error.name === 'ConstraintNotSatisfiedError') {
console.error('ConstraintNotSatisfiedError');
} else if (error.name === 'PermissionDeniedError') {
console.error(
'Permissions have not been granted to use your camera and '
+ 'microphone, you need to allow the page access to your devices in '
+ 'order for the demo to work.'
);
}
console.error(`getUserMedia error: ${error.name}`, error);
if (domId) {
document.querySelector(domId).src = '';
}
reject('');
};
if (navigator.webkitGetUserMedia) {
navigator.webkitGetUserMedia(
externalConstraints,
handleExternalSuccess,
handleExternalError
);
}
});
};
/**
* @function 开始推流
* @param streamId: String 流id
* @return Promise | void
*/
const startPush = (streamId ,channel = 0) => {
if(!streamId){
streamId = zbyAVSDK_init_params.trtc.streamId;
}
// 心跳开始
if (!isFirstHeartBeatReport) {
isFirstHeartBeatReport = true;
console.log('ppppppp上报呀')
heartBeatDataReport('start');
}
console.log('startPush',streamId,channel);
return callMethod('StartPush', {streamId, channel});
}
/**
* @function 停止推流
* @param streamId: String 流id
* @return Promise | void
*/
const stopPush = (channel) => {
// if(!streamId){
// streamId = zbyAVSDK_init_params.trtc.streamId;
// }
if(!channel){
channel = 0;
}
return callMethod('StopPush', {channel});
}
/**
* @function 不推/推 音频
* @param enable : bool
* @return Promise | void
*/
const muteLocalAudio = (enable) => {
return callMethod('MuteLocalAudio', {enable});
}
/**
* @function 不推/推 视频
* @param enable: bool
* @return Promise | void
*/
const muteLocalVideo = (enable) => {
return callMethod('MuteLocalVideo', {enable});
}
/**
* @function 开始转推本地摄像头TRTC流至RTMP。目前只支持转推1路
* @return Promise | void
*/
const addPublishRtmpStreamUrl = () => {
return callMethod('AddPublishRtmpStreamUrl', {});
}
/**
* @function 停止转推RTMP
* @return Promise | void
*/
const removePublishStreamUrl = () => {
return callMethod('RemovePublishStreamUrl', {});
}
/**
* @function 开始拉流
* @param streamId: String 流id
* @return Promise | void
*/
const startPlay = (streamId) => {
return callMethod('StartPlay', {streamId});
}
/**
* @function 初始化拉流
* @param streamId:String 从传来的信道消息中获取,必选
* @param domId:String <video> 标签的 id,可选
* 如果传了就把视频绑定到对应的 <video> 标签上
* @param pInfo:String 多媒体流附加信息,可选,默认为 'none'
* @return src:String 视频预览地址
*/
export const initPullFlow = async (streamId, domId, mute, pInfo, notAutoPlay, audioOnly) => {
defaultApi.writeLog(`TRTC:: initPullFlow_start ,streamId :${streamId}`);
let playChannel;
resetStreamIdRtcPlayerInfo1(streamId);
resetStreamIdRtcPlayerInfo(streamId);
try {
if (!isFirstHeartBeatReport) {
isFirstHeartBeatReport = true;
heartBeatDataReport('start');
}
} catch (error) {}
if (streamIdToPreviewId[streamId] == undefined) {
// defaultApi.writeLog(`TRTC:: The streamId queue does not contain this streamId ${uiChnIndexs}`);
playChannel = uiChnIndexs.pop();
streamIdToPreviewId[streamId] = playChannel;
console.log('streamIdIsNoExited',playChannel,streamIdToPreviewId[streamId],streamId,uiChnIndexs);
} else {
defaultApi.writeLog('TRTC:: The streamId queue contains this streamId');
playChannel = streamIdToPreviewId[streamId];
console.log('streamIdIsExited',playChannel,streamIdToPreviewId[streamId],streamId,uiChnIndexs);
await stopPlay(streamId);
resetStreamIdRtcPlayerInfo(streamId);
}
// 判断是否创建或者获取播放通道成功,不成功就删掉重试
// if (playChannel == undefined) {
// delete streamIdToPreviewId[streamId];
// defaultApi.writeLog('error', 'TRTC:: uiChnIndex is not exist');
// // delete streamIdToBlobUrl[streamId];
// return initPullFlow(streamId, domId, mute, pInfo, notAutoPlay, audioOnly);
// }
previewIdToStreamId[playChannel] = streamId;
//是否拉取声音
// await muteRemoteAudio(streamId, !!mute);
// //是否拉取画面
// await muteRemoteVideo(streamId, !!audioOnly);
if (!notAutoPlay) {
await startPlay(streamId);
}
await muteRemoteAudio(streamId, !!mute);
//是否拉取画面
await muteRemoteVideo(streamId, !!audioOnly);
const videoSrc = await startLocalOrRemotePreview(false, streamId, domId);
return {
videoSrc,
playerId: playChannel
};
};
/**
* @function 停止拉流
* @param streamId: String 流id
* @return Promise | void
*/
const stopPlay = (streamId, recovery) => {
const id = streamIdToPreviewId[streamId];
delete streamIdRtcPlayerInfo[streamId];
if (recovery && id && !uiChnIndexs.includes(id)) {
uiChnIndexs.push(id);
defaultApi.writeLog(`avsdk TRTC::stopPlayStream streamId: ${streamId} id: ${id} uiChnIndexs: ${uiChnIndexs}`);
delete streamIdToPreviewId[streamId];
}
return callMethod('StopPlay', {streamId});
}
/**
* @function 停止拉所有的流
* @return Promise | void
*/
const stopPlayAll = () => {
return callMethod('StopPlayAll', {});
}
/**
* @function 不拉/拉 音频 true是静音/false是拉声音
* @param streamId :string
* @param mute : bool
* @return Promise | void
*/
const muteRemoteAudio = (streamId, mute) => {
console.log('audio_type',mute)
streamIdRtcPlayerInfo1[streamId].audio_type = !mute;
console.log('audio_type1', streamIdRtcPlayerInfo1)
return callMethod('MuteRemoteAudio', {streamId, mute});
}
const pullAudioFlow = async (playerId, operation, streamid) => {
defaultApi.writeLog(`pullAudioFlow -- playerId ${playerId} operation ${operation} streamId ${streamid}`);
if(streamid){
if(streamIdToPreviewId[streamid] == undefined) {
NOTICE.pullAudioFlowError({streamid})
return
}else{
playerId = streamIdToPreviewId[streamid]
console.log('pullAudioFlow-playerId',playerId,streamIdToPreviewId)
}
}
let streamId = previewIdToStreamId[playerId];
try {
streamIdRtcPlayerInfo1[streamId].audio_type = !operation;
console.log('pullAudioFlow ::previewIdToStreamId',streamId,previewIdToStreamId)
console.log('pullAudioFlow ::streamIdRtcPlayerInfo1',streamId,streamIdRtcPlayerInfo1);
} catch (e) {
console.log('pullAudioFlow ::streamIdRtcPlayerInfo1--error',e);
}
try {
dataReport.setPullVoice({
code:+!operation,
pull_uid: util.getUidByStreamId(streamId),
pull_streamid:streamId,
playerId
// operator:'client'
});
} catch (e) {};
return await muteRemoteAudio(streamId, operation);
}
/**
* @function 不拉/拉 视频
* @param streamId :string
* @param mute: bool
* @return Promise | void
*/
const muteRemoteVideo = (streamId, mute) => {
try {
streamIdRtcPlayerInfo1[streamId].video_type = !mute;
console.log('activateVideoPlayStream ::streamIdRtcPlayerInfo1',streamIdRtcPlayerInfo1);
} catch (e) {
console.log('activateVideoPlayStream ::streamIdRtcPlayerInfo1 --error',e);
}
return callMethod('MuteRemoteVideo', {streamId, mute});
}
/**
*
* @function 全员开麦突出声音流
* @param bFocus :bool
* @param streamIdarr : array
* @return Promise | void
*/
const setFocusStreams = (bFocus, streamIdarr) => {
return callMethod('SetFocusStreams', {bFocus, streamId1, streamId1, streamId1, streamId1});
}
//加载采集插件的输入数据
export const loadCollectionInputEntry = () => {
return callMethod('LoadCollectionInputEntry', {});
};
//加载截屏插件
const LoadCollectionOutputEntry2 = () => {
defaultApi.writeLog('info', 'avsdk TRTC::LoadCollectionOutputEntry2');
return callMethod('LoadCollectionOutputEntry2', { });
};
//开启同屏
const startMultiScreen = async () => {
defaultApi.writeLog('info', 'avsdk TRTC::startMultiScreen');
// await setVideoCaptureFactory(true,1);
await LoadCollectionOutputEntry2();
};
//高光时刻 enable (bool)/strDomain (string)/strKey (string)
const enableHighlight = async (enable,strDomain = '',strKey = '') => {
defaultApi.writeLog('info', 'avsdk TRTC::enableHighlight');
return callMethod('EnableHighlight', {enable, strDomain, strKey});
};
/**
* @function 获取当前视频流所有的通道
* @param streamId 流 id
* @return channelIndex
*/
export const getAllChannelIndex = () => {
defaultApi.writeLog(`TRTC : getAllChannelIndex ${JSON.stringify(streamIdToPreviewId)}`);
return streamIdToPreviewId;
};
//开始连麦
const teacherStartLinkMic = async (mode) => {
if (mode === 0) {
await startMicrophone();
} else {
//开始连麦后,需要打开麦克风,开启外部采集器后(每次都要开启)
await startMicrophone();
await setEnableExternVideoCapture(true)
}
};
//结束连麦
const teacherStopLinkMic = async (mode = 0) => {
// if (mode === 0) {
// // await muteVideoPublish(false,0);
// } else {
await stopMicrophone();
// }
};
/**
* @function 离开教室
* @return Promise | void
*/
const leaveRoom = async () => {
for (let key in streamIdToPreviewId) {
await stopPlay(key, true);//huishou
}
await stopPush();
removerListener();
await destroyEngine();
heartBeatDataReport('stop');
isFirstHeartBeatReport = false;
streamIdToPreviewId = {};
previewIdToStreamId = {};
streamIdRtcPlayerInfo = {};
streamIdRtcPlayerInfo1 = {};
// window.zegoHasPushFlow = 0;
}
const heartBeatRealKeys = ['video_fps', 'video_bitrate', 'audio_fps', 'audio_bitrate'];
const _heartBeatDataReport = () => {
console.log('上报吧2')
// let cpuRate = 0;
// let memRate = 0;
// let rateCount = 0;
// let appCpuRate = 0;
// let appMemUsed = 0;
// let rateTimer = setInterval(async () => {
// rateCount++;
// let {cpu_rate, mem_rate, gpus, app_cpu_rate, app_mem_used} = (await toolApi.getCurCpuMemInfo()).msg;
// cpu_rate = cpu_rate < 0 ? 0 : cpu_rate;
// cpuRate += parseFloat(cpu_rate);
// memRate += parseFloat(mem_rate);
// if (window.zbyAVSDK_init_params.zego.role === 'student') {
// appCpuRate += parseFloat(app_cpu_rate);
// appMemUsed += parseFloat(app_mem_used);
// }
// if (rateCount >= 3) {
// heartBeatRealKeys.forEach(realKey => {
// if (heartBeatDataReportObj.hasOwnProperty(realKey) && heartBeatDataReportObj.count > 0) {
// heartBeatDataReportObj[realKey] = util.toFixed(heartBeatDataReportObj[realKey]/heartBeatDataReportObj.count);
// }
// });
const pullInfo = [];
console.log('拉流的类型1',streamIdRtcPlayerInfo)
Object.keys(streamIdRtcPlayerInfo).forEach(streamid => {
console.log('拉流的类型1.5')
heartBeatRealKeys.forEach(realKey => {
if (!streamIdRtcPlayerInfo[streamid].hasOwnProperty(realKey)) {
streamIdRtcPlayerInfo[streamid][realKey] = [];
}
// if (streamIdRtcPlayerInfo[streamid].count > 0) {
// streamIdRtcPlayerInfo[streamid][realKey] = util.toFixed(streamIdRtcPlayerInfo[streamid][realKey]/streamIdRtcPlayerInfo[streamid].count);
// }
});
console.log('拉流的类型2',streamIdRtcPlayerInfo1[streamid])
//获取拉流类型,后期可写为函数提出去
if(streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
streamIdRtcPlayerInfo1[streamid].stream_type = 'both';
} else if(!streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
streamIdRtcPlayerInfo1[streamid].stream_type = 'video';
} else if(streamIdRtcPlayerInfo1[streamid].audio_type && !streamIdRtcPlayerInfo1[streamid].video_type) {
streamIdRtcPlayerInfo1[streamid].stream_type = 'audio';
} else {
streamIdRtcPlayerInfo1[streamid].stream_type = 'none';
}
// console.log('hsghsghsg_type_type', streamIdRtcPlayerInfo1[streamid].stream_type);
pullInfo.push({
streamid,
// uid: util.getUidByStreamId(streamid),
...streamIdRtcPlayerInfo[streamid],
pull_type: streamIdRtcPlayerInfo1[streamid].stream_type,
volume: streamIdRtcPlayerInfo[streamid].volume.slice(0,streamIdRtcPlayerInfo[streamid].volume.length-1)
});
resetStreamIdRtcPlayerInfo(streamid);
});
if (isFirstHeartBeatReport) {
try {
//静音推流时过滤掉音频帧率和码率,上报为0;
// if (!isNoticeMicVolumeZego) {
// heartBeatDataReportObj['audio_fps'] = [];
// heartBeatDataReportObj['audio_bitrate'] = [];
// }
//获取推流类型,后期可写为函数提出去
if(zbysdk.deviceStatus.camera && zbysdk.deviceStatus.microphone) {
zbysdk.deviceStatus.stream_type = 'both';
} else if(!zbysdk.deviceStatus.camera && zbysdk.deviceStatus.microphone) {
zbysdk.deviceStatus.stream_type = 'audio';
} else if(zbysdk.deviceStatus.camera && !zbysdk.deviceStatus.microphone) {
zbysdk.deviceStatus.stream_type = 'video';
} else {
zbysdk.deviceStatus.stream_type = 'none';
};
// console.log('push_type222',zbysdk.deviceStatus,zbysdk.deviceStatus.stream_type);
defaultApi.writeLog(`push_type_trtc,camera: ${zbysdk.deviceStatus.camera},microphone: ${zbysdk.deviceStatus.microphone},type: ${zbysdk.deviceStatus.stream_type},a_fps: ${dataTrtcCapture.fps}, a_bit: ${dataTrtcCapture.audioBitrate}, v_fps: ${dataTrtcCapture.fps}, v_bit: ${dataTrtcCapture.videoBitrate}`);
// if (window.zbyAVSDK_init_params.zego.role === 'teacher') {
dataReport.heartbeat({
...{...heartBeatDataReportObj, push_type: zbysdk.deviceStatus.stream_type, volume: heartBeatDataReportObj.volume.slice(0,heartBeatDataReportObj.volume.length-1)},
// pull_info: JSON.stringify(pullInfo),
pull_info: pullInfo,
// cpu_rate: util.toFixed(cpuRate/rateCount),
// mem_rate: util.toFixed(memRate/rateCount),
});
// } else {
// dataReport.heartbeat({
// ...heartBeatDataReportObj,
// pull_info: JSON.stringify(pullInfo),
// cpu_rate: util.toFixed(cpuRate/rateCount),
// mem_rate: util.toFixed(memRate/rateCount),
// app_cpu: util.toFixed(appCpuRate/rateCount),
// app_mem: util.toFixed(appMemUsed/rateCount),
// video_mem: gpus
// });
// }
} catch (e) {
console.log(e);
}
}
resetHeartBeatDataReportObj();
// cpuRate = 0;
// memRate = 0;
// appCpuRate = 0;
// appMemUsed = 0;
// clearInterval(rateTimer);
// }
// }, 10 * 1000);
};
const heartBeatDataReport = (type) => {
try {
if (type === 'start' && !heartBeatDataReportTimer) {
_heartBeatDataReport();
heartBeatDataReportTimer = setInterval(() => {
_heartBeatDataReport();
}, 30 * 1000);
}
if (type === 'stop') {
clearInterval(heartBeatDataReportTimer);
heartBeatDataReportTimer = null;
}
} catch (error) {
console.log(error);
}
};
const heartBeatDataReportCalc = (name, _data) => {
console.log('hsgmzk111',name,_data);
let _d = JSON.parse(_data.json);
console.log('hsgmzk222',name,_d);
// 拉流
const pullKeys = ['fps', 'videoBitrate', 'afps', 'audioBitrate'];
if (name === 'onRemoteStatistics') {
console.log('hsgmzk222',streamIdRtcPlayerInfo,_d.streamId)
if (streamIdRtcPlayerInfo && streamIdRtcPlayerInfo.hasOwnProperty(_d.streamId)) {
console.log('hsgmzk22211');
let streamid = _d.streamId;
let isReport = true;
// streamIdRtcPlayerInfo[streamid].count++;
heartBeatRealKeys.forEach((realKey, index) => {
if (_d.hasOwnProperty(pullKeys[index])) {
if (streamIdRtcPlayerInfo[streamid][realKey] === undefined) {
streamIdRtcPlayerInfo[streamid][realKey] = [];
isReport = false;
}
// streamIdRtcPlayerInfo[streamid][realKey].push(parseFloat(parseInt(item[pullKeys[index]])));
}
});
console.log('hsgmzk333',_d)
if (isReport) {
let audio_fps_trtc_pull = 0;
let audio_bitrate_trtc_pull = 0;
let video_fps_trtc_pull = 0;
let video_bitrate_trtc_pull = 0;
console.log('hsgmzk444',_d)
if(streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
console.log('hsgmzk555',_d)
audio_fps_trtc_pull = parseFloat(parseInt(_d.afps));
audio_bitrate_trtc_pull = parseFloat(parseInt(_d.audioBitrate));
video_fps_trtc_pull = parseFloat(parseInt(_d.fps));
video_bitrate_trtc_pull = parseFloat(parseInt(_d.videoBitrate));
} else if(!streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
video_fps_trtc_pull = parseFloat(parseInt(_d.fps));
video_bitrate_trtc_pull = parseFloat(parseInt(_d.videoBitrate));
} else if(streamIdRtcPlayerInfo1[streamid].audio_type && !streamIdRtcPlayerInfo1[streamid].video_type) {
audio_fps_trtc_pull = parseFloat(parseInt(_d.afps));
audio_bitrate_trtc_pull = parseFloat(parseInt(_d.audioBitrate));
}
streamIdRtcPlayerInfo[streamid].audio_fps.push(audio_fps_trtc_pull);
streamIdRtcPlayerInfo[streamid].audio_bitrate.push(audio_bitrate_trtc_pull);
streamIdRtcPlayerInfo[streamid].video_fps.push(video_fps_trtc_pull);
streamIdRtcPlayerInfo[streamid].video_bitrate.push(video_bitrate_trtc_pull);
streamIdRtcPlayerInfo[streamid].pull_loss.push(_d.packetLoss);
streamIdRtcPlayerInfo[streamid].pull_delay.push(_d.rtt);
streamIdRtcPlayerInfo[streamid].ctime.push(Math.round((new Date().getTime()+dataReport.timestamp)/1000));
streamIdRtcPlayerInfo[streamid].video_ifg += _d.videoBlockRate;
streamIdRtcPlayerInfo[streamid].audio_ifg += _d.audioBlockRate;
// console.log('hsg_tpull_keys',JSON.parse(JSON.stringify(streamIdRtcPlayerInfo[streamid])),_d.avTimestampDiff);
}
}
}
// 推流
const pushKeys = ['fps', 'videoBitrate', 'afps', 'audioBitrate'];
if (name === 'onLocalStatistics') {
// console.log('hsgmzk',_d);
// heartBeatDataReportObj.count++;
// heartBeatRealKeys.forEach((realKey, index) => {
// if (heartBeatDataReportObj.hasOwnProperty(realKey) && _d.hasOwnProperty(pushKeys[index])) {
// heartBeatDataReportObj[realKey].push(parseFloat(parseInt(_d[pushKeys[index]])));
// }
// });
let audio_fps_trtc_push = 0;
let audio_bitrate_trtc_push = 0;
let video_fps_trtc_push = 0;
let video_bitrate_trtc_push = 0;
dataTrtcCapture =_d;
if(zbysdk.deviceStatus.camera && zbysdk.deviceStatus.microphone) {
audio_fps_trtc_push = parseFloat(parseInt(_d.afps));
audio_bitrate_trtc_push = parseFloat(parseInt(_d.audioBitrate));
video_fps_trtc_push = parseFloat(parseInt(_d.fps));
video_bitrate_trtc_push= parseFloat(parseInt(_d.videoBitrate));
} else if(!zbysdk.deviceStatus.camera && zbysdk.deviceStatus.microphone) {
audio_fps_trtc_push = parseFloat(parseInt(_d.afps));
audio_bitrate_trtc_push = parseFloat(parseInt(_d.audioBitrate));
} else if(zbysdk.deviceStatus.camera && !zbysdk.deviceStatus.microphone) {
video_fps_trtc_push = parseFloat(parseInt(_d.fps));
video_bitrate_trtc_push = parseFloat(parseInt(_d.videoBitrate));
}
// console.log('hsg6666666',audio_fps_trtc_push,audio_bitrate_trtc_push,video_fps_trtc_push,video_bitrate_trtc_push);
heartBeatDataReportObj.audio_fps.push(audio_fps_trtc_push);
heartBeatDataReportObj.audio_bitrate.push(audio_bitrate_trtc_push);
heartBeatDataReportObj.video_fps.push(video_fps_trtc_push);
heartBeatDataReportObj.video_bitrate.push(video_bitrate_trtc_push);
heartBeatDataReportObj.push_loss.push(_d.packetLoss);
heartBeatDataReportObj.push_delay.push(_d.rtt);
heartBeatDataReportObj.ctime.push(Math.round((new Date().getTime()+dataReport.timestamp)/1000));
// console.log('hsg_td5',JSON.parse(JSON.stringify(heartBeatDataReportObj)));
}
};
//推流字段
const resetHeartBeatDataReportObj = () => {
// console.log('hsg_td55556重置');
heartBeatDataReportObj = {
ctime: [],
push_type: 'none',
video_fps: [],
video_bitrate: [],
audio_fps: [],
audio_bitrate: [],
push_loss: [],
push_delay: [],
volume: ''
};
};
//记录拉流类型,用作数据上报
const resetStreamIdRtcPlayerInfo1 = (streamId) => {
streamIdRtcPlayerInfo1[streamId] = {
audio_type: false,
video_type: false,
stream_type: 'none'
};
// console.log('hsgshgs_heartbeat',streamIdRtcPlayerInfo1);
};
resetHeartBeatDataReportObj();
//拉
const resetStreamIdRtcPlayerInfo = (streamId) => {
streamIdRtcPlayerInfo[streamId] = {
pull_uid: util.getUidByStreamId(streamId),
streamid: streamId,
ctime: [],
pull_type: streamIdRtcPlayerInfo1[streamId].stream_type,
volume: '',
video_fps: [],
video_bitrate: [],
audio_fps: [],
audio_bitrate: [],
pull_loss: [],
pull_delay: [],
//音画不同步字段
avtimestampdiff:[],
// 累加
audio_ifg: 0,
video_ifg: 0
};
};
export default {
init,
setCameraCaptureResolution,
setCameraEncodeResolution,
setCameraEncodeFps,
setCameraEncodeBiarate,
getCameraResolution,
getMicrophoneDeviceListTrtc,
setMicrophoneDevice,
openOrCloseMicrophone,
getCurrentMicrophoneVolume,
setCurrentMicrophoneVolume,
setCurrentCameraDevice,
getCameraDeviceListTrtc,
setVideoDevice,
openOrCloseCamera,
getSpeakerDeviceListTrtc,
setSpeakerDevice,
getCurrentSpeakerVolume,
setCurrentSpeakerVolume,
setAudioSpeakerCapture,
startLocalOrRemotePreview,
startPush,
stopPush,
startPlay,
stopPlay,
initPullFlow,
pullAudioFlow,
muteRemoteVideo,
muteRemoteAudio,
stopPlayAll,
sendSEIMsg,
startMultiScreen,
enableHighlight,
getAllChannelIndex,
leaveRoom,
teacherStartLinkMic,
teacherStopLinkMic
}