UNPKG

zby-live-sdk

Version:

This is a live SDK for weclassroom.

1,472 lines (1,355 loc) 70.8 kB
import zbyAVSDK from './zby-av-sdk/zby-av-sdk'; import globalConfig, { version, config, // getLogAddress, getApiCloudBaseUrl, pomeloBackupDomains, } from './config/config'; import util from './util/util'; import dict from './util/dict'; import { setBackgroundStatus } from './util/statsStore'; import CHANNEL from './channel'; import dataReport from './network/dataReport'; import { getAndSetInitParams, getCloudData, changeSdkInRoom } from './network/api'; import toolBaseApi from './tool/base'; import liveBaseApi from './live/base'; import defaultApi from './default'; import {getDevicePermissionsFun, setMediaPermissionFun, isAppleM1, isWinX64} from './zby-av-sdk/device'; import NOTICE from './notice'; import { userAndDeviceStatusInfo } from './util/statsStore'; // window.zegoHasPushFlow = 0 defaultApi.writeLog(`sdk action: zby-live-sdk loaded, version: ${version}`); let useScreenExtendKeys = false; let isWinX64Flag = false; let sdkConfig = config; let sdk_status = -1; let sdkRetryCount = 0; let deviceCheckerInitStatus = -1; const windowObjArr = [['zby_sdk_req_get_cloud_params', 'zbyAVSDK_init_params', 'zbyAVSDK_device_checker_init', 'zby_sdk_cloud_data'], ['zbyAVSDK_init_sdk_type', 'current_sdk_type']]; let confId; let sdkTypeGroup = ''; // 'tm' / 'zego' const recordPathMap = {}; let mirrorStatus = null; // 重试初始化 function retryInit(error, name = 'init', args, dealSDKMsg) { //通知业务层,初始化失败,重试 sdkRetryCount++; sdk_status = -1; if (sdkRetryCount > 3) { sdkRetryCount = 0; NOTICE.sdkStatus({ status: 'retry_stop' }); try { // console.log('获取云控失败上报加入教室code1',window.zby_sdk_init_params); dataReport.joinRoomResult({ code: '1', // cloud_api_response: JSON.stringify(window.zby_sdk_cloud_data), // cloud_api_response: window.zby_sdk_cloud_data, cloud_api_url: `${getApiCloudBaseUrl()}/rtccloud/class/init` }); } catch(e) { defaultApi.writeLog('获取云控接口失败'); } } else { NOTICE.sdkStatus({ status: `retry_${name}`, count: sdkRetryCount }); defaultApi.writeLog(`sdk action: retry_${name}, count: it's the 【${sdkRetryCount}】 retry, ${error} error`); if (name === 'init') { return zbysdk.init(args, dealSDKMsg); } return zbysdk.changeSDK(1); } } /** * 设备状态通知 * @param {String} deviceType 'audio', 'video' * @param {Bollean} operation */ function sendDeviceStatus(deviceType, operation) { if (window.zbyAVSDK_init_params) { const initParams = window.zby_sdk_init_params; NOTICE.deviceStatus({ userId: initParams.userId, userName: initParams.userName, role: initParams.role, //获取设备类型和状态对应的文案,返回给业务层 deviceType: deviceType, deviceStatus: operation ? 'open' : 'closed' }); //更新设备状态,摄像头,麦克风 开启/关闭 CHANNEL.sendUpdateStreamDeviceStatus(Object.assign({}, initParams, { deviceType: dict.getDeviceTypeKey(deviceType), deviceStatus: dict.getDeviceStatusKey(operation ? 'open' : 'closed') })); } else { console.log('尚未初始化,无须设备状态同步'); } } /** * * @param {String} userId * @param {String} status 流状态 */ function noticeStreamStatus(userId, status) { NOTICE.streamStatus({ userId, status }); defaultApi.writeLog(`sdk stream status userId: ${JSON.stringify(userId)} ${status}`); } function generateStreamId(userId, groupId) { if (!window.zby_sdk_init_params) { console.log('缺少初始化参数,无法生成streamId'); } const initParams = window.zby_sdk_init_params; if (!initParams) { return ''; } return util.getStreamId({ ...initParams, userId, groupId }); } function caculateDeatailArgs(baseArgs, cloudData, sdkTypeGroup) { try { const commonArgs = { userId: baseArgs.userId + '', streamId: util.getStreamId(baseArgs), userName: baseArgs.userName || '', sid: baseArgs.sid, role: baseArgs.role, roomId: baseArgs.roomId + '', confId: confId, userAvatar: baseArgs.userAvatar || '', userToken: baseArgs.userToken || '', devices: baseArgs.devices, env: baseArgs.env, businessLinesType: baseArgs.businessLinesType, institutionId: baseArgs.institutionId, //站立模式:0 / 坐立模式:1 mode: baseArgs.mode, live_id: baseArgs.liveId, // 课堂模式,0=小组课/1=新小班 classMode: +baseArgs.classMode, //数据上报班课类型 liveType: +baseArgs.liveType, //是否开启转推功能 isTurnPush: baseArgs.isTurnPush || false, // isSetAEC: baseArgs.isSetAEC || false, lecturerStreamId: baseArgs.lecturerStreamId, }; const screenSameResolutionKey = useScreenExtendKeys ? 'screenSameResolutionExtend' : 'screenSameResolution'; const screenSameFpsKey = useScreenExtendKeys ? 'screenSameFpsExtend' : 'screenSameFps'; const screenSameBitrateKey = useScreenExtendKeys ? 'screenSameBitrateExtend' : 'screenSameBitrate'; //从云控返回值中获取直播相关配置 const liveConfig = { //大画面视频采集码率(取值范围:40kb~2000kb) // captureBitrate: +cloudData.captureBitrate, //大画面视频采集帧率(取值范围:5~30) // captureFps: +cloudData.captureFps, //大画面视频编码分辨率 encodedResolutionWidth: +cloudData.encodedResolution.split('*')[0], encodedResolutionHeight: +cloudData.encodedResolution.split('*')[1], // 预览画面视频采集码率(取值范围:40kb~300kb) encodeCaptureBitrate: +cloudData.encodedBitrate, encodeCaptureFps: +cloudData.encodedFps, // 预览画面视频采集帧率(取值范围:5~15) previewCaptureFps: +cloudData.previewFps, // 预览视频编码分辨率 previewResolutionWidth: +cloudData.previewResolution.split('*')[0], previewResolutionHeight: +cloudData.previewResolution.split('*')[1], //rtc同屏分辨率 screenSameResolutionWidth: cloudData[screenSameResolutionKey] ? +cloudData[screenSameResolutionKey].split('*')[0] : 1280, screenSameResolutionHeight: cloudData[screenSameResolutionKey] ? +cloudData[screenSameResolutionKey].split('*')[1] : 720, //rtc同屏帧率 码率 screenSameFps: cloudData[screenSameFpsKey] ? +cloudData[screenSameFpsKey] : 15, screenSameBitrate: cloudData[screenSameBitrateKey] ? +cloudData[screenSameBitrateKey] : 512000, // 转推Rtmp地址 recordUrl: cloudData.recordUrl, aecMode: cloudData.aecMode != null ? cloudData.aecMode : -1, noiseSuppressMode: cloudData.noiseSuppressMode != null ? cloudData.noiseSuppressMode : -1 }; const detailArgs = { rtc: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.rtc, appId: cloudData.appId, sdkTypeGroup }), talrtc: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.talrtc || '1.0.0.0', appId: cloudData.appId, usersign: 'testsign', teacherId: baseArgs.teacherId, sdkTypeGroup }), nertc: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.talrtc || '1.0.0.0', appId: cloudData.appId, usersign: 'testsign', teacherId: baseArgs.teacherId, sdkTypeGroup }), volcrtc: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.talrtc || '1.0.0.0', appId: cloudData.appId, usersign: 'testsign', teacherId: baseArgs.teacherId, sdkTypeGroup }), trtc: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.trtc || '1.0.0.0', appId: cloudData.appId, usersign: cloudData.txRtcKey, sdkTypeGroup }), zego: Object.assign({}, commonArgs, liveConfig, { extensionVersion: baseArgs.extension.version.zego, appId: parseInt(cloudData.appId)|| 2251703116, appSignature: cloudData.appKey|| 'uYsmfJ4F8ERzRNC4ug6lWB/vfU6ffg+/ETRF14vjzs4=', businessType: 0, nNetType: 1, sdkTypeGroup }) }; return detailArgs; } catch (error) { console.error(error); } } /** * SDK 方法 */ const zbysdk = { version: version, notice: null, // 打开监听log openListenerLog: false, //端上初始化时传的false autoChangeSdk: true, log_id:null, /** * 配置设置 * @param {Object} options * @param {'test' | 'online'} options.env 环境 * @param {boolean} options.weblog 是否开启日志 * @param {'saas' | 'xes'} options.businessLinesType 业务线类型 saas:乐读 xes:素养 */ setConfig(options) { Object.assign(sdkConfig, options); Object.assign(this, options); }, /** * 设置备用域名 * @param {{ host: string, port: number }[]} domains */ setBackupDomains(domains) { defaultApi.writeLog(`sdk action: setBackupDomains ${JSON.stringify(domains)}`); pomeloBackupDomains.length = 0; if (Array.isArray(domains)) { domains.forEach(({host, port = 443}) => { pomeloBackupDomains.push({ host, port }); }); } }, deviceStatus: {}, enableLog(enable = true) { defaultApi.writeLog(`sdk action: enableLog ${JSON.stringify(enable)}`); config.weblog = !!enable; }, /** * 打开美颜,默认不用调用,sdk内部会自动打开 */ enableBeauty(streamId, idx) { defaultApi.writeLog(`sdk action: enableBeauty, streamId: ${streamId}, idx: ${idx}`); return zbyAVSDK.enableBeautify(true, streamId, idx); }, /** * 关闭美颜 */ disableBeauty(streamId, idx) { defaultApi.writeLog(`sdk action: disableBeauty, streamId: ${streamId}, idx: ${idx}`); return zbyAVSDK.enableBeautify(false, streamId, idx); }, /** * 设置美颜参数 * @param {Object} options * @param {number} options.whiten 美白 0-1 * @param {number} options.dermabrasion 磨皮0-1 * @param {number} options.lift 窄脸0-1 * @param {number} options.shave 削脸0-1 * @param {number} options.eye 大眼0-1 * @param {number} options.chin 下巴0-1 * @param {number} options.darkCircle 黑眼圈0-1 * @param {number} options.nasolabialFolds 法令纹0-1 * @param {number} options.cheekbone 颧骨0-1 * @param {number} options.head 小头0-1 * @param {number} options.eyeBrightness 亮眼0-1 * @param {number} options.lip 嘴唇 -1 - 1 * @param {number} options.forehead 发际线 0-1 * @param {number} options.nose 鼻子 -1 - 1 * @param {number} options.usm 清晰 0-1 * @param {string?} streamId 流id * @param {number?} idx 流索引 */ setBeautify(options, streamId, idx) { defaultApi.writeLog(`sdk action: setBeautify ${JSON.stringify(options)}, streamId: ${streamId}, idx: ${idx}`); const result = []; for (let key in options) { if (typeof options[key] !== 'number' || options[key] < 0 || options[key] > 1) { defaultApi.writeLog(`sdk action: setBeautify options.${key} value should be between 0 and 1`); continue; } let mode, subMode = 0, value = Math.round(options[key] * 100); switch (key) { case 'whiten': mode = 101; break; case 'dermabrasion': mode = 103; subMode = 1; break; case 'lift': mode = 201; break; case 'eye': mode = 202; break; case 'usm': mode = 603; break; default: defaultApi.writeLog(`sdk action: setBeautify options.${key} not support yet`); break; } if (!mode) { continue; } result.push(zbyAVSDK.setBeautifyParam2(mode, subMode, value, streamId, idx)); } return Promise.all(result); }, /** * 设置背景 * @param {Object} options * @param {'image' | 'blur' | 'transparent'} options.type 背景类型 * @param {string?} options.path 图片地址 * @param {string?} streamId 流id * @param {number?} idx 流索引 */ setBackground(options, streamId, idx) { defaultApi.writeLog(`sdk action: setBackground ${JSON.stringify(options)}, streamId: ${streamId}, idx: ${idx}`); if (!options || !options.type) { const res1 = zbyAVSDK.setBeautifyParam2(605, 1, 0, streamId, idx); // 关闭背景虚化 const res2 = zbyAVSDK.setBeautifyParam2(901, 0, 0, streamId, idx); // 关闭自定义背景 return Promise.all([res1, res2]); } if (options.type === 'blur') { return zbyAVSDK.setBeautifyParam2(605, 1, 100, streamId, idx, options.path); } if (options.type === 'image') { return zbyAVSDK.setBeautifyParam2(901, 0, 100, streamId, idx, options.path); } return Promise.resolve(); }, async deviceCheckerInit(cb, extension, env = 'test') { if (!extension) { defaultApi.writeLog('sdk deviceCheckerInit extension param is required'); } if (deviceCheckerInitStatus > -1) { return 'please stop check device first'; } deviceCheckerInitStatus = 0; defaultApi.writeLog(`sdk action: deviceCheckerInit ${JSON.stringify({ cb, extension, env, sdk_version: version })}`); if (typeof cb === 'function') { zbysdk.notice = cb; } await zbyAVSDK.deviceCheckerInit(extension, env); deviceCheckerInitStatus = 1; defaultApi.writeLog('sdk devices checked'); }, // 结束设备检测 stopCheckDevice() { if (deviceCheckerInitStatus === -1) { defaultApi.writeLog('please start check device first'); return 'please start check device first'; } deviceCheckerInitStatus = -1; defaultApi.writeLog('sdk stop check device'); return zbyAVSDK.stopCheckDevice(); }, /** * * @param {Object} args * @param {string} args.institutionId 机构id * @param {string} args.roomId 房间id * @param {string} args.userId 用户id * @param {string} args.role 用户角色 * @param {string} args.teacherId 辅导流id * @param {Object} args.cloudData 云控数据 * @param {string} args.liveId * @param {string} args.sid streamId * @param {string} args.userName * @param {string} args.userAvatar * @param {string} args.userToken * @param {Object} args.devices 设备信息 * @param {'test' | 'online'} args.env 环境 * @param {'saas' | 'xes'} args.businessLinesType 业务线类型 * @param {number} args.mode 站立模式:0 / 坐立模式:1 * @param {number} args.classMode 课堂模式,0=小组课/1=新小班 * @param {string} args.liveType 数据上报班课类型 * @param {string} args.isTurnPush 是否开启转推功能 * @param {string} args.lecturerStreamId 主讲流id,学生端专用字段 * @param {Function} dealSDKMsg * @returns */ async init(args, dealSDKMsg) { if (sdk_status !== -1) { console.log('not allow init'); dealSDKMsg({ type: 'error', data: { message: 'should not start init before init finished' } }); return; } defaultApi.writeLog(`sdk action: init zby_live_sdk_version : ${version}`); isWinX64Flag = await isWinX64(); useScreenExtendKeys = !!args.useScreenExtendKeys; defaultApi.writeLog(`sdk action: init args : ${JSON.stringify(args)}, ${isWinX64Flag ? 'winx64' : ''}`); try { let argsCopy = JSON.parse(JSON.stringify(args)); delete argsCopy.cloudData; defaultApi.writeLog(`sdk action: init_argsCopy_args : ${JSON.stringify(argsCopy)}`); } catch (e) {}; this.log_id = 0; sdk_status = 0; // 初始化参数存入共享 window.zby_sdk_init_params = args; // 设置confId confId = util.getConfId(args.institutionId, args.roomId); defaultApi.writeLog('sdk action: init load live sdk - start'); await liveBaseApi.init(); defaultApi.writeLog('sdk action: init load live sdk - end'); try { toolBaseApi.init(); } catch(e) { defaultApi.writeLog(`toolBaseApi_Init error: ${e}`, null, 'error'); } // try { // await util.getNetworkTimeStamp(); // } catch(e) { // console.log('getTimeError',e); // }; //使用初始化传入的 env, isHttps 参数 Object.assign(sdkConfig, args); zbysdk.notice = dealSDKMsg; try { const useZego = (args.role === 'assistant' || isWinX64Flag); // TODO 辅导端RTMP流不支持云控,默认用zego sdkTypeGroup = useZego ? 'zego' : await getAndSetInitParams({ institutionId: args.institutionId, userId: args.userId, liveId: args.liveId, role: args.role }); defaultApi.writeLog(`云控返回的当前大班的sdk类型, ${sdkTypeGroup}`); } catch (error) { defaultApi.writeLog(`获取大班云控初始化参数里面的sdk类型失败${error}`); } const reqParam = { clientType: 'pc', roomType: 7, institutionId: args.institutionId + '', roomId: args.roomId + '', userType: args.role === 'assistant' ? 'student' : args.role, userId: args.userId + '', teacherId: args.teacherId + '' }; window.zby_sdk_req_get_cloud_params = reqParam; let cloudData; if (args.cloudData && args.cloudData.sdkName && args.cloudData.encodedResolution && args.cloudData.previewResolution) { cloudData = args.cloudData; } else { defaultApi.writeLog(`sdk_init: getCloudData reqParam : ${JSON.stringify(reqParam)}`); let cloudResponse; try { cloudResponse = await getCloudData(reqParam); } catch (error) { return retryInit('getCloudData', 'init', args, dealSDKMsg); } defaultApi.writeLog(`sdk_init: cloudResponse : ${JSON.stringify(cloudResponse)}`); if (cloudResponse.code === 0 && cloudResponse.data) { cloudData = cloudResponse.data; } else { defaultApi.writeLog(`sdk_init: get cloudResponse error: ${JSON.stringify(cloudResponse)}`); return false; } } defaultApi.writeLog(`sdk_init: cloudData : ${JSON.stringify(cloudData)}`); window.zby_sdk_cloud_data = cloudData; const detailArgs = caculateDeatailArgs(args, cloudData, sdkTypeGroup); let sdk_type = cloudData.sdkName; // let sdk_type = 'zego'; Object.assign(window.zby_sdk_init_params, cloudData); //通知业务层,初始化完成 NOTICE.sdkStatus({ sdk_type, status: 'before_init' }); defaultApi.writeLog(`sdk status : before_init , sdk_type : ${sdk_type}`); await zbyAVSDK.init(sdk_type, detailArgs).catch(error => { defaultApi.writeLog(`sdk init AVSDK init_failed ${JSON.stringify(error)}`); return; }); defaultApi.writeLog(`sdk status : setAudioCallbackType , sdk_type : ${sdk_type}`); try { // 设置rtmp流的音频采集方式 if (sdkTypeGroup == 'tm') { // tm推RTMP流 await liveBaseApi.setAudioCallbackType(sdk_type); } else { if (sdkConfig.classMode === 0) { defaultApi.writeLog('zego小组课不需要在zby_live_sdk设置声音采集模式'); } else if (args.role === 'assistant') { defaultApi.writeLog('辅导端zego推RTMP流, 不需要在zby_live_sdk设置声音采集模式'); } else { // zego推rtmp流 await zbyAVSDK.setThirdAudioCallbackType(sdk_type); } } } catch (e) { defaultApi.writeLog(`sdk status : setAudioCallbackType , error : ${JSON.stringify(e)}`); }; try { // dataReport.joinRoom({initParams: JSON.stringify(args)}); dataReport.joinRoom({initParams: args}); } catch (e) {}; defaultApi.writeLog(`sdk status : init_finished , sdk_type : ${sdk_type}`); //通知业务层,初始化完成 NOTICE.sdkStatus({ sdk_type, status: 'init_finished' }); try { window.zby_isM1Type =(await isAppleM1()).data.is_Apple_Silicon; } catch (error) { defaultApi.writeLog(`sdk action : isAppleM1 error ${JSON.stringify(error)}`); } try{ dataReport.initFinished({code:0}); }catch (e){ } sdk_status = 1; sdkRetryCount = 0; // 缓存初始化信息 windowObjArr[0].forEach(item => { if (window[item] !== undefined) { localStorage.setItem(item, JSON.stringify(window[item])); } }); windowObjArr[1].forEach(item => { if (window[item] !== undefined) { localStorage.setItem(item, window[item]); } }); //进入信道房间 // enterChannelRoom({...args, chatUrl: cloudData.chatUrl}, dealSDKMsg); // sendInitChannelMsg(args); CHANNEL.joinRoom({...args, chatUrl: cloudData.chatUrl, guid: window.zby_sdk_init_params.guid}, dealSDKMsg, cloudData.chatType); }, // 设置新窗口配置 setNewWindowConfig(args) { defaultApi.writeLog(`sdk action : setNewWindowConfig , args : ${JSON.stringify(args)}`); window.zbyAVSDK_init_sdk_type = args.sdkType; }, // 恢复sdk async recoverSdk(args, dealSDKMsg) { defaultApi.writeLog(`sdk action : recoverSdk , args : ${JSON.stringify(args)}`); // 恢复全局变量 windowObjArr[0].forEach(item => { const obj = localStorage.getItem(item); if (obj && obj.indexOf('{') > -1) { try { window[item] = JSON.parse(obj); } catch (error) { } } }); let cloudData; if (args.cloudData) { cloudData = args.cloudData; } else { try { cloudData = JSON.parse(localStorage.getItem('zby_sdk_cloud_data')); } catch (error) { } } windowObjArr[1].forEach(item => { window[item] = localStorage.getItem(item); }); window.zby_sdk_init_params = args; defaultApi.writeLog('sdk action : recoverSdk , set window params finished'); // try { // await getLogAddress(); // await getAndSetInitParams({institutionId: args.institutionId, userId: args.userId}); // } catch (error) { // return retryInit('getAndSetInitParams', 'init', args, dealSDKMsg); // } //使用初始化传入的 env, isHttps 参数 Object.assign(sdkConfig, args); zbysdk.notice = dealSDKMsg; const detailArgs = caculateDeatailArgs(args, cloudData, sdkTypeGroup); await zbyAVSDK.recoverSdk(detailArgs); sdk_status = 1; //通知业务层,初始化完成 NOTICE.sdkStatus({ sdk_type: window.zbyAVSDK_init_sdk_type, status: 'init_finished' }); defaultApi.writeLog('sdk action : recoverSdk finished'); //进入信道房间 // enterChannelRoom({...args, chatUrl: cloudData.chatUrl}, dealSDKMsg); // sendInitChannelMsg(args); CHANNEL.joinRoom({...args, chatUrl: cloudData.chatUrl}, dealSDKMsg, cloudData.chatType); }, // 接收到信道消息,进行切换SDK操作 // from 0:云控 1:重试 2: 上层调用 async changeSDK(from = 0) { if (!window.zby_sdk_init_params || !window.zby_sdk_req_get_cloud_params) { console.log('缺少初始化参数,无法切换SDK'); return; } //重试(2)不走下一步,否则会陷入死循环,如果是reJoin(1)来的,自动走切sdk逻辑,不触发start_sdk_change回调直接切 if (from < 1) { // 通知业务层,切换之前(授课业务逻辑需要,比如老师主动调切sdk,云控走的切sdk全部由老师主动切,修复连麦崩溃) NOTICE.sdkStatus({ sdk_type: window.zbyAVSDK_init_sdk_type, status: 'start_sdk_change' }); } defaultApi.writeLog('sdk status : start_sdk_change'); if (from === 0 && !this.autoChangeSdk) { return; } const initParams = window.zby_sdk_init_params; let nowSdk = window.zbyAVSDK_init_sdk_type; let cloudData; //请求云控获取更新后的SDK配置相关信息 let cloudResponse; try { cloudResponse = await getCloudData(window.zby_sdk_req_get_cloud_params); } catch (error) { defaultApi.writeLog(`changeSDK: getCloudData error ${JSON.stringify(error)}`); return retryInit('getCloudData', 'changeSDK'); }; cloudData = cloudResponse.data; if (cloudData) { const changeSDKParam = caculateDeatailArgs(initParams, cloudData, sdkTypeGroup); const sdk_type = cloudData.sdkName; window.zbyAVSDK_init_params = changeSDKParam; if (window.zbyAVSDK_init_sdk_type === sdk_type && sdk_type !== 'talrtc') { console.log('%cchangeSDK :和本地SDK一致,不切换:' + sdk_type, 'color:blue'); defaultApi.writeLog(`sdk: change sdk action , target is the same as local , will not change sdk to ${sdk_type}`); window.target_sdk_type = null; return; } else { window.target_sdk_type = sdk_type; defaultApi.writeLog(`sdk action: changeSDK to sdk_type : ${sdk_type}, sdk status : start_change `); } // 通知业务层,切换之前 NOTICE.sdkStatus({ sdk_type: window.zbyAVSDK_init_sdk_type, target_sdk_type: sdk_type, status: 'before_sdk_change' }); defaultApi.writeLog(`sdk status : before_sdk_change to sdk_type : ${sdk_type}`); // try { // dataReport.sdkChange({ // from: window.zbyAVSDK_init_sdk_type, // to: sdk_type // }); // } catch (e){}; // //切换SDK之前,先停止转推 if(window.zbyAVSDK_init_params[sdk_type].isTurnPush) { zbyAVSDK.turnPush('stop'); }; sdk_status = 0; console.log('%c执行SDK切换' + sdk_type, 'color:blue'); try { CHANNEL.sendRemoveStream(window.zby_sdk_init_params); CHANNEL.sendLeave(window.zby_sdk_init_params); await zbyAVSDK.changeSDK({ sdk_type }); } catch (error) { defaultApi.writeLog(`changeSDK error : ${JSON.stringify(error)}`); window.target_sdk_type = null; } if (mirrorStatus !== null) { // 如果之前有镜像,切sdk之后,重新设置镜像 await zbyAVSDK.setMirrorStatus(mirrorStatus); } try { console.log('开始设置rtmp声音回调',sdk_type); // 设置rtmp流的音频采集方式 if (sdkTypeGroup == 'tm') { // tm推RTMP流 await liveBaseApi.setAudioCallbackType(sdk_type); } else { if (sdkConfig.classMode === 0) { defaultApi.writeLog('zego小组课不需要在zby_live_sdk设置声音采集模式'); } else if (initParams.role === 'assistant') { defaultApi.writeLog('辅导端zego推RTMP流, 不需要在zby_live_sdk设置声音采集模式'); } else { // zego推rtmp流 await zbyAVSDK.setThirdAudioCallbackType(sdk_type); } } } catch (error) { defaultApi.writeLog(`setAudioCallbackType error : ${JSON.stringify(error)}`); } try { dataReport.sdkChange({ from: nowSdk, to: sdk_type }); } catch (e){}; console.log('%cSDK切换完毕' + sdk_type, 'color:blue'); sdkRetryCount = 0; sdk_status = 1; window.target_sdk_type = null; // 通知业务层,切换完成 NOTICE.sdkStatus({ sdk_type, status: 'sdk_changed' }); defaultApi.writeLog(`sdk status : sdk_changed , sdk_type : ${sdk_type}`); if (globalConfig.usePomelo) { // 如果切换SDK之后,usePomelo为true,重新进入信道 CHANNEL.joinRoom({...initParams, chatUrl: cloudData.chatUrl}, zbysdk.notice, cloudData.chatType); } else { CHANNEL.leaveRoom(); } //切换SDK 完成后,先发送 join消息 CHANNEL.sendJoin(initParams); // 打开本地摄像头, 并开始推流后, 老师视频和麦克风状态变为'开启', 即true //切换完成之后,学生重新推流 // if (window.zby_sdk_init_params.role === 'student') { console.log('%c执行打开摄像头和推流:' + sdk_type, 'color:blue'); if (sdkTypeGroup == 'zego' && (initParams.role == 'assistant' || (sdkConfig.classMode === 0 && initParams.role == 'teacher'))) { defaultApi.writeLog('zego小组课云控切rtc流sdk,不重新设置摄像头麦克风打开状态(设备状态在pyzx设置的,zby拿不到状态)'); } else { if (typeof userAndDeviceStatusInfo.camera === 'boolean') { await zbysdk.openOrCloseCamera(userAndDeviceStatusInfo.camera); } if (typeof userAndDeviceStatusInfo.microPhone === 'boolean') { await zbysdk.openOrCloseMicrophone(userAndDeviceStatusInfo.microPhone); } } if (userAndDeviceStatusInfo.isPushingFlow) { await zbysdk.startPushFlow(); } const videoSrc = await zbysdk.getOrLocateVideo({ isLocal: true, }); NOTICE.updateLocalPreview({ videoSrc: videoSrc }); defaultApi.writeLog(`sdk update_local_preview , videoSrc : ${videoSrc} `); // } } }, changeGroup(groupId, channelToken) { return this.changeRoom(groupId, channelToken); }, //alias changeGroup async changeRoom(roomId, channelToken) { if (!channelToken) { console.warn('changeRoom param: channelToken is required !'); defaultApi.writeLog('changeRoom param: channelToken is required !'); return; } defaultApi.writeLog(`sdk action : changeRoom to roomId : ${roomId}`); //业务层停止所有拉流 window.zby_sdk_init_params.roomId = roomId; const initParams = window.zby_sdk_init_params; // 通知业务层,room 切换之前 zbysdk.notice({ type: 'sdk_status', data: { sdk_type: window.zbyAVSDK_init_sdk_type, target_room_id: roomId, status: 'before_room_change' } }); defaultApi.writeLog(`sdk status : before_room_change to roomId ${roomId}`); //广播 leave 消息 CHANNEL.sendLeave(initParams); //断开信道 CHANNEL.leaveRoom(initParams); defaultApi.writeLog('channle status : leave channel room invoked'); //退出当前流媒体房间 await zbyAVSDK.leaveRoom(); //获取新小组的云控数据 let reqParam = { clientType: 'pc', roomType: 7, institutionId: initParams.institutionId + '', roomId: initParams.roomId + '', userType: initParams.role, userId: initParams.userId + '', teacherId: initParams.teacherId + '' }; reqParam.sign = util.getVerifySign(reqParam); reqParam.main = 2; //暂存请求云控所需参数,为切换SDK作预备 window.zby_sdk_req_get_cloud_params = reqParam; const cloudResponse = await getCloudData(window.zby_sdk_req_get_cloud_params); const cloudData = cloudResponse.data; const sdk_type = cloudData.sdkName; //SDK重新初始化 const detailArgs = caculateDeatailArgs(initParams, cloudData); await zbyAVSDK.init(sdk_type, detailArgs); //重新进入信道 initParams.channelToken = channelToken; // enterChannelRoom({...initParams, chatUrl: cloudData.chatUrl}); defaultApi.writeLog('channle status : enter channel room invoked'); // sendInitChannelMsg(initParams); CHANNEL.joinRoom({...args, chatUrl: cloudData.chatUrl}, dealSDKMsg, cloudData.chatType); // 通知业务层,room 切换之前 zbysdk.notice({ type: 'sdk_status', data: { sdk_type: window.zbyAVSDK_init_sdk_type, room_id: roomId, status: 'room_changed' } }); defaultApi.writeLog(`sdk status : room_changed ,roomId ${roomId}`); }, async setCameraDevice(deviceId) { defaultApi.writeLog(`sdk action : setCameraDevice --start,deviceId ${deviceId}`); await zbyAVSDK.setCameraDevice(deviceId,'client'); defaultApi.writeLog(`sdk action : setCameraDevice --end,deviceId ${deviceId}`); }, async getCameraDeviceList() { defaultApi.writeLog('sdk action : getCameraDeviceList '); return await zbyAVSDK.getCameraDeviceList(); }, async openOrCloseCamera(operation) { defaultApi.writeLog(`sdk action : openOrCloseCamera ${operation} --start`); userAndDeviceStatusInfo.camera = operation; // 标记业务操作,不做为设备状态参考 await zbyAVSDK.openOrCloseCamera(operation); try { dataReport.deviceChange({ device_type: 1, code: operation? 1 : 0, device_name: window.zbyAVSDK_device_checker_init.camera.name, device_id: window.zbyAVSDK_device_checker_init.camera.use }); } catch (e){}; //记录摄像头状态,用作推流类型上报,是否推视频 this.deviceStatus.camera = operation; sdk_status === 1 && sendDeviceStatus('video', operation); defaultApi.writeLog(`sdk action : openOrCloseCamera ${operation} --end`); }, //推不推画面 async setPushStreamVideo(operation) { await zbyAVSDK.setPushStreamVideo(operation); defaultApi.writeLog(`sdk action : setPushStreamVideo ${operation} `); }, //看或不看指定用户的视频 async setVideoMute(userId, operation, groupId, streamid) { const streamId = streamid || generateStreamId(userId, groupId); defaultApi.writeLog(`sdk action : setVideoMute userId ${userId}, groupId ${groupId}, operation ${operation}, streamId ${streamId}`); await zbyAVSDK.setVideoMute(streamId, operation); }, async getOrLocateVideo(args) { defaultApi.writeLog(`sdk action : getOrLocateVideo --start args : ${JSON.stringify(args)}`); const videoSrc = await zbyAVSDK.getOrLocateVideo({ domId: args.domId, isLocal: args.isLocal, streamId: args.streamId || (args.userId && generateStreamId(args.userId, args.groupId)), isTeacherNewWindowPreview: args.isTeacherNewWindowPreview }); defaultApi.writeLog(`sdk getOrLocateVideo successfully, videoSrc : ${videoSrc} `); return videoSrc; }, async linkMicReport(args) { defaultApi.writeLog(`sdk action : linkMicReport args : ${JSON.stringify(args)}`); const {name, pull_uid, trace_id} = args; let pull_uid1 = []; pull_uid.forEach( item => { pull_uid1.push(item+''); }); if (dataReport.hasOwnProperty(name)) { dataReport[name]({pull_uid:pull_uid1,trace_id}); }; }, async startPushFlow(streamid, idx) { defaultApi.writeLog(`sdk action : startPushFlow streamId:${streamid} idx: ${idx}`); try { // dataReport.startPublish({publish_streamid:window.zbyAVSDK_init_params.rtc.streamId}); streamid&&idx ? dataReport.startPublish({publish_rtc_streamid:streamid}) : dataReport.startPublish() ; } catch (e) {}; if (!idx) { userAndDeviceStatusInfo.isPushingFlow = true; // 仅标记业务调用行为,不作为推流成功参考 } await zbyAVSDK.startPushFlow(streamid, idx); // 不重新推流此情况不适用,推流状态跟着设备开关情况改变,以下仅用作数据上报 // console.log('push_type000',this.deviceStatus.camera,this.deviceStatus.microphone); if(this.deviceStatus.camera && this.deviceStatus.microphone) { this.deviceStatus.stream_type = 'both'; } else if(!this.deviceStatus.camera && this.deviceStatus.microphone) { this.deviceStatus.stream_type = 'audio'; } else if(this.deviceStatus.camera && !this.deviceStatus.microphone) { this.deviceStatus.stream_type = 'video'; } else { this.deviceStatus.stream_type = 'none'; } // console.log('push_type111',this.deviceStatus,this.deviceStatus.stream_type); const initParams = window.zby_sdk_init_params; // initParams.role === 'teacher' && zbyAVSDK.turnPush('start'); if (window.zbyAVSDK_init_sdk_type === 'zego' && initParams.role === 'student') { //仅当学生为zego类型时,才确保推流成功之后再发join消息 return new Promise((resolve, reject) => { let timer = setInterval(() => { if (window.zegoHasPushFlow) { // window.zegoHasPushFlow = 0 clearInterval(timer); resolve(); } }, 300); }).then(() => { //需要确保处于推流状态才能发送AddStream CHANNEL.sendAddStream(initParams); }, err => { reject(err); }).catch(err => { console.log(err); }); } else { //rtc同屏流不走信道 !1 if(!idx) { CHANNEL.sendAddStream(initParams); } } }, async stopPushFlow(idx, streamid) { defaultApi.writeLog(`sdk action : stopPushFlow streamid:${streamid} idx:${idx}`); if (!idx) { userAndDeviceStatusInfo.isPushingFlow = false; // 仅标记业务调用行为,不作为推流成功参考 } await zbyAVSDK.stopPushFlow(idx, streamid); try { streamid && idx ? dataReport.stopPublish({ stop_rtc_streamid: streamid }) : dataReport.stopPublish(); // dataReport.stopPublish({}); } catch (error) { }; if(window.zby_sdk_init_params.isTurnPush) { zbyAVSDK.turnPush('stop'); }; if(!idx) { CHANNEL.sendRemoveStream(window.zby_sdk_init_params); } }, async initPullFlow(args) { defaultApi.writeLog(`sdk action : initPullFlow ,${JSON.stringify(args)}`); const streamId = args.streamId || generateStreamId(args.userId, args.groupId); let {mute, audioOnly} = args; let streamType = 'none'; if(mute && audioOnly) { streamType = 'none'; } else if (mute && !audioOnly) { streamType = 'video'; } else if (!mute && audioOnly) { streamType = 'audio'; } else { streamType = 'both'; }; const result = zbyAVSDK.initPullFlow({ ...args, streamId }); // defaultApi.writeLog(`sdk action : initPullFlow——result ,${JSON.stringify(result)}`); try { dataReport.startPull({pull_uid: args.userId || util.getUidByStreamId(streamId), pull_streamid: streamId, stream_type: streamType}); } catch (e) {}; const { videoSrc, playerId } = await result.videoSrc; defaultApi.writeLog(`sdk initPullFlow ${JSON.stringify(args)}, streamId : ${streamId}, result :${result.sdk_type}: ${videoSrc} type:${streamType} playerId:${playerId}`); if (args.needPlayerId) { return { videoSrc, playerId, streamId, ...args }; } return videoSrc; }, async startPullFlow(userId, groupId) { if (typeof userId !== 'number' && typeof userId !== 'string') { defaultApi.writeLog(`sdk action : startPullFlow ,userId : ${JSON.stringify(userId)}, param error`); return; } else { defaultApi.writeLog(`sdk action : startPullFlow ,userId : ${JSON.stringify(userId)}, begin`); } const streamId = generateStreamId(userId, groupId); await zbyAVSDK.startPullFlow(streamId); // userAndDeviceStatusInfo.ignoreList.delete(userId) noticeStreamStatus(userId, 'stream_recover'); defaultApi.writeLog(`sdk action : startPullFlow ,userId ${userId}, notice: stream_recover`); }, async stopPullFlow(userId, groupId, recovery, streamid) { // const {userId, groupId, recovery, streamid} = args; if (typeof userId !== 'number' && typeof userId !== 'string') { defaultApi.writeLog(`sdk action : stopPullFlow ,userId : ${userId}, groupId: ${groupId}, param error`); return; } else { defaultApi.writeLog(`sdk action : stopPullFlow ,userId : ${userId}, groupId: ${groupId}, begin`); } const streamId = streamid || generateStreamId(userId, groupId); await zbyAVSDK.stopPullFlow(streamId, recovery); try { dataReport.stopPull({pull_uid:userId,pull_streamid:streamId}); } catch (e) {}; noticeStreamStatus(userId, 'stream_stopped'); defaultApi.writeLog(`sdk action : stopPullFlow ,userId : ${userId}, groupId: ${groupId}, notice: stream_stopped`); }, /** * @function 暂停拉所有的流 * @return Promise | void */ async stopAllPullFlow() { defaultApi.writeLog('sdk action : stopAllPullFlow begin'); await zbyAVSDK.stopAllPullFlow(); defaultApi.writeLog('sdk action : stopAllPullFlow end'); }, async playDestroy(userId, groupId) { if (typeof userId !== 'number' && typeof userId !== 'string') { defaultApi.writeLog(`sdk action : playDestroy ,userId : ${userId}, groupId: ${groupId}, param error`); return; } else { defaultApi.writeLog(`sdk action : playDestroy ,userId : ${userId}, groupId: ${groupId}, begin`); } const streamId = generateStreamId(userId, groupId); await zbyAVSDK.playDestroy(streamId); noticeStreamStatus(userId, 'stream_destroy'); defaultApi.writeLog(`sdk action : playDestroy ,userId : ${userId}, groupId: ${groupId}, notice: stream_destroy`); }, async changePullFlow(args) { defaultApi.writeLog(`sdk action : changePullFlow ,${JSON.stringify(args)}`); const streamId = generateStreamId(args.userId, args.groupId); const toStreamId = generateStreamId(args.toUserId, args.toGroupId); const result = zbyAVSDK.changePullFlow({ toDomId: args.toDomId, streamId, toStreamId }); const { videoSrc, playerId } = await result; defaultApi.writeLog(`sdk changePullFlow ${JSON.stringify(args)}, streamId : ${streamId}, toStreamId : ${toStreamId}, result :${result.sdk_type}: ${videoSrc}`); if (args.needPlayerId) { return { videoSrc, playerId }; } return videoSrc; }, async getSpeakerDeviceList() { defaultApi.writeLog('sdk action : getSpeakerDeviceList'); return await zbyAVSDK.getSpeakerDeviceList(); }, async setSpeakerDevice(deviceId) { defaultApi.writeLog(`sdk action : setSpeakerDevice deviceId:${deviceId}`); await zbyAVSDK.setSpeakerDevice(deviceId, 'client'); }, async getSpeakerDevice() { defaultApi.writeLog('sdk action : getSpeakerDevice'); return zbyAVSDK.getSpeakerDevice(); }, async getSpeakerVolume() { defaultApi.writeLog('sdk action : getSpeakerVolume '); return zbyAVSDK.getSpeakerVolume(); }, async setSpeakerVolume(volume) { await zbyAVSDK.setSpeakerVolume(volume); defaultApi.writeLog(`sdk action : setSpeakerVolume ${volume}`); }, async setSpeakerMute(mute) { await zbyAVSDK.setSpeakerMute(mute); try { dataReport.deviceChange({ device_type: 3, code: mute ? 0 :1, device_name: window.zbyAVSDK_device_checker_init.speaker.name, device_id: window.zbyAVSDK_device_checker_init.speaker.use }); } catch (e){}; defaultApi.writeLog(`sdk action : setSpeakerMute ${mute}`); }, async openOrCloseCameraAndMicrophone(type) { await zbyAVSDK.openOrCloseCameraAndMicrophone(type); defaultApi.writeLog(`sdk action : openOrCloseCameraAndMicrophone ${type}`); }, async getAppVolume() { const volume = await zbyAVSDK.getAppVolume(); defaultApi.writeLog(`sdk action : getAppVolume ${volume}`); return volume; }, async setAppVolume(volume) { await zbyAVSDK.setAppVolume(volume); defaultApi.writeLog(`sdk action : setAppVolume ${volume}`); }, async setAppMute(mute) { await zbyAVSDK.setAppMute(mute); defaultApi.writeLog(`sdk action : setAppMute ${mute}`); }, async getMicrophoneDeviceList() { const microPhoneList = await zbyAVSDK.getMicrophoneDeviceList(); defaultApi.writeLog(`sdk action : getMicrophoneDeviceList ${JSON.stringify(microPhoneList)}`); return microPhoneList; }, async setMicrophoneDevice(deviceId) { await zbyAVSDK.setMicrophoneDevice(deviceId, 'client'); defaultApi.writeLog(`sdk action : setMicrophoneDevice ${deviceId}`); }, async openOrCloseMicrophone(operation) { defaultApi.writeLog(`sdk action : openOrCloseMicrophone ${operation} --start`); userAndDeviceStatusInfo.microPhone = operation; // 标记业务操作,不做为设备状态参考 await zbyAVSDK.openOrCloseMicrophone(operation); try { dataReport.deviceChange({ device_type: 2, code: operation ? 1 : 0, device_name: window.zbyAVSDK_device_checker_init.microphone.name, device_id: window.zbyAVSDK_device_checker_init.microphone.use }); } catch (e){}; //记录麦克风状态,用作推流类型上报,是否推声音 this.deviceStatus.microphone = operation; sdk_status === 1 && sendDeviceStatus('audio', operation); defaultApi.writeLog(`sdk action : openOrCloseMicrophone ${operation} --end`); }, //听或不听指定用户的声音 async setAudioMute(userId, operation, groupId, streamid) { const streamId = streamid || generateStreamId(userId, groupId); defaultApi.writeLog(`sdk action : setAudioMute userId ${userId}, operation ${operation}, groupId ${groupId}, streamid ${streamid}`); await zbyAVSDK.setAudioMute(streamId, operation); }, /** * @function 是否拉取音频流--通过播放器id控制 * @param operation:Boolean,必选,true | false * @param playerId:Number,必选,播放器id * @return Promise | void */ async pullAudioFlow(playerId, operation, streamid) { defaultApi.writeLog(`sdk action : pullAudioFlow --start playerId ${playerId}, ${operation}, streamid ${streamid}`); const streamId = streamid ? streamid : undefined; await zbyAVSDK.pullAudioFlow(playerId, operation, streamId); defaultApi.writeLog(`sdk action : pullAudioFlow playerId ${playerId}, ${operation}`); }, async getMicrophoneVolume() { defaultApi.writeLog('sdk action : getMicrophoneVolume'); return await zbyAVSDK.getMicrophoneVolume(); }, async setMicrophoneVolume(volume, mute) { await zbyAVSDK.setMicrophoneVolume(volume, mute); defaultApi.writeLog(`sdk action : setMicrophoneVolume ${volume} ${mute}`); }, async setMicrophoneMute(mute) { await zbyAVSDK.setMicrophoneMute(mute); defaultApi.writeLog(`sdk action : setMicrophoneMute ${mute}`); }, async leaveRoom(type) { //未初始化完成,无须卸载 // if (sdk_status === -1) { // zbysdk.notice({ // type: 'error', // data: { // message: 'should not leaveRoom before init finished' // } // }); // return; // } defaultApi.writeLog('sdk action : leaveRoom'); // if (window.zby_sdk_init_params.role === 'student') { CHANNEL.sendRemoveStream(window.zby_sdk_init_params); // } CHANNEL.sendLeave(window.zby_sdk_init_params); CHANNEL.leaveRoom(); // 重置设备检测初始化状态 deviceCheckerInitStatus = -1; await zbyAVSDK.leaveRoom(type); windowObjArr[0].concat(windowObjArr[1]).forEach(item => { localStorage.removeItem(item); }); sdk_status = -1; try { dataReport.leaveRoom(); } catch (e) {}; defaultApi.writeLog('sdk leaveRoom end ,sdk status : uninstall_finished'); //通知业务层,卸载完成 NOTICE.sdkStatus({ sdk_type: window.zbyAVSDK_init_sdk_type, status: 'uninstall_finished' }); window.zbyAVSDK_device_checker_init = null; }, //崩溃后的销毁引擎,反初始化 async deinit() { defaultApi.writeLog('sdk action : deinit'); await zbyAVSDK.deinit(); }, /** * @function 转推,录课 * @param type:String 动作类型,必选,'start' | 'stop' | 'pause' | 'resume' * @return Promise | void */ async turnPush(cmd) { await zbyAVSDK.turnPush(cmd); defaultApi.writeLog(`sdk action : turnPush ${cmd}`); }, openMicVolumeCb(open) { zbyAVSDK.openMicVolumeCb(open); defaultApi.writeLog(`sdk action : openMicVolumeCb ${open}`); }, // 开始混流--已废弃 startMixtStream(args) { zbyAVSDK.startMixtStream(args); defaultApi.writeLog(`sdk action : startMixtStream, args: ${JSON.stringify(args)}`); }, // 结束混流--已废弃 stopMixtStream(args) { zbyAVSDK.stopMixtStream(args); defaultApi.writeLog(`sdk action : stopMixtStream, args: ${JSON.stringify(args)}`); }, mixedstuVideo(stuArray) { zbyAVSDK.mixedstuVideo(stuArray); defaultApi.writeLog(`sdk action : mixedstuVideo, stuArray: ${stuArray}`); }, /** * @function 单路流录制 * @param args:Object * { * type: String,必选,'start' | 'stop' * groupId: String, 可选,分组id * userId: String, 可选,用户id * } */ singleRecord(args) { args.streamId = this.getStreamInfo(args.userId, args.groupId).streamId; zbyAVSDK.singleRecord(args); defaultApi.writeLog(`sdk action : singleRecord, args: ${JSON.stringify(args)}`); }, //开启拉流音量监听 startSoundLevelMonitor() { defaultApi.writeLog('sdk action : startSoundLevelMonitor --start'); zbyAVSDK.startSoundLevelMonitor(); defaultApi.writeLog('sdk action : startSoundLevelMonitor --end'); }, /** * @function 多路转推 * @param args:Object * { * type: String,必选,'start' | 'stop' * groupId: String, 可选,分组id * userId: String, 可选,用户id * } */ async recordPublish(args) { args.streamId = this.getStreamInfo(args.userId, args.groupId).streamId; zbyAVSDK.recordPublishTarget(args); defaultApi.writeLog(`sdk action : recordPublish, args: ${JSON.stringify(args)}`); }, /** * @function 获取视频快照截图所需的 id 数据 * @param userId:String 用户 ID * @param roomId:String 房间 ID */ getStreamInfo(userId, roomId) { const streamId = generateStreamId(userId, roomId); defaultApi.writeLog(`sdk action :getStreamInfo --start, userId : ${userId}, roomId: ${roomId}`); if (!userId || userId == window.zby_sdk_init_params.userId) { switch (window.current_sdk_type) { case 'rtc': try{ dataReport.takeSnapShot({snapshootId:streamId}); }catch(e){} return { streamId, snapshootId: streamId }; break; case 'zego': try{ dataReport.takeSnapShot({getStreamInfoZego:streamId,snapshootId:-1}); }catch(e){} return { streamId, snapshootId: -1 }; break; case 'nertc': case 'volcrtc': case 'talrtc': try { dataReport.takeSnapShot({snapshootId:streamId}); } catch (e) {} return { streamId, snapshootId: -2 }; case 'trtc': try { dataReport.takeSnapShot({snapshootId:streamId}); } catch (e) {} return { streamId, snapshootId: -3 }; default: break; } } let snapshootId = zbyAVSDK.getSnapshootId(streamId); defaultApi.writeLog(`sdk action :getStreamInfo, userId : ${userId}, snapshootId: ${snapshootId}`); return { streamId, snapshootId }; }, getAllChannelIndex() { let channelMap = zbyAVSDK.getAllChannelIndex(); return channelMap; }, /** * @function 记录日志 * @param productName:String 产品名称,必选 * @param type:String 日志类型,可选,default : 'info', 'debug' | 'info' | 'warnning' | 'error' | 'critical', * @param content:String | Object 日志记录主要内容 */ log(productName, content, type = 'info') { if (!productName) { defaultApi.writeLog('sdk action :log methods invoked error, no productName'); return; } defaultApi.writeLog(content, productNa