zbzt-live-sdk 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.babelrc +8 -0
  2. package/.editorconfig +13 -0
  3. package/.eslintrc.js +29 -0
  4. package/CHANGELOG.md +16 -0
  5. package/README.md +32 -0
  6. package/dist/zbzt-live-sdk.cjs.js +51 -0
  7. package/dist/zbzt-live-sdk.esm.js +51 -0
  8. package/dist/zbzt-live-sdk.umd.js +52 -0
  9. package/dist/zbzt-live-sdk.umd.js.map +1 -0
  10. package/example/app.js +133 -0
  11. package/example/bootstrap-3.4.1/css/bootstrap-theme.css +587 -0
  12. package/example/bootstrap-3.4.1/css/bootstrap-theme.css.map +1 -0
  13. package/example/bootstrap-3.4.1/css/bootstrap-theme.min.css +6 -0
  14. package/example/bootstrap-3.4.1/css/bootstrap-theme.min.css.map +1 -0
  15. package/example/bootstrap-3.4.1/css/bootstrap.css +6834 -0
  16. package/example/bootstrap-3.4.1/css/bootstrap.css.map +1 -0
  17. package/example/bootstrap-3.4.1/css/bootstrap.min.css +6 -0
  18. package/example/bootstrap-3.4.1/css/bootstrap.min.css.map +1 -0
  19. package/example/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.eot +0 -0
  20. package/example/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.svg +288 -0
  21. package/example/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.ttf +0 -0
  22. package/example/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.woff +0 -0
  23. package/example/bootstrap-3.4.1/fonts/glyphicons-halflings-regular.woff2 +0 -0
  24. package/example/bootstrap-3.4.1/js/bootstrap.js +2580 -0
  25. package/example/bootstrap-3.4.1/js/bootstrap.min.js +6 -0
  26. package/example/bootstrap-3.4.1/js/npm.js +13 -0
  27. package/example/css/style.css +18 -0
  28. package/example/index.html +59 -0
  29. package/example/js/jquery-3.7.1.min.js +2 -0
  30. package/example/js/utils.js +25 -0
  31. package/example/js/variables.js +14 -0
  32. package/example/js/zegoApi.js +229 -0
  33. package/example/style.css +25 -0
  34. package/example/test.html +100 -0
  35. package/package.json +60 -0
  36. package/release.js +33 -0
  37. package/rollup-plugin-http.js +49 -0
  38. package/src/channel/getSendMsgParams.js +66 -0
  39. package/src/channel/index.js +135 -0
  40. package/src/channel/pomelo/index.js +182 -0
  41. package/src/channel/pomelo/latestQueue.js +150 -0
  42. package/src/channel/pomelo/polemo.js +730 -0
  43. package/src/channel/pomelo/util.js +54 -0
  44. package/src/channel/sdk-cb.js +73 -0
  45. package/src/channel/stream-msg.js +97 -0
  46. package/src/channel/zbzt/index.js +74 -0
  47. package/src/channel/zbzt/interactWithChannel.js +4 -0
  48. package/src/channel/zbzt/interactWithChannelControl.js +1568 -0
  49. package/src/channel/zbzt/interactWithChannelEntry.js +318 -0
  50. package/src/config/config.js +226 -0
  51. package/src/default/base.js +71 -0
  52. package/src/default/extend.js +36 -0
  53. package/src/default/index.js +10 -0
  54. package/src/live/base.js +43 -0
  55. package/src/live/call-method.js +10 -0
  56. package/src/live/extend.js +53 -0
  57. package/src/live/index.js +10 -0
  58. package/src/network/api.js +56 -0
  59. package/src/network/commonFetch.js +66 -0
  60. package/src/network/dataReport.js +448 -0
  61. package/src/notice.js +418 -0
  62. package/src/tool/base.js +74 -0
  63. package/src/tool/call-method.js +10 -0
  64. package/src/tool/extend.js +42 -0
  65. package/src/tool/index.js +10 -0
  66. package/src/util/bridge.js +87 -0
  67. package/src/util/bridge1.js +46 -0
  68. package/src/util/dict.js +51 -0
  69. package/src/util/sessionStorage.js +29 -0
  70. package/src/util/sha256.js +483 -0
  71. package/src/util/util.js +329 -0
  72. package/src/zbzt-av-sdk/default-sdk.js +192 -0
  73. package/src/zbzt-av-sdk/device.js +86 -0
  74. package/src/zbzt-av-sdk/rtc-sdk.js +2854 -0
  75. package/src/zbzt-av-sdk/talrtc-sdk.js +2620 -0
  76. package/src/zbzt-av-sdk/trtc-sdk.js +1802 -0
  77. package/src/zbzt-av-sdk/zbzt-av-sdk.js +2121 -0
  78. package/src/zbzt-av-sdk/zego-sdk.js +1718 -0
  79. package/src/zbzt-av-sdk/zego-sdk.js.bak +3133 -0
  80. package/src/zbzt-live-sdk.js +1484 -0
@@ -0,0 +1,3133 @@
1
+ /**
2
+ * @File: Zego 音视频 SDK
3
+ * @Author: xuyuanrui
4
+ * @Email: raywhbxyr@163.com
5
+ * @Date: 2018-08-08 10:14:41
6
+ **/
7
+ import { dabanDataReport } from '../network/api.js';
8
+ import dataReport from '../network/dataReport.js';
9
+ import {
10
+ getS,
11
+ setS,
12
+ compareS
13
+ } from '../util/sessionStorage.js';
14
+ import defaultApi from '../default/index.js';
15
+ import util from '../util/util.js';
16
+ import NOTICE from '../notice.js';
17
+ import toolApi from '../tool/index.js';
18
+ import { deviceListReport } from './device.js';
19
+ import zbztsdk from '../zbzt-live-sdk.js';
20
+
21
+ // 扩展标识
22
+ const extensionId = 'zego_ext';
23
+ // 端提供的 API 入口
24
+ const EM = window.EM;
25
+ // 维护的一份当前正在使用的音频设备的 deviceId 的列表
26
+ let usingAudioDeviceId = {
27
+ speaker: '',
28
+ microphone: ''
29
+ };
30
+ // 维护的一份拉流的 streamId 与本地预览通道的映射表
31
+ let streamIdToPreviewId = {};
32
+ let previewIdToStreamId = {};
33
+ // const streamIdToBlobUrl = {};
34
+ // 拉流的播放通道初始化从 0 开始依次递增至44(共45路流),-1 为推流的本地视频预览
35
+ // const uiChnIndexs = new Array(50).fill(0).map((a, b) => b + 1).reverse();
36
+ const uiChnIndexs = new Array(48).fill(0).map((a, b) => b).reverse();
37
+ // 初始化是否完成的标志,0 为未完成,1 为完成
38
+ let isInitFinished = 0;
39
+ // 设备检测初始化是否完成的标志,0 为未完成,1 为完成
40
+ let isDeviceCheckInitFinished = 0;
41
+ // 进入房间是否成功
42
+ let hasLoginChannel = 0;
43
+ // 是否已经推流
44
+ let hasPushFlow = 0;
45
+ // 是否logoutChannel成功
46
+ let isAVEngineStopped = 0;
47
+ // 上层透传的回调函数缓存
48
+ // let zegoCallback = null;
49
+ // 是否执行过 Zego 的 AddListener 的标志
50
+ let hasAddListener = false;
51
+ // 是否处于网络错误状态中的标志
52
+ let hasNetWrong = false;
53
+ // rtc小班课=0;rtc大班课=1
54
+ const classType = 0;
55
+ // 监听id
56
+ let EMListenerId = 0;
57
+
58
+ //静音推流时,音量值是否上抛上层标志 false=没有声音不往上层通知/true=有声音有上层通知
59
+ let isNoticeMicVolumeZego = false;
60
+
61
+ // 心跳
62
+ let heartBeatDataReportObj = {};
63
+ let heartBeatDataReportTimer = null;
64
+ let isFirstHeartBeatReport = false;
65
+ let streamIdRtcPlayerInfo = {};
66
+ let streamIdRtcPlayerInfo1 = {};
67
+ let currStreamIdRtcPlayerInfo;
68
+
69
+ //记录底层推流回调的值
70
+ let dataZegoCapture = {};
71
+
72
+ //记录当前角色
73
+ let currentRole = '';
74
+ //记录当前课态类型:小组课=0/小班课=1
75
+ let currentClassMode = null;
76
+ //记录当前rtmp推流sdk类型
77
+ let currentGroupSdkType = '';
78
+ //主流ID
79
+ let localStreamId = '';
80
+ //屏幕流ID
81
+ let screenStreamId = '';
82
+ /**
83
+ * @function 调用端提供的回调方法
84
+ * @param name:String 回调方法名
85
+ * @param args 回调参数
86
+ * @return Promise | void
87
+ */
88
+ const callMethod = (name, args) => {
89
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
90
+ if (EM) {
91
+ return new Promise((resolve, reject) => {
92
+ let noneCamera = (name === 'SetVideoDevice' && !args.pszDeviceID);
93
+ let noneMicrophone = (name === 'SetAudioDevice' && args.deviceType === 0 && !args.pszDeviceID);
94
+ let noneSpeaker = (name === 'SetAudioDevice' && args.deviceType === 1 && !args.pszDeviceID);
95
+ if (noneCamera || noneMicrophone || noneSpeaker) {
96
+ return resolve();
97
+ }
98
+ EM.CallMethod(
99
+ extensionId,
100
+ name,
101
+ JSON.stringify({ ...args, classType }),
102
+ (code, msg) => {
103
+ defaultApi.writeLog(`${name} Code: ${code} Message: ${msg} Params: ${JSON.stringify({ ...args, classType })}`);
104
+ resolve({
105
+ code,
106
+ msg
107
+ });
108
+ }
109
+ );
110
+ });
111
+ }
112
+ };
113
+
114
+ /**
115
+ * @function 加载 Zego 扩展
116
+ * @param extensionVersion:String 扩展版本号,必选
117
+ * @return Promise | void
118
+ */
119
+ export const loadZego = (extensionVersion) => {
120
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
121
+ if (EM) {
122
+ return new Promise((resolve, reject) => {
123
+ if (getS('zegoVersion')) {
124
+ if (compareS('zegoVersion', extensionVersion)) {
125
+ return resolve();
126
+ }
127
+ }
128
+ EM.Load(
129
+ extensionId,
130
+ extensionVersion,
131
+ false,
132
+ (code, msg) => {
133
+ defaultApi.writeLog(`loadZego Code: ${code}\nMessage: ${msg}`);
134
+ if (code === 0) {
135
+ setS('zegoVersion', extensionVersion);
136
+ }
137
+ resolve();
138
+ }
139
+ );
140
+ });
141
+ }
142
+ };
143
+
144
+ /**
145
+ * @function 卸载 Zego 扩展
146
+ * @return Promise | void
147
+ */
148
+ export const unloadZego = () => {
149
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
150
+ if (EM) {
151
+ return new Promise((resolve, reject) => {
152
+ EM.UnLoad(
153
+ extensionId,
154
+ (code, msg) => {
155
+ defaultApi.writeLog(`unloadZego Code: ${code}\nMessage: ${msg}`);
156
+ resolve();
157
+ }
158
+ );
159
+ });
160
+ }
161
+ };
162
+
163
+ /**
164
+ * @function 添加扩展监听机制
165
+ * @param userId:Number 用户 id,必选
166
+ * @param userName:String 用户名,必选
167
+ * @param roomId:String 频道(房间) id,必选
168
+ * @param nNetType:Number 网络类型,可选,默认为 1
169
+ * @return void
170
+ */
171
+ const addListener = (userId, userName, confId, nNetType, devices, role) => {
172
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
173
+ if (EM && !hasAddListener) {
174
+ hasAddListener = true;
175
+ EM.AddListener(extensionId, (event, data) => {
176
+ if (data && data.indexOf(extensionId) > -1) {
177
+ try {
178
+ EMListenerId = JSON.parse(data)[extensionId];
179
+ defaultApi.writeLog(`ZEGO::addListener-- EMListenerId: ${EMListenerId}`);
180
+ } catch (error) { }
181
+ }
182
+ if (!event || !data) {
183
+ return;
184
+ }
185
+ let _data = JSON.parse(data);
186
+ // if (_data && _data.classType === 1) {
187
+ // return false;
188
+ // }
189
+ switch (event) {
190
+ case 'OnInitSDK':
191
+ // 只有 OnInitSDK 事件成功返回后才可以执行后续操作,比如 loginChannel
192
+ var status = JSON.parse(data).nError;
193
+ var nclassType = JSON.parse(data).nClassType;
194
+ defaultApi.writeLog(`ZEGO::addListener-- OnInitSDK: ${status}--${nclassType}`);
195
+ if (status === 0 && nclassType == 0) {
196
+ if (userId === 'deviceCheckerInit') {
197
+ deviceCheckerInitSDK();
198
+ } else {
199
+ afterInitSDK(userId, userName, confId, nNetType, devices, role);
200
+ }
201
+ }
202
+ break;
203
+ case 'OnLoginChannel':
204
+ var status = JSON.parse(data).uiErrorCode;
205
+ defaultApi.writeLog(`ZEGO::addListener-- OnLoginChannel: ${status}`);
206
+ if (status === 0) {
207
+ hasLoginChannel = 1;
208
+ }
209
+ break;
210
+ case 'OnPublishStateUpdate':
211
+ let res = JSON.parse(data);
212
+ let keys = Object.keys(res);
213
+ if (keys.indexOf('eState') > -1) {
214
+ switch (res.eState) {
215
+ case 0:
216
+ hasPushFlow = 1;
217
+ window.zegoHasPushFlow = 1;
218
+ try {
219
+ let ReportArgs = {};
220
+ if (_data.pszStreamID.split('_').length == 5) {
221
+ ReportArgs.publish_rtc_streamid = _data.pszStreamID;
222
+ }
223
+ dataReport.publishResult({
224
+ code: '0',
225
+ ...ReportArgs
226
+ // publish_streamid: window.zbztAVSDK_init_params.zego.streamId,
227
+ });
228
+ NOTICE.pushFlowSuccess({ code: 0, publish_streamid: _data.pszStreamID });
229
+ } catch (e) { };
230
+ if (window.zbztAVSDK_init_params.zego.isTurnPush) {
231
+ singleRecord('start');
232
+ }
233
+ break;
234
+ case 1:
235
+ hasPushFlow = 0;
236
+ window.zegoHasPushFlow = 0;
237
+ break;
238
+ // 推流重试
239
+ case 6:
240
+ case 7:
241
+ case 105:
242
+ // pushFlowExceptionHandler();
243
+ try {
244
+ dataReport.publishResult({
245
+ code: res.eState,
246
+ // publish_streamid: window.zbztAVSDK_init_params.zego.streamId,
247
+ });
248
+ } catch (e) { };
249
+ break;
250
+ case 10:
251
+ if (!hasNetWrong) {
252
+ hasNetWrong = true;
253
+ defaultApi.writeLog('error', 'Network error');
254
+ NOTICE.networkError({
255
+ message: 'Network error'
256
+ });
257
+ }
258
+ try {
259
+ dataReport.publishResult({
260
+ code: res.eState,
261
+ // publish_streamid: window.zbztAVSDK_init_params.zego.streamId,
262
+ });
263
+ } catch (e) { };
264
+ // pushFlowExceptionHandler();
265
+ break;
266
+ default:
267
+ try {
268
+ dataReport.publishResult({
269
+ code: res.eState,
270
+ // publish_streamid: window.zbztAVSDK_init_params.zego.streamId,
271
+ });
272
+ } catch (e) { };
273
+ break;
274
+ }
275
+ }
276
+ break;
277
+ case 'OnPublishQualityUpdate':
278
+ if (_data.hasOwnProperty('pq') && (_data.pszStreamID).split('_').length != 5) {
279
+ // 主辅两路质量回调,丢包延时只上抛一次,过滤掉辅路数据
280
+ _data.opt = 'quality';
281
+ _data.type = 'mediaupqos';
282
+ if (typeof _data.pq.kbps === 'number' && typeof _data.pq.fps === 'number') {
283
+ NOTICE.pushQuality({
284
+ video: {
285
+ bitrate: Math.round(_data.pq.kbps),
286
+ fps: Math.round(_data.pq.fps)
287
+ }
288
+ });
289
+ }
290
+ // console.log('推流延迟丢包zego',_data);
291
+ NOTICE.pushLossAndDelay({
292
+ userId: util.getUidByStreamId(_data.pszStreamID),
293
+ delay: _data.pq.rtt,
294
+ lostrate: _data.pq.pktLostRate
295
+ });
296
+ heartBeatDataReportCalc(event, _data.pq, _data.pszStreamID);
297
+ }
298
+ break;
299
+ case 'OnCaptureSoundLevelUpdate':
300
+ if (isNoticeMicVolumeZego) {
301
+ NOTICE.captureMicVolumeChanged({
302
+ volume: Math.round(_data.pCaptureSoundLevel[0].soundLevel)
303
+ });
304
+ }
305
+ // heartBeatDataReportObj.volume.push(Math.round(_data.pCaptureSoundLevel[0].soundLevel));
306
+ heartBeatDataReportObj.volume = heartBeatDataReportObj.volume + Math.round(_data.pCaptureSoundLevel[0].soundLevel) + ',';
307
+ break;
308
+ case 'OnSoundLevelUpdate':
309
+ _data.pSoundLevelList.forEach(item => {
310
+ const cbData = {
311
+ streamid: item.szStreamID,
312
+ userId: util.getUidByStreamId(item.szStreamID),
313
+ volume: Math.round(item.soundLevel)
314
+ };
315
+ NOTICE.playerVolumeChanged(cbData);
316
+ NOTICE.volumeChange(cbData);
317
+ // currStreamIdRtcPlayerInfo && currStreamIdRtcPlayerInfo.volume.push(Math.round(item.soundLevel));
318
+ // streamIdRtcPlayerInfo[item.szStreamID] && streamIdRtcPlayerInfo[item.szStreamID].volume.push(Math.round(item.soundLevel));
319
+ if (streamIdRtcPlayerInfo[item.szStreamID]) {
320
+ streamIdRtcPlayerInfo[item.szStreamID].volume = streamIdRtcPlayerInfo[item.szStreamID].volume + Math.round(item.soundLevel) + ',';
321
+ }
322
+ });
323
+ break;
324
+ case 'OnPlayStateUpdate':
325
+ if (_data.hasOwnProperty('eState')) {
326
+ let code = _data.eState;
327
+ if (code === 3) {
328
+ defaultApi.writeLog('error', `ZEGO:: OnPlayStateUpdate eState: ${code}`);
329
+ }
330
+ let normalCode = [0, 1, 3, 1011];
331
+ if (code === 10 && !hasNetWrong) {
332
+ hasNetWrong = true;
333
+ defaultApi.writeLog('error', 'Network error');
334
+ NOTICE.networkError({
335
+ message: 'Network error'
336
+ });
337
+ dabanDataReport({
338
+ action: 'zbzt_live_sdk_player_network_error',
339
+ uid: window.zbztAVSDK_init_params.zego.userId,
340
+ streamid: _data.pszStreamID,
341
+ teacherId: window.zbztAVSDK_init_params.zego.teacherId,
342
+ errorcode: code,
343
+ sdktype: 'zego'
344
+ });
345
+ }
346
+ // 拉流重试
347
+ if (normalCode.indexOf(code) === -1) {
348
+ setTimeout(() => {
349
+ // pullFlowExceptionHandler(_data.pszStreamID);
350
+ NOTICE.playError({
351
+ userId: util.getUidByStreamId(_data.pszStreamID),
352
+ message: 'play error'
353
+ });
354
+
355
+ dabanDataReport({
356
+ action: 'zbzt_live_sdk_player_play_error',
357
+ uid: window.zbztAVSDK_init_params.zego.userId,
358
+ streamid: _data.pszStreamID,
359
+ teacherId: window.zbztAVSDK_init_params.zego.teacherId,
360
+ errorcode: code,
361
+ sdktype: 'zego'
362
+ });
363
+ }, 1000);
364
+ };
365
+ try {
366
+ if (_data.pszStreamID.indexOf('ai') < 0) {
367
+ dataReport.pullResult({
368
+ code: code,
369
+ // pull_uid: _data.pszStreamID.split('_').length == 5 ? _data.pszStreamID : util.getUidByStreamId(_data.pszStreamID),
370
+ pull_uid: util.getUidByStreamId(_data.pszStreamID),
371
+ pull_streamid: _data.pszStreamID
372
+ });
373
+ NOTICE.pullFlowResult({ code: code, pull_streamid: _data.pszStreamID });
374
+ }
375
+ // dataReport.pullResult({
376
+ // code: code,
377
+ // pull_uid: util.getUidByStreamId(_data.pszStreamID),
378
+ // pull_streamid: _data.pszStreamID
379
+ // });
380
+ } catch (e) { };
381
+ }
382
+ break;
383
+ case 'OnPlayQulityUpdate': // 拉流
384
+ if (_data.hasOwnProperty('pq')) {
385
+ // console.log('拉流回调',`${new Date().getMinutes()}:${new Date().getSeconds()}`,_data);
386
+ _data.opt = 'quality';
387
+ _data.type = 'mediadownqos';
388
+ NOTICE.pullQuality({
389
+ video: {
390
+ streamId: _data.pszStreamID,
391
+ userId: util.getUidByStreamId(_data.pszStreamID),
392
+ bitrate: _data.pq.kbps,
393
+ fps: _data.pq.fps,
394
+ }
395
+ });
396
+ // console.log('拉流延迟丢包zego',_data);
397
+ NOTICE.playLossAndDelay({
398
+ userId: util.getUidByStreamId(_data.pszStreamID),
399
+ delay: _data.pq.rtt,
400
+ lostrate: _data.pq.pktLostRate
401
+ });
402
+ currStreamIdRtcPlayerInfo = streamIdRtcPlayerInfo[_data.pszStreamID];
403
+ heartBeatDataReportCalc(event, _data.pq, _data.pszStreamID);
404
+ }
405
+ break;
406
+ case 'OnVideoDeviceStateChanged': // 视频设备状态变更
407
+ // _data.state 0=添加设备 1=移除设备
408
+ // console.log('hsghsghsg摄像头热插拔',_data);
409
+ setVideoDevice({ deviceId: _data.state == 1 ? '' : _data.deviceInfo.szDeviceId, idx: 0, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceInfo.szDeviceId });
410
+ // try {
411
+ // dataReport.deviceTest({
412
+ // device: '1',
413
+ // fore_state: _data.state == 0 ? 1 : 2 ,
414
+ // camera_name: _data.deviceInfo && _data.deviceInfo.szDeviceName,
415
+ // });
416
+ // } catch (e){};
417
+ break;
418
+ case 'OnAudioDeviceStateChanged': // 音频设备状态变更
419
+ // console.log('hsghsghsg扬声器热插拔1',_data);
420
+ if (_data.deviceType === 0) {
421
+ // _data.state 0=添加设备 1=移除设备
422
+ setMicrophoneDevice({ deviceId: _data.state == 1 ? '' : _data.deviceInfo.szDeviceId, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceInfo.szDeviceId });
423
+ }
424
+ if (_data.deviceType === 1) {
425
+ // console.log('hsghsghsg扬声器热插拔',_data);
426
+ setSpeakerDevice({ deviceId: _data.state == 1 ? '' : _data.deviceInfo.szDeviceId, operationType: 'hotPlug', deviceState: _data.state, changedDeviceId: _data.deviceInfo.szDeviceId });
427
+ }
428
+ // try {
429
+ // dataReport.deviceTest({
430
+ // device: _data.deviceType === 0 ? '2' : '3',
431
+ // fore_state: _data.state == 0 ? 1 : 2 ,
432
+ // microphone_name: _data.deviceInfo && _data.deviceInfo.szDeviceName,
433
+ // speaker_name: _data.deviceInfo && _data.deviceInfo.szDeviceName
434
+ // });
435
+ // } catch (e){};
436
+ break;
437
+ case 'OnDeviceError':
438
+ //errorCode 无效设备ID (-2), 没有权限 (-3), 采集帧率为0 (-4), 设备被占用 (-5), 设备未插入 (-6), 需要重启系统 (-7), 媒体服务无法恢复 (-8), 设备被SIRI占用 (-9)
439
+ let codemsg = {
440
+ '-2': '无效设备ID',
441
+ '-3': '没有权限',
442
+ '-4': '采集帧率为0',
443
+ '-5': '设备被占用',
444
+ '-6': '设备未插入',
445
+ '-7': '需要重启系统',
446
+ '-8': '媒体服务无法恢复',
447
+ '-9': '设备被SIRI占用'
448
+ };
449
+ defaultApi.writeLog(`avsdk ZEGO:: OnDeviceError ${_data.deviceName} ${_data.errorCode}`);
450
+ dataReport.deviceError({ deviceName: _data.deviceName, errorCode: _data.errorCode });
451
+ // _data.deviceName === 'camera' ? setVideoDevice({deviceId: '', idx: 0, operationType: 'deviceError', deviceState: '', code: codemsg[_data.errorCode]}) : setMicrophoneDevice({deviceId: '', operationType: 'deviceError', deviceState: '', code: codemsg[_data.errorCode]});
452
+ break;
453
+ case 'OnAVKitEvent':
454
+ // defaultApi.writeLog('avsdk ZEGO:: OnAVKitEvent');
455
+ if (_data.event === 4 && hasNetWrong) {
456
+ hasNetWrong = false;
457
+ NOTICE.networkRecovery({
458
+ message: 'Network recovery'
459
+ });
460
+ }
461
+ break;
462
+ case 'OnAVEngineStop':
463
+ isAVEngineStopped = 1;
464
+ defaultApi.writeLog('avsdk ZEGO:: listened AVEngineStop');
465
+ break;
466
+ case 'OnMixStream':
467
+ defaultApi.writeLog('avsdk ZEGO:: listened mix_stream_response');
468
+ break;
469
+ case 'OnRenderRemoteVideoFirstFrame':
470
+ // 大班数据上报
471
+ if (window.zbztAVSDK_init_params.zego.role === 'student') {
472
+ dabanDataReport({
473
+ action: 'interact_play',
474
+ teammate_streamid: _data.pszStreamID,
475
+ uid: window.zbztAVSDK_init_params.zego.userId
476
+ });
477
+ }
478
+ try {
479
+ NOTICE.firstVideoSize({
480
+ streamId: _data.pszStreamID,
481
+ // userId: _data.pszStreamID.split('_').length == 5 ? _data.pszStreamID : util.getUidByStreamId(_data.pszStreamID)
482
+ userId: util.getUidByStreamId(_data.pszStreamID)
483
+ });
484
+ dataReport.firstVideoSize({
485
+ pull_streamid: _data.pszStreamID,
486
+ pull_uid: util.getUidByStreamIdDr(_data.pszStreamID),
487
+ code: '0'
488
+ });
489
+ } catch (e) { };
490
+ defaultApi.writeLog(`ZEGO: pullStream success & haveFirstVideoSize streamId: ${_data.pszStreamID}`);
491
+ // try {
492
+ // dataReport.pullResult({
493
+ // status: 0,
494
+ // pull_uid: util.getUidByStreamId(_data.pszStreamID),
495
+ // pull_streamid: _data.pszStreamID
496
+ // });
497
+ // } catch (e) {};
498
+ break;
499
+ case 'OnRecvRemoteAudioFirstFrame':
500
+ try {
501
+ NOTICE.firstAudioSize({
502
+ streamId: _data.pszStreamID,
503
+ userId: util.getUidByStreamId(_data.pszStreamID)
504
+ });
505
+ dataReport.firstAudioSize({
506
+ pull_streamid: _data.pszStreamID,
507
+ pull_uid: util.getUidByStreamIdDr(_data.pszStreamID),
508
+ code: '0'
509
+ });
510
+ } catch (e) { };
511
+ break;
512
+ // 转推回调 0=转推停止 1=正在转推 2=正在重试
513
+ case 'onRecvMediaSideInfo':
514
+ defaultApi.writeLog(`avsdk ZEGO:: onRecvMediaSideInfo, ${JSON.stringify(_data)}`);
515
+ NOTICE.seiReceived({ data: _data });
516
+ break;
517
+ case 'zego_recovery_start':
518
+ defaultApi.writeLog(`avsdk ZEGO:: zego_recovery_start ${JSON.stringify(_data)}`);
519
+ NOTICE.zegoRecoveryStart();
520
+ break;
521
+ case 'OnRelayCDNStateUpdate':
522
+ if (_data.statesInfo && _data.statesInfo[0] && _data.statesInfo[0].state === 1) {
523
+ NOTICE.recordResponse({
524
+ streamId: _data.streamID,
525
+ userId: util.getUidByStreamId(_data.streamID)
526
+ });
527
+ }
528
+ // try {
529
+ // dataReport.turnPushResult({
530
+ // errorcode:_data.statesInfo[0].state,
531
+ // case: 'turn push',
532
+ // streamid: _data.streamID
533
+ // })
534
+ // } catch (e) {};
535
+ break;
536
+ case 'OnCaptureVideoFirstFrame':
537
+ // 大班数据上报
538
+ dabanDataReport({
539
+ action: 'open_camera',
540
+ camera_status: 1,
541
+ uid: window.zbztAVSDK_init_params.zego.userId
542
+ });
543
+ break;
544
+ case 'OnKaDunEvent':
545
+ if (_data.event === 8) {
546
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.video_ifg += _data.kaDunTime);
547
+ }
548
+ if (_data.event === 10) {
549
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.audio_ifg += _data.kaDunTime);
550
+ }
551
+ break;
552
+ }
553
+ if (zbztsdk.openListenerLog) {
554
+ defaultApi.writeLog(`Zego::Listener:: event: ${event}, data: ${JSON.stringify(data)}`);
555
+ }
556
+ });
557
+ }
558
+ };
559
+
560
+ /**
561
+ * @function 添加扩展监听机制
562
+ * @return void
563
+ */
564
+ const removerListener = () => {
565
+ hasAddListener = false;
566
+ defaultApi.writeLog(`ZEGO::action--removerListener EMListenerId:${EMListenerId}`);
567
+ EM.RemoverListener(extensionId, EMListenerId, (ec, content) => { });
568
+ EMListenerId = 0;
569
+ };
570
+
571
+ /**
572
+ * @function 推流异常恢复
573
+ */
574
+ export const pushFlowExceptionHandler = async () => {
575
+ await new Promise((resolve, reject) => {
576
+ setTimeout(() => {
577
+ resolve();
578
+ }, 1000);
579
+ });
580
+ defaultApi.writeLog('断网重推');
581
+ defaultApi.writeLog('avsdk ZEGO::try to pushFlow again');
582
+ await stopPublish();
583
+ await startPublish2();
584
+ };
585
+
586
+ /**
587
+ * @function 拉流异常恢复
588
+ */
589
+ export const pullFlowExceptionHandler = async (streamId) => {
590
+ await new Promise((resolve, reject) => {
591
+ setTimeout(() => {
592
+ resolve();
593
+ }, 1000);
594
+ });
595
+ defaultApi.writeLog('断网重拉');
596
+ defaultApi.writeLog(`avsdk ZEGO::try to pullFlow again ,streamId : ${streamId}`);
597
+ await stopPlayStream(streamId);
598
+ await playStream(streamId);
599
+ };
600
+
601
+ /**
602
+ * @function 初始化 Engine
603
+ * @param appId:String Zego 秘钥,必选
604
+ * @param appSignature:String 签名,必选
605
+ * @param businessType:Number 业务类型,可选,默认为 0
606
+ * @param videoRenderType:Number zego视频渲染类型,默认为2(只外部渲染),zego小组课需要设置为5(同时支持内部+外部渲染)
607
+ * @return Promise | void
608
+ */
609
+ export const startEngine = (appId, appSignature, businessType, videoRenderType=2) => {
610
+ if (typeof businessType === 'undefined') {
611
+ businessType = 0;
612
+ }
613
+ defaultApi.writeLog('avsdk ZEGO::StartEngine');
614
+ return callMethod('StartEngine', {
615
+ appId,
616
+ appSignature,
617
+ businessType,
618
+ videoRenderType
619
+ });
620
+ };
621
+
622
+ //开启消除回声
623
+ export const setEnableAEC = (bEnable) => {
624
+ return callMethod('EnableAEC', { bEnable });
625
+ };
626
+
627
+ //设置回声消除模式 mode :激进模式 =0/中等模式 =1/轻度模式 =2
628
+ export const setAECMode = (mode) => {
629
+ return callMethod('SetAECMode', { mode });
630
+ };
631
+
632
+ //开启噪音消除
633
+ export const setEnableNoiseSuppress = (bEnable) => {
634
+ return callMethod('EnableNoiseSuppress', { bEnable });
635
+ };
636
+
637
+ //设置噪音消除模式 mode :0:低 1:中 2高
638
+ export const setNoiseSuppressMode = (level) => {
639
+ return callMethod('SetNoiseSuppressMode', { level });
640
+ };
641
+
642
+ //新增瞬时降噪接口 瞬时降噪 可以处理掉 敲键盘、敲桌子、敲门等瞬态噪声。非瞬态噪声,此接口无法处理,比如划桌子等摩擦噪音。
643
+ export const enableTransientNoiseSuppress = (enable) => {
644
+ return callMethod('EnableTransientNoiseSuppress', { enable })
645
+ }
646
+
647
+ /**
648
+ * @function 加载采集插件的输入数据 //调用后,zego 可以向采集插件传送摄像头数据,用于拼接
649
+ * @return: Promise
650
+ */
651
+ export const loadCollectionInputEntry = () => {
652
+ return callMethod('LoadCollectionInputEntry', {});
653
+ };
654
+
655
+ /**
656
+ * @function 加载采集插件的输出数据 //调用后,zego 可以向采集插件传送学生流数据(加载截屏插件,获取截屏插件设置拉流头像回调函数)
657
+ * @param stream_ids array 设置需要拼接的学生头像流id,按数组顺序拼接
658
+ * @return: Promise
659
+ */
660
+ export const loadCollectionInputEntry2 = (stream_ids) => {
661
+ return callMethod('LoadCollectionInputEntry2', { stream_ids });
662
+ };
663
+
664
+ /**
665
+ * @function 加载采集插件的输出数据 //调用后,zego 可以从采集插件获取拼接数据
666
+ * @return: Promise
667
+ */
668
+ export const loadCollectionOutputEntry = () => {
669
+ return callMethod('LoadCollectionOutputEntry', {});
670
+ };
671
+ /**
672
+ * @function 设置直推url //调用后,zego 可以从采集插件获取拼接数据
673
+ * @param pRtmpUrl:String 直推地址
674
+ * @param idx:Number 使用外部采集的通道idx,与StartEngine中channel_idx保持一致
675
+ * @return: Promise
676
+ */
677
+ export const setCDNPublishTarget = (pRtmpUrl, idx) => {
678
+ return callMethod('SetCDNPublishTarget', { pRtmpUrl, idx });
679
+ };
680
+ /**
681
+ * @function 销毁引擎
682
+ * @return Promise | void
683
+ */
684
+ export const destroyEngine = () => {
685
+ return callMethod('DestroyEngine', {});
686
+ };
687
+
688
+ /**
689
+ * @function 加入频道
690
+ * @param userId:Number 用户 id,必选
691
+ * @param userName:String 用户名,必选
692
+ * @param channelId:String 频道 id,必选
693
+ * @param nNetType:Number 网络类型,可选,默认为 1
694
+ * @return Promise | void
695
+ */
696
+ export const loginChannel = (userId, userName, channelId, nNetType) => {
697
+ if (typeof nNetType === 'undefined') {
698
+ nNetType = 1;
699
+ }
700
+ return callMethod('LoginChannel', {
701
+ pszUserID: userId + '',
702
+ pszUserName: userName,
703
+ pszChannelID: channelId,
704
+ nNetType
705
+ });
706
+ };
707
+
708
+ /**
709
+ * @function 退出直播频道
710
+ * @return Promise | void
711
+ */
712
+ export const logoutChannel = () => {
713
+ defaultApi.writeLog('avsdk ZEGO:: CallMethod : LogoutChannel');
714
+ return callMethod('LogoutChannel', {});
715
+ };
716
+
717
+ /**
718
+ * @function 云控时退出房间
719
+ * @return Promise
720
+ */
721
+ export const leaveRoomWithChangeSDK = async () => {
722
+ defaultApi.writeLog(`leaveRoomWithChangeSDK--currentClassMode--currentGroupSdkType ${currentClassMode}, ${currentGroupSdkType}`);
723
+ let needDestroyZegoEngine = true; //云控从zego切到其他sdk时,默认释放zego引擎。但是如果zego在推拉RTMP流,则不能释放
724
+ if (currentGroupSdkType == 'zego' || window.zbzt_isM1Type) {
725
+ switch (currentClassMode) {
726
+ case 0: // 小组
727
+ case 2: // 组合小班
728
+ needDestroyZegoEngine = false;
729
+ break;
730
+ case 1: // 小班
731
+ if (window.zbzt_sdk_init_params.role === 'teacher' || window.zbzt_sdk_init_params.role === 'assistant') {
732
+ needDestroyZegoEngine = false;
733
+ }
734
+ break;
735
+ }
736
+ }
737
+ await stopSoundLevelMonitor();
738
+ for (let key in streamIdToPreviewId) {
739
+ await stopPlayStream(key, true);
740
+ }
741
+ if ((isZegoGroupClass() && (currentRole === 'teacher' || currentRole === 'assistant')) || (isZegoCombinationClass() && currentRole === 'assistant')) {
742
+ // zego小组课,切RTC流云控后,授课端不能停止预览
743
+ console.log('zego小组课不可停止预览,会影响rtmp')
744
+ }
745
+ else {
746
+ await stopPreview();
747
+ }
748
+ await stopPublish();
749
+ removerListener();
750
+
751
+ if (needDestroyZegoEngine === true) {
752
+ await destroyEngine();
753
+ }
754
+ if ((window.zbzt_sdk_init_params.role === 'teacher') && window.zbzt_sdk_init_params.mode === 1) {
755
+ //坐立模式关闭外部采集器,站立关闭外部采集器
756
+ await setVideoCaptureFactory(false);
757
+ }
758
+ heartBeatDataReport('stop');
759
+ isFirstHeartBeatReport = false;
760
+ streamIdToPreviewId = {};
761
+ previewIdToStreamId = {};
762
+ streamIdRtcPlayerInfo = {};
763
+ streamIdRtcPlayerInfo1 = {};
764
+ // heartBeatDataReportObj = {};
765
+ hasLoginChannel = 0;
766
+ hasPushFlow = 0;
767
+ isAVEngineStopped = 0;
768
+ window.zegoHasPushFlow = 0;
769
+ };
770
+
771
+ /**
772
+ * @function 退出房间
773
+ * @return Promise
774
+ */
775
+ export const leaveRoom = async (type) => {
776
+ await stopSoundLevelMonitor();
777
+ for (let key in streamIdToPreviewId) {
778
+ await stopPlayStream(key, true);
779
+ }
780
+ await stopPublish();
781
+ removerListener();
782
+ // await logoutChannel();
783
+ // await new Promise((resolve, reject) => {
784
+ // let timer = setInterval(() => {
785
+ // if (isAVEngineStopped) {
786
+ // clearInterval(timer);
787
+ // resolve();
788
+ // }
789
+ // }, 300);
790
+ // });
791
+ if (type == 'reload') {
792
+ defaultApi.writeLog('leaveroom -- reload --小组课刷新不可销毁zego引擎')
793
+ } else {
794
+ await stopPreview();
795
+ await destroyEngine();
796
+ }
797
+ if ((window.zbzt_sdk_init_params.role === 'teacher') && window.zbzt_sdk_init_params.mode === 1) {
798
+ //坐立模式关闭外部采集器,站立关闭外部采集器
799
+ await setVideoCaptureFactory(false);
800
+ }
801
+ heartBeatDataReport('stop');
802
+ isFirstHeartBeatReport = false;
803
+ streamIdToPreviewId = {};
804
+ previewIdToStreamId = {};
805
+ streamIdRtcPlayerInfo = {};
806
+ streamIdRtcPlayerInfo1 = {};
807
+ // heartBeatDataReportObj = {};
808
+ hasLoginChannel = 0;
809
+ hasPushFlow = 0;
810
+ isAVEngineStopped = 0;
811
+ window.zegoHasPushFlow = 0;
812
+ };
813
+
814
+ export const stopCheckDevice = async () => {
815
+ removerListener();
816
+ await stopSoundLevelMonitor();
817
+ await stopPreview();
818
+ defaultApi.writeLog('rtc stopCheckDevice and removerListener and captureDestroy');
819
+ return callMethod('DestroyEngine', {});
820
+ };
821
+
822
+ /**
823
+ * @function 获取系统默认的音频设备
824
+ * @param deviceType:Number 音频设备类型,0 -> 麦克风,1 -> 扬声器,必选
825
+ * @return Promise | void
826
+ */
827
+ export const getDefaultAudioDeviceId = (deviceType) => {
828
+ return callMethod('GetDefaultAudioDeviceId', {
829
+ deviceType,
830
+ // 以下两个参数仅仅是为了向下向后兼容,使用 hardcore 即可
831
+ deviceId: '',
832
+ deviceIdLength: 0
833
+ });
834
+ };
835
+
836
+ /**
837
+ * @function 获取系统默认的麦克风设备 id
838
+ * @return Promise
839
+ */
840
+ export const getDefaultMicrophone = () => {
841
+ return getDefaultAudioDeviceId(0);
842
+ };
843
+
844
+ /**
845
+ * @function 获取系统默认的扬声器设备 id
846
+ * @return Promise
847
+ */
848
+ export const getDefaultSpeaker = () => {
849
+ return getDefaultAudioDeviceId(1);
850
+ };
851
+
852
+ /**
853
+ * @function 获取摄像头列表
854
+ * @return Promise | void
855
+ */
856
+ export const getVideoDeviceList = async () => {
857
+ let videoListArr = JSON.parse((await callMethod('GetVideoDeviceList', {
858
+ // 这个参数是 C++ 要使用的引用参数,随便传个整型就行
859
+ device_count: 1
860
+ })).msg).ret;
861
+ let videoList = [];
862
+ for (let i = 0, len = videoListArr.length; i < len; i++) {
863
+ videoList.push({
864
+ deviceId: videoListArr[i].szDeviceId,
865
+ deviceName: videoListArr[i].szDeviceName,
866
+ isDefault: i === 0
867
+ });
868
+ deviceListReport.cameraList[videoListArr[i].szDeviceId] = videoListArr[i].szDeviceName;
869
+ }
870
+ if (!window.zbztAVSDK_device_checker_init) {
871
+ window.zbztAVSDK_device_checker_init = {};
872
+ }
873
+ if (!window.zbztAVSDK_device_checker_init.camera) {
874
+ window.zbztAVSDK_device_checker_init.camera = {};
875
+ }
876
+ window.zbztAVSDK_device_checker_init.camera.hasTest = true;
877
+ window.zbztAVSDK_device_checker_init.camera.list = videoList;
878
+ return videoList;
879
+ };
880
+
881
+ /**
882
+ * @function 指定使用的摄像头
883
+ * @param deviceId:String 摄像头 id,必选
884
+ * @param idx:Number 推流通道,可选,默认为 0
885
+ * @param operationType:String 操作类型,可选
886
+ * 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
887
+ * 不传即是普通的设置摄像头设备的行为
888
+ * @return Promise | void
889
+ */
890
+ export const setVideoDevice = async (args) => {
891
+ defaultApi.writeLog(`${JSON.stringify(args)}----setVideoDevice-zego----`);
892
+ let { deviceId, idx, operationType, deviceState, code, changedDeviceId } = args;
893
+ let deviceName = '';
894
+ let cameraData;
895
+ if (!deviceId) {
896
+ cameraData = await getVideoDeviceList();
897
+ // console.log('hsghsghsg0',cameraData);
898
+ if (cameraData.length) {
899
+ let hasGetCamare = false;
900
+ // console.log('hsghsghsg1',hasGetSpeaker);
901
+ for (let item of cameraData) {
902
+ if (item.isDefault) {
903
+ deviceId = item.deviceId;
904
+ deviceName = item.deviceName;
905
+ hasGetCamare = true;
906
+ break;
907
+ }
908
+ }
909
+ // console.log('hsghsghsg2',hasGetSpeaker);
910
+ if (!hasGetCamare) {
911
+ deviceId = cameraData[0].deviceId;
912
+ deviceName = cameraData[0].deviceName;
913
+ // console.log('hsghsghsg91',deviceId);
914
+ }
915
+ } else {
916
+ deviceId = '';
917
+ }
918
+ // console.log('hsghsghsg1',deviceId);
919
+ if (deviceId === '') {
920
+ NOTICE.noDevice({
921
+ deviceType: 'camera'
922
+ });
923
+ }
924
+ }
925
+ window.zbztAVSDK_device_checker_init.camera.use = deviceId;
926
+ window.zbztAVSDK_device_checker_init.camera.name = deviceListReport.cameraList[deviceId];
927
+ if (typeof idx === 'undefined') {
928
+ idx = 0;
929
+ }
930
+ try {
931
+ dataReport.setDevice({
932
+ device_type: 1,
933
+ device_id: deviceId,
934
+ device_name: deviceListReport.cameraList[deviceId],
935
+ operationType,
936
+ fore_state: operationType == 'hotPlug' ? deviceState + 1 : '-'
937
+ });
938
+ } catch (e) { };
939
+ await callMethod('SetVideoDevice', {
940
+ pszDeviceID: deviceId,
941
+ idx
942
+ });
943
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
944
+ if (!cameraData) {
945
+ cameraData = await getVideoDeviceList();
946
+ deviceName = deviceListReport.cameraList[deviceId];
947
+ }
948
+ NOTICE[operationType]({
949
+ deviceType: 'camera',
950
+ useDeviceId: deviceId,
951
+ useDeviceName: deviceName,
952
+ deviceList: cameraData,
953
+ messge: code,
954
+ deviceState,
955
+ changedDeviceId
956
+ });
957
+ }
958
+ try {
959
+ NOTICE.useredCamera({
960
+ deviceId,
961
+ deviceName
962
+ });
963
+ } catch (e) { };
964
+ };
965
+
966
+ /**
967
+ * @function 开/关摄像头
968
+ * @param enable:Boolean false -> 关闭,true -> 打开,必选
969
+ * @param idx:Number 推流通道,可选,默认为 0
970
+ * @return Promise | void
971
+ */
972
+ export const enableCamera = (enable, idx = 0) => {
973
+ // try {
974
+ // dataReport.deviceChange({
975
+ // device: 1,
976
+ // device_state: enable? 1 : 0
977
+ // });
978
+ // } catch (e){};
979
+ return callMethod('EnableCamera', {
980
+ bEnable: enable,
981
+ idx
982
+ });
983
+ };
984
+
985
+ /**
986
+ * @function 开/关麦克风
987
+ * @param bEnable:Boolean false -> 关闭,true -> 打开,必选
988
+ * @param idx:Number 推流通道,可选,默认为 0
989
+ * @return Promise | void
990
+ */
991
+ export const enableMic = async (bEnable, idx) => {
992
+ defaultApi.writeLog('enableMic --start');
993
+ isNoticeMicVolumeZego = bEnable;
994
+ // if (bEnable) {
995
+ // await setMicDeviceMute(false);
996
+ // defaultApi.writeLog('openMic and muteFalse');
997
+ // }
998
+ if (typeof idx === 'undefined') {
999
+ idx = 0;
1000
+ }
1001
+ // try {
1002
+ // dataReport.deviceChange({
1003
+ // device: 2,
1004
+ // device_state: bEnable ? 1 : 0
1005
+ // });
1006
+ // } catch (e){};
1007
+ return callMethod('EnableMic', {
1008
+ bEnable,
1009
+ idx
1010
+ });
1011
+ };
1012
+
1013
+ /**
1014
+ * @function 是否推声音
1015
+ * @param mute:Boolean true/不推声音,false/推声音,必选
1016
+ * @return Promise | void
1017
+ */
1018
+ export const setMuteStreamAudio = (mute) => {
1019
+ return callMethod('MuteStreamAudio', { mute });
1020
+ };
1021
+
1022
+ /**
1023
+ * @function 是否推画面
1024
+ * @param mute:Boolean true/不推画面,false/推画面,必选
1025
+ * @return Promise | void
1026
+ */
1027
+ export const setMuteStreamVideo = (mute) => {
1028
+ return callMethod('MuteStreamVideo', { mute });
1029
+ };
1030
+
1031
+ /**
1032
+ * @function 获取音频设备
1033
+ * @param deviceType:Number 音频设备类型,0 -> 麦克风,1 -> 扬声器,必选
1034
+ * @return Promise | void
1035
+ */
1036
+ export const getAudioDeviceList = (deviceType) => {
1037
+ return callMethod('GetAudioDeviceList', {
1038
+ deviceType,
1039
+ // 这个参数是 C++ 要使用的引用参数,随便传个整型就行
1040
+ device_count: 0
1041
+ });
1042
+ };
1043
+
1044
+ /**
1045
+ * @function 指定音频设备
1046
+ * @param deviceType:Number 音频设备类型,0 -> 麦克风,1 -> 扬声器,必选
1047
+ * @param deviceId:String 音频设备 id,必选
1048
+ * @return Promise | void
1049
+ */
1050
+ export const setAudioDevice = (deviceType, deviceId) => {
1051
+ if (deviceType == 0) {
1052
+ window.zbztAVSDK_device_checker_init.microphone.use = deviceId;
1053
+ } else {
1054
+ window.zbztAVSDK_device_checker_init.speaker.use = deviceId;
1055
+ }
1056
+ return callMethod('SetAudioDevice', {
1057
+ deviceType,
1058
+ pszDeviceID: deviceId
1059
+ }).then((result) => {
1060
+ if (deviceType == 1 && result.code === 0) {
1061
+ NOTICE.speakerChanged({
1062
+ deviceId
1063
+ });
1064
+ }
1065
+ return result;
1066
+ });
1067
+ };
1068
+
1069
+ /**
1070
+ * 获取当前扬声器设备id
1071
+ * @return {String} 当前扬声器设备id
1072
+ */
1073
+ const getCurrentSpeakerDevice = () => {
1074
+ defaultApi.writeLog(`avsdk ZEGO::getSpeakerDevice ${usingAudioDeviceId.speaker}`);
1075
+ return usingAudioDeviceId.speaker;
1076
+ };
1077
+
1078
+ /**
1079
+ * @function 获取扬声器列表
1080
+ * @return Promise | void
1081
+ */
1082
+ export const getSpeakerDeviceList = async () => {
1083
+ const defaultSpeakerId = JSON.parse((await getDefaultSpeaker()).msg).ret.deviceId;
1084
+ let speakerListArr = JSON.parse((await getAudioDeviceList(1)).msg).ret;
1085
+ let speakerList = [];
1086
+ for (let i = 0, len = speakerListArr.length; i < len; i++) {
1087
+ speakerList.push({
1088
+ deviceId: speakerListArr[i].szDeviceId,
1089
+ deviceName: speakerListArr[i].szDeviceName,
1090
+ isDefault: defaultSpeakerId === speakerListArr[i].szDeviceId
1091
+ });
1092
+ deviceListReport.speakerList[speakerListArr[i].szDeviceId] = speakerListArr[i].szDeviceName;
1093
+
1094
+ }
1095
+ if (!window.zbztAVSDK_device_checker_init) {
1096
+ window.zbztAVSDK_device_checker_init = {};
1097
+ }
1098
+ if (!window.zbztAVSDK_device_checker_init.speaker) {
1099
+ window.zbztAVSDK_device_checker_init.speaker = {};
1100
+ }
1101
+ window.zbztAVSDK_device_checker_init.speaker.hasTest = true;
1102
+ window.zbztAVSDK_device_checker_init.speaker.list = speakerList;
1103
+ return speakerList;
1104
+ };
1105
+
1106
+ /**
1107
+ * @function 指定扬声器
1108
+ * @param deviceId:String 扬声器 id,必选
1109
+ * @param operationType:String 操作类型,可选
1110
+ * 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
1111
+ * 不传即是普通的设置扬声器设备的行为
1112
+ * @return Promise | void
1113
+ */
1114
+ export const setSpeakerDevice = async (args) => {
1115
+ defaultApi.writeLog(`${JSON.stringify(args)}----setSpeakerDevice-zego----`);
1116
+ // console.log('hsghsghsg999',args);
1117
+ let { deviceId, operationType, deviceState, code, changedDeviceId } = args;
1118
+ let deviceName = '';
1119
+ let speakerData;
1120
+ if (!deviceId) {
1121
+ speakerData = await getSpeakerDeviceList();
1122
+ // console.log('hsghsghsg0',speakerData.length);
1123
+ if (speakerData.length) {
1124
+ let hasGetSpeaker = false;
1125
+ // console.log('hsghsghsg1',hasGetSpeaker);
1126
+ for (let item of speakerData) {
1127
+ if (item.isDefault) {
1128
+ deviceId = item.deviceId;
1129
+ deviceName = item.deviceName;
1130
+ hasGetSpeaker = true;
1131
+ break;
1132
+ }
1133
+ }
1134
+ // console.log('hsghsghsg2',hasGetSpeaker);
1135
+ if (!hasGetSpeaker) {
1136
+ deviceId = speakerData[0].deviceId;
1137
+ deviceName = speakerData[0].deviceName;
1138
+ // console.log('hsghsghsg91',deviceId);
1139
+ }
1140
+ } else {
1141
+ deviceId = '';
1142
+ }
1143
+ if (deviceId === '') {
1144
+ NOTICE.noDevice({
1145
+ deviceType: 'speaker'
1146
+ });
1147
+ }
1148
+ }
1149
+ // console.log('hsghsghsg999',deviceId);
1150
+ try {
1151
+ dataReport.setDevice({
1152
+ device_type: 3,
1153
+ device_id: deviceId,
1154
+ device_name: deviceListReport.speakerList[deviceId],
1155
+ operationType,
1156
+ fore_state: operationType == 'hotPlug' ? deviceState + 1 : '-'
1157
+ });
1158
+ window.zbztAVSDK_device_checker_init.speaker.name = deviceListReport.speakerList[deviceId];
1159
+ } catch (e) { };
1160
+ usingAudioDeviceId.speaker = deviceId;
1161
+ await setAudioDevice(1, deviceId);
1162
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
1163
+ if (!speakerData) {
1164
+ speakerData = await getSpeakerDeviceList();
1165
+ deviceName = deviceListReport.speakerList[deviceId];
1166
+ }
1167
+ NOTICE[operationType]({
1168
+ deviceType: 'speaker',
1169
+ useDeviceId: deviceId,
1170
+ useDeviceName: deviceName,
1171
+ deviceList: speakerData,
1172
+ message: code,
1173
+ deviceState,
1174
+ changedDeviceId
1175
+ });
1176
+ }
1177
+ };
1178
+
1179
+ /**
1180
+ * @function 获取扬声器音量
1181
+ * @return Promise | void
1182
+ */
1183
+ export const getSpeakerDeviceVolume = () => {
1184
+ return callMethod('GetSpeakerDeviceVolume', {
1185
+ deviceId: usingAudioDeviceId.speaker
1186
+ });
1187
+ };
1188
+
1189
+ /**
1190
+ * @function 设置扬声器音量
1191
+ * @param volume:Number 扬声器音量,必选
1192
+ * @return Promise | void
1193
+ */
1194
+ export const setSpeakerDeviceVolume = (volume) => {
1195
+ return callMethod('SetSpeakerDeviceVolume', {
1196
+ deviceId: usingAudioDeviceId.speaker,
1197
+ volume
1198
+ });
1199
+ };
1200
+
1201
+ /**
1202
+ * @function 设置扬声器静音
1203
+ * @param mute:Boolean 必选
1204
+ * @return Promise | void
1205
+ */
1206
+ export const setSpeakerDeviceMute = (mute) => {
1207
+ // try {
1208
+ // dataReport.deviceChange({
1209
+ // device: 3,
1210
+ // device_state: mute ? 0 :1
1211
+ // });
1212
+ // } catch (e){};
1213
+ return callMethod('SetSpeakerDeviceMute', {
1214
+ deviceId: usingAudioDeviceId.speaker,
1215
+ mute
1216
+ });
1217
+ };
1218
+
1219
+ /**
1220
+ * @function 获取麦克风列表
1221
+ * @return Promise | void
1222
+ */
1223
+ export const getMicrophoneDeviceList = async () => {
1224
+ const defaultMicrophoneId = JSON.parse((await getDefaultMicrophone()).msg).ret.deviceId;
1225
+ let microphoneListArr = JSON.parse((await getAudioDeviceList(0)).msg).ret;
1226
+ let microphoneList = [];
1227
+ for (let i = 0, len = microphoneListArr.length; i < len; i++) {
1228
+ microphoneList.push({
1229
+ deviceId: microphoneListArr[i].szDeviceId,
1230
+ deviceName: microphoneListArr[i].szDeviceName,
1231
+ isDefault: defaultMicrophoneId === microphoneListArr[i].szDeviceId
1232
+ });
1233
+ deviceListReport.micList[microphoneListArr[i].szDeviceId] = microphoneListArr[i].szDeviceName;
1234
+
1235
+ }
1236
+ if (!window.zbztAVSDK_device_checker_init) {
1237
+ window.zbztAVSDK_device_checker_init = {};
1238
+ }
1239
+ if (!window.zbztAVSDK_device_checker_init.microphone) {
1240
+ window.zbztAVSDK_device_checker_init.microphone = {};
1241
+ }
1242
+ window.zbztAVSDK_device_checker_init.microphone.hasTest = true;
1243
+ window.zbztAVSDK_device_checker_init.microphone.list = microphoneList;
1244
+ return microphoneList;
1245
+ };
1246
+
1247
+ /**
1248
+ * @function 指定麦克风
1249
+ * @param deviceId:String 麦克风 id,必选
1250
+ * @param operationType:String 操作类型,可选
1251
+ * 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
1252
+ * 不传即是普通的设置麦克风设备的行为
1253
+ * @return Promise | void
1254
+ */
1255
+ export const setMicrophoneDevice = async (args) => {
1256
+ defaultApi.writeLog(`${JSON.stringify(args)}----setMicrophoneDevice-zego----`);
1257
+ let { deviceId, operationType, deviceState, code, changedDeviceId } = args;
1258
+ let deviceName = '';
1259
+ let microPhoneData;
1260
+ if (!deviceId) {
1261
+ microPhoneData = await getMicrophoneDeviceList();
1262
+ if (microPhoneData.length) {
1263
+ let hasGetMicrophone = false;
1264
+ for (let item of microPhoneData) {
1265
+ if (item.isDefault) {
1266
+ deviceId = item.deviceId;
1267
+ deviceName = item.deviceName;
1268
+ hasGetMicrophone = true;
1269
+ break;
1270
+ }
1271
+ }
1272
+ if (!hasGetMicrophone) {
1273
+ deviceId = microPhoneData[0].deviceId;
1274
+ deviceName = microPhoneData[0].deviceName;
1275
+ }
1276
+ } else {
1277
+ deviceId = '';
1278
+ }
1279
+ if (deviceId === '') {
1280
+ NOTICE.noDevice({
1281
+ deviceType: 'microphone'
1282
+ });
1283
+ }
1284
+ }
1285
+ try {
1286
+ dataReport.setDevice({
1287
+ device_type: 2,
1288
+ device_id: deviceId,
1289
+ device_name: deviceListReport.micList[deviceId],
1290
+ operationType,
1291
+ fore_state: operationType == 'hotPlug' ? deviceState + 1 : '-'
1292
+ });
1293
+ window.zbztAVSDK_device_checker_init.microphone.name = deviceListReport.micList[deviceId];
1294
+ } catch (e) { };
1295
+ usingAudioDeviceId.microphone = deviceId;
1296
+ await setAudioDevice(0, deviceId);
1297
+ await setAudioVolumeNotify(0, deviceId);
1298
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
1299
+ if (!microPhoneData) {
1300
+ microPhoneData = await getMicrophoneDeviceList();
1301
+ deviceName = deviceListReport.micList[deviceId];
1302
+ }
1303
+ NOTICE[operationType]({
1304
+ deviceType: 'microphone',
1305
+ useDeviceId: deviceId,
1306
+ useDeviceName: deviceName,
1307
+ deviceList: microPhoneData,
1308
+ message: code,
1309
+ deviceState,
1310
+ changedDeviceId
1311
+ });
1312
+ }
1313
+ };
1314
+
1315
+ /**
1316
+ * @function 获取麦克风音量
1317
+ * @return Promise | void
1318
+ */
1319
+ export const getMicDeviceVolume = () => {
1320
+ return callMethod('GetMicDeviceVolume', {
1321
+ deviceId: usingAudioDeviceId.microphone
1322
+ });
1323
+ };
1324
+
1325
+ /**
1326
+ * @function 设置麦克风音量
1327
+ * @param volume:Number 麦克风音量,必选
1328
+ * @return Promise | void
1329
+ */
1330
+ export const setMicDeviceVolume = (volume) => {
1331
+ return callMethod('SetMicDeviceVolume', {
1332
+ deviceId: usingAudioDeviceId.microphone,
1333
+ volume
1334
+ });
1335
+ };
1336
+
1337
+ /**
1338
+ * @function 设置麦克风静音
1339
+ * @param mute:Boolean 必选
1340
+ * @return Promise | void
1341
+ */
1342
+ export const setMicDeviceMute = (mute) => {
1343
+ return callMethod('SetMicDeviceMute', {
1344
+ deviceId: usingAudioDeviceId.microphone,
1345
+ mute
1346
+ });
1347
+ };
1348
+
1349
+ //设置采集扬声器声音
1350
+ export const setAudioSpeakerCapture = async (bEnable) => {
1351
+ return callMethod('EnableMixSystemPlayout', {
1352
+ bEnable,
1353
+ });
1354
+ };
1355
+
1356
+ // //采集扬声器
1357
+ // export const setAudioSpeakerCapture2 = async (bEnable) => {
1358
+ // return callMethod('MixEnginePlayout', {
1359
+ // bEnable,
1360
+ // });
1361
+ // };
1362
+
1363
+ /**
1364
+ * @function 获取当前应用程序音量
1365
+ * @return Promise | void
1366
+ */
1367
+ export const getSpeakerSimpleVolume = () => {
1368
+ return callMethod('GetSpeakerSimpleVolume', {
1369
+ deviceId: usingAudioDeviceId.speaker
1370
+ });
1371
+ };
1372
+
1373
+ /**
1374
+ * @function 设置视频预览载体 view
1375
+ * @param idx:Number 直播通道,可选,默认为 0
1376
+ * @return Promise | void
1377
+ */
1378
+ export const setPreviewView = (idx) => {
1379
+ if (typeof idx === 'undefined') {
1380
+ idx = 0;
1381
+ }
1382
+ return callMethod('SetPreviewView', {
1383
+ idx
1384
+ });
1385
+ };
1386
+
1387
+ /**
1388
+ * @function 设置本地预览视频视图的模式
1389
+ * @param mode:Number 模式,必选,0 | 1 | 2
1390
+ * 0:等比缩放,可能有黑边
1391
+ * 1:等比缩放填充整View,可能有部分被裁减
1392
+ * 2:填充整个View
1393
+ * @param idx:Number 直播通道,可选,默认为 0
1394
+ * @return Promise | void
1395
+ */
1396
+ export const setPreviewViewMode = (mode, idx) => {
1397
+ if (typeof idx === 'undefined') {
1398
+ idx = 0;
1399
+ }
1400
+ return callMethod('SetPreviewViewMode', {
1401
+ mode,
1402
+ idx
1403
+ });
1404
+ };
1405
+
1406
+ /**
1407
+ * @function 开启预览
1408
+ * @param idx:Number 推流通道,可选,默认为 0
1409
+ * @return Promise | void
1410
+ */
1411
+ export const startPreview = (idx) => {
1412
+ if (typeof idx === 'undefined') {
1413
+ idx = 0;
1414
+ }
1415
+ return callMethod('StartPreview', {
1416
+ idx
1417
+ });
1418
+ };
1419
+
1420
+ /**
1421
+ * @function 停止预览
1422
+ * @param idx:Number 推流通道,可选,默认为 0
1423
+ * @return Promise | void
1424
+ */
1425
+ export const stopPreview = (idx) => {
1426
+ if (typeof idx === 'undefined') {
1427
+ idx = 0;
1428
+ }
1429
+ return callMethod('StopPreview', {
1430
+ idx
1431
+ });
1432
+ };
1433
+
1434
+ /**
1435
+ * @function 设置当前应用程序音量
1436
+ * @param volume:Number 应用程序音量,必选
1437
+ * @return Promise | void
1438
+ */
1439
+ export const setSpeakerSimpleVolume = (volume) => {
1440
+ return callMethod('SetSpeakerSimpleVolume', {
1441
+ deviceId: usingAudioDeviceId.speaker,
1442
+ volume
1443
+ });
1444
+ };
1445
+
1446
+ /**
1447
+ * @function 设置当前应用程序静音
1448
+ * @param mute:Boolean 是否静音,必选
1449
+ * @return Promise | void
1450
+ */
1451
+ export const setSpeakerSimpleMute = (mute) => {
1452
+ return callMethod('SetSpeakerSimpleMute', {
1453
+ deviceId: usingAudioDeviceId.speaker,
1454
+ mute
1455
+ });
1456
+ };
1457
+
1458
+ /**
1459
+ * @function 开启本地或者远程的视频视图
1460
+ * @param isLocal:Boolean 是否是本地的视频预览,必选
1461
+ * @param streamId:String 要拉取的视频流的 id,可选,只有拉取远程的视频流的时候才是必选的
1462
+ * @param domId:String <video> 标签的 id,可选
1463
+ * 如果传了 domId,就把视频绑定到对应的 <video> 标签上
1464
+ * @return Promise 可从 Promise 中获取 src,Promise.then((src) => {})
1465
+ */
1466
+ export const startLocalOrRemotePreview = async (isLocal, streamId, domId, isTeacherNewWindowPreview) => {
1467
+ defaultApi.writeLog(`${streamId}----streamId-zego----`);
1468
+ let playChannel = null;
1469
+ let isUpdateChromeVersion = await util.getChromeVersion();
1470
+ // zego 的本地视频预览必须使用 -1 通道,为了与远程的视频预览兼容使用,此处需要判断是否是本地预览
1471
+ if (isLocal) {
1472
+ playChannel = -1;
1473
+ } else {
1474
+ playChannel = streamIdToPreviewId[streamId];
1475
+ }
1476
+ const externalConstraints = {
1477
+ audio: false,
1478
+ video: {
1479
+ mandatory: {
1480
+ chromeMediaSource: 'external',
1481
+ chromeMediaSourceId: `ems://zego/${isLocal || isTeacherNewWindowPreview ? -1 : streamId}`
1482
+ }
1483
+ }
1484
+ };
1485
+ defaultApi.writeLog(`avsdk ZEGO::startLocalOrRemotePreview streamId: ${streamId} uiChnIndex: ${playChannel}`);
1486
+
1487
+ return new Promise((resolve, reject) => {
1488
+ const handleExternalSuccess = (stream) => {
1489
+ defaultApi.writeLog(`${stream}----stream-zego----`);
1490
+ stream.oninactive = () => {
1491
+ defaultApi.writeLog('Stream inactive');
1492
+ };
1493
+ const src = isUpdateChromeVersion ? stream : window.URL.createObjectURL(stream);
1494
+ if (domId && document.querySelector(domId)) {
1495
+ if (isUpdateChromeVersion) {
1496
+ document.querySelector(domId).srcObject = src;
1497
+ } else {
1498
+ document.querySelector(domId).src = src;
1499
+ }
1500
+ }
1501
+ defaultApi.writeLog(`setVidoeSrc, streamId:${streamId}, domId: ${domId}, src: ${src}`);
1502
+ resolve(src);
1503
+ };
1504
+
1505
+ const handleExternalError = (error) => {
1506
+ if (error.name === 'ConstraintNotSatisfiedError') {
1507
+ console.error('ConstraintNotSatisfiedError');
1508
+ } else if (error.name === 'PermissionDeniedError') {
1509
+ console.error(
1510
+ 'Permissions have not been granted to use your camera and ' +
1511
+ 'microphone, you need to allow the page access to your devices in ' +
1512
+ 'order for the demo to work.'
1513
+ );
1514
+ }
1515
+ console.error(`getUserMedia error: ${error.name}`, error);
1516
+ if (domId) {
1517
+ document.querySelector(domId).src = '';
1518
+ }
1519
+ reject('');
1520
+ };
1521
+
1522
+ if (navigator.webkitGetUserMedia) {
1523
+ navigator.webkitGetUserMedia(
1524
+ externalConstraints,
1525
+ handleExternalSuccess,
1526
+ handleExternalError
1527
+ );
1528
+ }
1529
+ });
1530
+ };
1531
+
1532
+ /**
1533
+ * @function 设置本地预览以及推流的视频帧率
1534
+ * @param nFps:Number 帧率,必选
1535
+ * @param idx:Number 推流通道,可选,默认为 0
1536
+ * @return Promise | void
1537
+ */
1538
+ export const setVideoFPS = (nFps, idx) => {
1539
+ if (typeof idx === 'undefined') {
1540
+ idx = 0;
1541
+ }
1542
+ return callMethod('SetVideoFPS', {
1543
+ nFps,
1544
+ idx
1545
+ });
1546
+ };
1547
+
1548
+ /**
1549
+ * @function 设置本地预览以及推流的视频码率
1550
+ * @param nBitrate:Number 码率,必选
1551
+ * @param idx:Number 推流通道,可选,默认为 0
1552
+ * @return Promise | void
1553
+ */
1554
+ export const setVideoBitrate = (nBitrate, idx) => {
1555
+ if (typeof idx === 'undefined') {
1556
+ idx = 0;
1557
+ }
1558
+ return callMethod('SetVideoBitrate', {
1559
+ nBitrate,
1560
+ idx
1561
+ });
1562
+ };
1563
+
1564
+ /**
1565
+ * @function 设置本地预览以及推流的音频码率
1566
+ * @param bitrate:Number 码率,必选
1567
+ * @param idx:Number 推流通道,可选,默认为 0
1568
+ * @return Promise | void
1569
+ */
1570
+ export const setAudioBitrate = (bitrate, idx) => {
1571
+ if (typeof idx === 'undefined') {
1572
+ idx = 0;
1573
+ }
1574
+ return callMethod('SetAudioBitrate', {
1575
+ bitrate,
1576
+ idx
1577
+ });
1578
+ };
1579
+
1580
+ /**
1581
+ * @function 设置本地预览的视频分辨率
1582
+ * @param nWidth:Number 分辨率宽,必选
1583
+ * @param nHeight:Numnber 分辨率高,必选
1584
+ * @param idx:Number 推流通道,可选,默认为 0
1585
+ * @return Promise | void
1586
+ */
1587
+ export const setCameraParam = async (nWidth, nHeight, idx) => {
1588
+ defaultApi.writeLog(`avsdk ZEGO::setCameraParam ${nWidth}--${nHeight}`);
1589
+ await enableCamera(false);
1590
+ await setVideoCaptureResolution(nWidth, nHeight, idx);
1591
+ return enableCamera(true);
1592
+ };
1593
+
1594
+ /**
1595
+ * @function 设置本地预览的视频分辨率
1596
+ * @param nWidth:Number 分辨率宽,必选
1597
+ * @param nHeight:Numnber 分辨率高,必选
1598
+ * @param idx:Number 推流通道,可选,默认为 0
1599
+ * @return Promise | void
1600
+ */
1601
+ export const setVideoCaptureResolution = async (nWidth, nHeight, idx) => {
1602
+ if (typeof idx === 'undefined') {
1603
+ idx = 0;
1604
+ }
1605
+ await setCapturePipelineScaleMode();
1606
+ return callMethod('SetVideoCaptureResolution', {
1607
+ nWidth,
1608
+ nHeight,
1609
+ idx
1610
+ });
1611
+ };
1612
+
1613
+ export const setCapturePipelineScaleMode = () => {
1614
+ return callMethod('SetCapturePipelineScaleMode', {
1615
+ scaleMode: 1
1616
+ });
1617
+ };
1618
+
1619
+ /**
1620
+ * @function 设置推流的视频分辨率
1621
+ * @param nWidth:Number 分辨率宽,必选
1622
+ * @param nHeight:Numnber 分辨率高,必选
1623
+ * @param idx:Number 推流通道,可选,默认为 0
1624
+ * @return Promise | void
1625
+ */
1626
+ export const setVideoEncodeResolution = (nWidth, nHeight, idx) => {
1627
+ if (typeof idx === 'undefined') {
1628
+ idx = 0;
1629
+ }
1630
+ return callMethod('SetVideoEncodeResolution', {
1631
+ nWidth,
1632
+ nHeight,
1633
+ idx
1634
+ });
1635
+ };
1636
+
1637
+ /**
1638
+ * @function 初始化
1639
+ * @param args:Object
1640
+ * {
1641
+ * extensionVersion, // String,扩展版本号,必选
1642
+ * appId, // String,Zego 秘钥,必选
1643
+ * appSignature, // String,签名,必选
1644
+ * businessType, // Number,业务类型,必选
1645
+ * userId, // Number,用户 id,必选
1646
+ * userName, // String,用户名,必选
1647
+ * roomId, // String,频道(房间) id,必选
1648
+ * nNetType // Number,网络类型,可选,默认为 1
1649
+ * }
1650
+ * classMode 0:小组课及其他 1:小班课 2:组合小班课
1651
+ * @return Promise
1652
+ */
1653
+ export const init = async (args) => {
1654
+ defaultApi.writeLog(`avsdk ZEGO::init ${JSON.stringify(args)}`);
1655
+ currentRole = args.role;
1656
+ currentClassMode = args.classMode;
1657
+ currentGroupSdkType = args.sdkTypeGroup;
1658
+ localStreamId = args.streamId;
1659
+ await loadZego(args.extensionVersion);
1660
+ if (args.role === 'teacher' && args.mode === 1) {
1661
+ //坐立模式开启外部采集器,站立关闭外部采集器,只有小组课坐立模式才会调用,通过这个把rtmp数据给到zego或者rtc(头像),开启了外部采集,zego不会再本地采集数据
1662
+ await setVideoCaptureFactory(true);
1663
+ }
1664
+ // if (args.classMode === 1 || args.classMode === 2){
1665
+ // //如果是小班课保证关闭外部采集器,小组课上一步打开
1666
+ // await setVideoCaptureFactory(false);
1667
+ // };
1668
+ // 注册回调
1669
+ addListener(args.userId, args.userName, args.confId, args.nNetType, args.devices, args.role);
1670
+ //rtc同屏以及高光时刻,都开启音频外部采集,默认传1
1671
+ if (args.role === 'teacher') {
1672
+ defaultApi.writeLog('avsdk ZEGO::init_ open setAudioAuxSource');
1673
+ if (args.classMode === 1 || args.classMode === 2) {
1674
+ await setAudioAuxSource(1);
1675
+ }
1676
+ }
1677
+
1678
+ if (args.mode === 1 && ((isZegoGroupClass() && (args.role === 'teacher' || args.role === 'assistant')) || (isZegoCombinationClass() && args.role === 'assistant'))) {
1679
+ //zego推拉RTMP小组课,授课端坐立模式、辅导端坐立模式 或 zego推拉RTMP组合小班辅导端坐立模式,需要将摄像头渲染模式设置为 内部渲染+外部渲染
1680
+ await startEngine(args.appId, args.appSignature, args.businessType, 5); //5为摄像头内部渲染+外部渲染
1681
+ } else {
1682
+ await startEngine(args.appId, args.appSignature, args.businessType); //默认为摄像头外部渲染
1683
+ }
1684
+
1685
+ //小班课 需要加载采集插件的输入数据,为了拼接zego头像
1686
+ if ((args.classMode === 1 || args.classMode === 2) && args.role === 'teacher') {
1687
+ screenStreamId = `${window.zbzt_sdk_init_params.institutionId}_${args.roomId}_${args.userId}_${args.live_id}_1`;
1688
+ loadCollectionInputEntry();
1689
+ };
1690
+ if (args.noiseSuppressMode == -2) {
1691
+ defaultApi.writeLog(`noiseSuppressMode 关闭噪声消除 ${args.noiseSuppressMod}`);
1692
+ await setEnableNoiseSuppress(false);
1693
+ } else if (args.noiseSuppressMode == -1) {
1694
+ defaultApi.writeLog(`noiseSuppressMode 由底层进行配置,js层不进行配置 ${args.noiseSuppressMode}`);
1695
+ } else {
1696
+ defaultApi.writeLog(`noiseSuppressMode 启动噪音消除,模式为: ${args.noiseSuppressMode}`);
1697
+ await setEnableNoiseSuppress(true);
1698
+ await setNoiseSuppressMode(+args.noiseSuppressMode);
1699
+ await enableTransientNoiseSuppress(true);
1700
+ };
1701
+ //aecMode为-1是关闭回音消除,云控下传
1702
+ if (args.aecMode == -2) {
1703
+ defaultApi.writeLog(`aecMode 关闭回音消除 ${args.aecMode}`);
1704
+ await setEnableAEC(false);
1705
+ } else if (args.aecMode == -1) {
1706
+ defaultApi.writeLog(`aecMode 由底层进行配置,js层不进行配置 ${args.aecMode}`);
1707
+ } else {
1708
+ defaultApi.writeLog(`aecMode 启动回音消除,模式为: ${args.aecMode}`);
1709
+ await setEnableAEC(true);
1710
+ await setAECMode(+args.aecMode);
1711
+ };
1712
+ await setVideoBitrate(args.encodeCaptureBitrate);
1713
+ await setAudioBitrate(args.encodeCaptureBitrate);
1714
+ await setVideoFPS(args.encodeCaptureFps);
1715
+ await setVideoCaptureResolution(args.previewResolutionWidth, args.previewResolutionHeight);
1716
+ await setVideoEncodeResolution(args.encodedResolutionWidth, args.encodedResolutionHeight);
1717
+
1718
+ if ((isZegoGroupClass() && (args.role === 'teacher' || args.role === 'assistant')) || (isZegoCombinationClass() && args.role === 'assistant')) {
1719
+ defaultApi.writeLog('zego小组课或辅导端组合小班课,用第二路推RTMP流,在pyzx初始化采集参数');
1720
+ } else {
1721
+ await setVideoBitrate(args.screenSameBitrate,1);
1722
+ await setVideoFPS(args.screenSameFps, 1);
1723
+ await setVideoCaptureResolution(args.screenSameResolutionWidth, args.screenSameResolutionHeight, 1);
1724
+ await setVideoEncodeResolution(args.screenSameResolutionWidth, args.screenSameResolutionHeight, 1);
1725
+ }
1726
+
1727
+ // await setVideoBitrate(500000);
1728
+ // await setAudioBitrate(500000);
1729
+ // await setVideoFPS(15);
1730
+ // await setVideoCaptureResolution(1280, 720);
1731
+ // await setVideoEncodeResolution(1280, 720);
1732
+ await setSoundLevelMonitorCycle(500);
1733
+ if (isInitFinished) {
1734
+ defaultApi.writeLog(`avsdk ZEGO::init_isInitFinished ${isInitFinished}`);
1735
+ // await afterInitSDK(args.userId, args.userName, args.roomId, args.nNetType, JSON.parse(JSON.stringify(args.devices)));
1736
+ isInitFinished = 0;
1737
+ window.current_sdk_type = 'zego';
1738
+ defaultApi.writeLog('zego init finished current_sdk_type : zego');
1739
+ } else {
1740
+ await new Promise((resolve, reject) => {
1741
+ let timer = null;
1742
+ timer = setInterval(() => {
1743
+ if (isInitFinished) {
1744
+ isInitFinished = 0;
1745
+ clearInterval(timer);
1746
+ resolve();
1747
+ }
1748
+ }, 30);
1749
+ });
1750
+ window.current_sdk_type = 'zego';
1751
+ defaultApi.writeLog('zego init finished current_sdk_type : zego');
1752
+ }
1753
+ };
1754
+
1755
+ /**
1756
+ * @function 在OnInitSDK事件之后调用的初始化方法
1757
+ * @param userId:Number 用户 id,必选
1758
+ * @param userName:String 用户名,必选
1759
+ * @param roomId:String 频道(房间) id,必选
1760
+ * @param nNetType:Number 网络类型,可选,默认为 1
1761
+ * @return Promise
1762
+ */
1763
+ const afterInitSDK = async (userId, userName, confId, nNetType, devices, role, classMode) => {
1764
+ // 指定默认设备
1765
+ const usedDevices = window.zbztAVSDK_device_checker_init;
1766
+ const _devices = {
1767
+ camera: (devices && devices.camera) || (usedDevices && usedDevices.camera && usedDevices.camera.use) || '',
1768
+ microphone: (devices && devices.microphone) || (usedDevices && usedDevices.microphone && usedDevices.microphone.use) || '',
1769
+ speaker: (devices && devices.speaker) || (usedDevices && usedDevices.speaker && usedDevices.speaker.use) || ''
1770
+ };
1771
+ defaultApi.writeLog('avsdk ZEGO::afterInitSDK');
1772
+ await setDefaultDevice(_devices, 'default');
1773
+ await loginChannel(userId, userName, confId, nNetType);
1774
+ //设置拉流质量监控周期
1775
+ await setPlayQualityMoniterCycle(5000);
1776
+ await setPublishQualityMoniterCycle(5000);
1777
+ await setMediaSideFlags();
1778
+ defaultApi.writeLog(`test: isZegoGroupClass, ${isZegoGroupClass()}`);
1779
+ if ((isZegoGroupClass() && (role === 'teacher' || role === 'assistant')) || (isZegoCombinationClass() && role === 'assistant')) {
1780
+ defaultApi.writeLog(`avsdk ZEGO::afterInitSDK zegoRtmp, classMode: ${classMode} role: ${role}`);
1781
+ } else {
1782
+ // 初始化的时候不打开摄像头
1783
+ await enableCamera(false);
1784
+ // 只有调用了这个方法之后才开启关闭摄像头才有效
1785
+ await startPreview();
1786
+ }
1787
+ // 置为 1 表示初始化完成
1788
+ isInitFinished = 1;
1789
+ };
1790
+
1791
+ const deviceCheckerInitSDK = async () => {
1792
+ defaultApi.writeLog('avsdk ZEGO::deviceCheckerInitSDK');
1793
+ await enableCamera(false);
1794
+ await startPreview();
1795
+ isDeviceCheckInitFinished = 1;
1796
+ };
1797
+
1798
+ const getDeviceCheckInitStatus = () => {
1799
+ return isDeviceCheckInitFinished;
1800
+ };
1801
+
1802
+ const setDeviceCheckInitStatus = () => {
1803
+ isDeviceCheckInitFinished = 0;
1804
+ }
1805
+
1806
+ //设置是否发送sei
1807
+ const setMediaSideFlags = (bStart = true, bOnlyAudioPublish = false, mediaInfoType = 2, seiSendType = 1, idx = 0) => {
1808
+ return callMethod('SetMediaSideFlags', { bStart, bOnlyAudioPublish, mediaInfoType, seiSendType, idx });
1809
+ };
1810
+ //设置拉流质量监控周期
1811
+ const setPlayQualityMoniterCycle = (timeInMS) => {
1812
+ return callMethod('SetPlayQualityMoniterCycle', { timeInMS });
1813
+ };
1814
+
1815
+ //设置推流质量监控周期
1816
+ const setPublishQualityMoniterCycle = (timeInMS) => {
1817
+ return callMethod('SetPublishQualityMoniterCycle', { timeInMS });
1818
+ };
1819
+
1820
+ /**
1821
+ * @function 设置默认的硬件设备,包括摄像头、麦克风以及扬声器
1822
+ * @return Promise
1823
+ */
1824
+ export const setDefaultDevice = async (devices, operationType) => {
1825
+ // 设置默认的摄像头
1826
+ if (devices && devices.camera) {
1827
+ if (zbztAVSDK_device_checker_init.camera.list.length == 0) {
1828
+ await getVideoDeviceList();
1829
+ }
1830
+ await setVideoDevice({ deviceId: devices.camera, operationType: `${operationType}_1` });
1831
+ } else {
1832
+ const cameraData = await getVideoDeviceList();
1833
+ if (cameraData.length) {
1834
+ let hasSetCamera = false;
1835
+ for (let item of cameraData) {
1836
+ if (item.isDefault) {
1837
+ await setVideoDevice({ deviceId: item.deviceId, operationType: `${operationType}_2` });
1838
+ hasSetCamera = true;
1839
+ break;
1840
+ }
1841
+ }
1842
+ if (!hasSetCamera) {
1843
+ await setVideoDevice({ deviceId: cameraData[0].deviceId, operationType: `${operationType}_3` });
1844
+ }
1845
+ }
1846
+ }
1847
+ // 设置默认的麦克风
1848
+ if (devices && devices.microphone) {
1849
+ if (zbztAVSDK_device_checker_init.microphone.list.length == 0) {
1850
+ await getMicrophoneDeviceList();
1851
+ }
1852
+ await setMicrophoneDevice({ deviceId: devices.microphone, operationType: `${operationType}_1` });
1853
+ } else {
1854
+ const microPhoneData = await getMicrophoneDeviceList();
1855
+ if (microPhoneData.length) {
1856
+ let hasSetMicrophone = false;
1857
+ for (let item of microPhoneData) {
1858
+ if (item.isDefault) {
1859
+ await setMicrophoneDevice({ deviceId: item.deviceId, operationType: `${operationType}_2` });
1860
+ hasSetMicrophone = true;
1861
+ break;
1862
+ }
1863
+ }
1864
+ if (!hasSetMicrophone) {
1865
+ await setMicrophoneDevice({ deviceId: microPhoneData[0].deviceId, operationType: `${operationType}_3` });
1866
+ }
1867
+ }
1868
+ }
1869
+ // 设置默认的扬声器
1870
+ if (devices && devices.speaker) {
1871
+ await setSpeakerDevice({ deviceId: devices.speaker, operationType: `${operationType}_1` });
1872
+ } else {
1873
+ const speakerData = await getSpeakerDeviceList();
1874
+ if (speakerData.length) {
1875
+ let hasSetSpeaker = false;
1876
+ for (let item of speakerData) {
1877
+ if (item.isDefault) {
1878
+ await setSpeakerDevice({ deviceId: item.deviceId, operationType: `${operationType}_2` });
1879
+ hasSetSpeaker = true;
1880
+ break;
1881
+ }
1882
+ }
1883
+ if (!hasSetSpeaker) {
1884
+ await setSpeakerDevice({ deviceId: speakerData[0].deviceId, operationType: `${operationType}_3` });
1885
+ }
1886
+ }
1887
+ }
1888
+ };
1889
+
1890
+ /**
1891
+ * @function 开始推流
1892
+ * @param title:String 直播的名称,可选,默认为 ''
1893
+ * @param flag:Number 直播属性,可选,默认为 0
1894
+ * @param seq:Number 请求序号,可选,默认为 0
1895
+ * @param idx:Number 推流通道,可选,默认为 0
1896
+ * @return Promise | void
1897
+ */
1898
+ export const startPublish2 = async (streamid, idx, title, flag, seq) => {
1899
+ const streamId = streamid || window.zbztAVSDK_init_params.zego.streamId;
1900
+ if (typeof title === 'undefined') {
1901
+ title = 'none';
1902
+ }
1903
+ if (typeof flag === 'undefined') {
1904
+ flag = 0;
1905
+ }
1906
+ if (typeof seq === 'undefined') {
1907
+ seq = 0;
1908
+ }
1909
+ if (typeof idx === 'undefined') {
1910
+ idx = 0;
1911
+ }
1912
+ await new Promise((resolve, reject) => {
1913
+ let timer = setInterval(() => {
1914
+ if (hasLoginChannel) {
1915
+ clearInterval(timer);
1916
+ resolve();
1917
+ }
1918
+ }, 30);
1919
+ });
1920
+ let res = await callMethod('StartPublish2', {
1921
+ pszStreamID: streamId,
1922
+ pszTitle: title,
1923
+ seq,
1924
+ idx,
1925
+ flag
1926
+ });
1927
+ await startSoundLevelMonitor();
1928
+ await new Promise((resolve, reject) => {
1929
+ let timer = setInterval(() => {
1930
+ if (hasPushFlow) {
1931
+ clearInterval(timer);
1932
+ resolve();
1933
+ }
1934
+ }, 300);
1935
+ });
1936
+ // 心跳开始
1937
+ if (!isFirstHeartBeatReport) {
1938
+ isFirstHeartBeatReport = true;
1939
+ heartBeatDataReport('start');
1940
+ }
1941
+ return res;
1942
+ };
1943
+
1944
+ /**
1945
+ * @function 结束推流
1946
+ * @param msg:String 自定义信息,server 对接流结束回调包含此字段内容,可选,默认为 'none'
1947
+ * @param flag:Number 直播属性,可选,默认为 0
1948
+ * @param idx:Number 推流通道,可选,默认为 0
1949
+ * @return Promise | void
1950
+ */
1951
+ export const stopPublish = (idx, msg, flag) => {
1952
+ if (typeof msg === 'undefined') {
1953
+ msg = 'none';
1954
+ }
1955
+ if (typeof flag === 'undefined') {
1956
+ flag = 0;
1957
+ }
1958
+ if (typeof idx === 'undefined') {
1959
+ idx = 0;
1960
+ }
1961
+ // try {
1962
+ // dataReport.stopPublish({publish_streamid:window.zbztAVSDK_init_params.zego.streamId});
1963
+ // } catch (error) {}
1964
+ return callMethod('StopPublish', {
1965
+ pszMsg: msg,
1966
+ flag,
1967
+ idx
1968
+ });
1969
+ };
1970
+
1971
+ /**
1972
+ * @function 初始化拉流
1973
+ * @param streamId:String 从传来的信道消息中获取,必选
1974
+ * @param domId:String <video> 标签的 id,可选
1975
+ * 如果传了就把视频绑定到对应的 <video> 标签上
1976
+ * @param pInfo:String 多媒体流附加信息,可选,默认为 'none'
1977
+ * @return src:String 视频预览地址
1978
+ */
1979
+ export const initPullFlow = async (streamId, domId, mute, pInfo, notAutoPlay, audioOnly) => {
1980
+ defaultApi.writeLog(`ZEGO:: initPullFlow_start ,streamId :${streamId}`);
1981
+ let playChannel;
1982
+ resetStreamIdRtcPlayerInfo1(streamId);
1983
+ resetStreamIdRtcPlayerInfo(streamId);
1984
+ try {
1985
+ if (!isFirstHeartBeatReport) {
1986
+ isFirstHeartBeatReport = true;
1987
+ heartBeatDataReport('start');
1988
+ }
1989
+ } catch (error) { }
1990
+ if (streamIdToPreviewId[streamId] == undefined) {
1991
+ // if (typeof zegoCallback === 'function' && uiChnIndexs.length === 0) {
1992
+ // zegoCallback({
1993
+ // type: 'over_max_connect',
1994
+ // data: {
1995
+ // message: 'ZEGO:: all uiChnIndexs are used'
1996
+ // }
1997
+ // });
1998
+ // }
1999
+ defaultApi.writeLog(`ZEGO:: The streamId queue does not contain this streamId ${uiChnIndexs}`);
2000
+ if (uiChnIndexs.length === 0) {
2001
+ NOTICE.overMaxConnect();
2002
+ defaultApi.writeLog('error', `ZEGO:: all uiChnIndexs are used ${uiChnIndexs}`);
2003
+ return {
2004
+ videoSrc: '',
2005
+ playerId: -2
2006
+ };
2007
+ }
2008
+ playChannel = uiChnIndexs.pop();
2009
+ streamIdToPreviewId[streamId] = playChannel;
2010
+ defaultApi.writeLog(`streamIdIsNoExited ${playChannel} ${uiChnIndexs}`);
2011
+ } else {
2012
+ playChannel = streamIdToPreviewId[streamId];
2013
+ defaultApi.writeLog(`ZEGO:: The streamId queue contains this streamId ${playChannel} ${uiChnIndexs}`);
2014
+ await stopPlayStream(streamId);
2015
+ resetStreamIdRtcPlayerInfo(streamId);
2016
+ }
2017
+ // 判断是否创建或者获取播放通道成功,不成功就删掉重试
2018
+ if (playChannel == undefined) {
2019
+ delete streamIdToPreviewId[streamId];
2020
+ defaultApi.writeLog('error', 'ZEGO:: uiChnIndex is not exist');
2021
+ // delete streamIdToBlobUrl[streamId];
2022
+ return initPullFlow(streamId, domId, mute, pInfo, notAutoPlay, audioOnly);
2023
+ }
2024
+ previewIdToStreamId[playChannel] = streamId;
2025
+ //是否拉取声音
2026
+ activateAudioPlayStream(streamId, !!!mute);
2027
+ //是否拉取画面
2028
+ activateVideoPlayStream(streamId, !!!audioOnly);
2029
+ if (!notAutoPlay) {
2030
+ await playStream(streamId, playChannel, pInfo);
2031
+ }
2032
+ const videoSrc = await startLocalOrRemotePreview(false, streamId, domId);
2033
+ return {
2034
+ videoSrc,
2035
+ playerId: playChannel
2036
+ };
2037
+ };
2038
+
2039
+ /**
2040
+ * @function 恢复拉指定的流
2041
+ * @param streamId:String 被拉取的流的 id,必选
2042
+ * @param uiChnIndex:Number 播放通道,可选
2043
+ * @param pInfo:String 多媒体流附加信息,可选,默认为 'none'
2044
+ * @return Promise | void
2045
+ */
2046
+ export const playStream = (streamId, uiChnIndex, pInfo) => {
2047
+ if (typeof uiChnIndex === 'undefined') {
2048
+ uiChnIndex = streamIdToPreviewId[streamId];
2049
+ }
2050
+ if (typeof pInfo === 'undefined') {
2051
+ pInfo = 'none';
2052
+ }
2053
+ defaultApi.writeLog(`avsdk ZEGO::PlayStream streamId: ${streamId} uiChnIndex: ${uiChnIndex}`);
2054
+ return callMethod('PlayStream', {
2055
+ pszStreamID: streamId,
2056
+ uiChnIndex,
2057
+ pInfo
2058
+ });
2059
+ };
2060
+
2061
+ /**
2062
+ * @function 停止拉指定的流
2063
+ * @param streamId:String 被拉取的流的 id,必选
2064
+ * @param recovery:Boolean 是否回收播放器, 可选
2065
+ * @return Promise | void
2066
+ */
2067
+ export const stopPlayStream = async (streamId, recovery) => {
2068
+ const id = streamIdToPreviewId[streamId];
2069
+ delete streamIdRtcPlayerInfo[streamId];
2070
+ if (recovery && id && !uiChnIndexs.includes(id)) {
2071
+ uiChnIndexs.push(id);
2072
+ defaultApi.writeLog(`avsdk ZEGO::stopPlayStream streamId: ${streamId} id: ${id} uiChnIndexs: ${uiChnIndexs}`);
2073
+ delete streamIdToPreviewId[streamId];
2074
+ // delete streamIdToBlobUrl[streamId];
2075
+ }
2076
+ return callMethod('StopPlayStream', {
2077
+ pszStreamID: streamId
2078
+ });
2079
+ };
2080
+
2081
+ /**
2082
+ * @function 停止并回收所有拉流
2083
+ * @return Promise | void
2084
+ */
2085
+ export const stopAllPlayStream = () => {
2086
+ const toRecoveryArr = [];
2087
+ for (let streamId in streamIdToPreviewId) {
2088
+ if (streamIdToPreviewId.hasOwnProperty(streamId)) {
2089
+ const id = streamIdToPreviewId[streamId];
2090
+ if (id && !uiChnIndexs.includes(id)) {
2091
+ uiChnIndexs.push(id);
2092
+ toRecoveryArr.push(callMethod('StopPlayStream', {
2093
+ pszStreamID: streamId
2094
+ }));
2095
+ }
2096
+ }
2097
+ }
2098
+ defaultApi.writeLog(`avsdk ZEGO::stopAllPlayStream uiChnIndexs: ${uiChnIndexs}`);
2099
+ streamIdToPreviewId = {};
2100
+ return Promise.all(toRecoveryArr);
2101
+ };
2102
+
2103
+ /**
2104
+ * @function 切换播放流
2105
+ * @param streamId:String 需要停止流的 id,必选
2106
+ * @param toStreamId:String 被拉取的流的 id,必选
2107
+ * @param toDomId:String <video> 标签的 id,可选
2108
+ * @return Promise | void
2109
+ */
2110
+ export const changePullFlow = async (streamId, toStreamId, toDomId) => {
2111
+ await stopPlayStream(streamId, true);
2112
+ return initPullFlow(toStreamId, toDomId);
2113
+ };
2114
+
2115
+ /**
2116
+ * @function 转推,录课
2117
+ * @param type:String 必选,'start' | 'stop'
2118
+ * @param seq:Number 可选,默认为 1
2119
+ * @return Promise | void
2120
+ */
2121
+ export const mixStream = (type, args, seq) => {
2122
+ if (!args) {
2123
+ const zego = window.zbztAVSDK_init_params.zego;
2124
+ const streamId = zego.streamId;
2125
+ const sid = zego.sid;
2126
+ let pInputStreamList;
2127
+ let nInputStreamCount;
2128
+ if (type === 'start') {
2129
+ pInputStreamList = [{
2130
+ szStreamID: streamId,
2131
+ layout: {
2132
+ top: 0,
2133
+ right: zego.previewResolutionWidth,
2134
+ bottom: zego.previewResolutionHeight,
2135
+ left: 0
2136
+ },
2137
+ uSoundLevelID: 0,
2138
+ nContentControl: 0
2139
+ }];
2140
+ nInputStreamCount = 1;
2141
+ }
2142
+ if (type === 'stop') {
2143
+ pInputStreamList = [];
2144
+ nInputStreamCount = 0;
2145
+ }
2146
+ if (typeof seq === 'undefined') {
2147
+ seq = 1;
2148
+ }
2149
+
2150
+ return callMethod('MixStream', {
2151
+ config: {
2152
+ szOutputStream: zego.recordUrl + '/' + sid,
2153
+ bOutputIsUrl: true,
2154
+ nOutputFps: zego.previewCaptureFps,
2155
+ nOutputBitrate: zego.previewCaptureBitrate,
2156
+ nOutputAudioBitrate: zego.previewCaptureBitrate,
2157
+ nOutputWidth: zego.previewResolutionWidth,
2158
+ nOutputHeight: zego.previewResolutionHeight,
2159
+ nOutputAudioConfig: 1,
2160
+ pInputStreamList,
2161
+ nInputStreamCount,
2162
+ pUserData: '',
2163
+ nLenOfUserData: 0,
2164
+ nChannels: 0,
2165
+ nOutputBackgroundColor: 0,
2166
+ pOutputBackgroundImage: '',
2167
+ bWithSoundLevel: false
2168
+ },
2169
+ seq
2170
+ });
2171
+ } else {
2172
+ return callMethod('MixStream', args);
2173
+ }
2174
+
2175
+ };
2176
+
2177
+ /**
2178
+ * @function 是否拉取音频流--通过流id控制
2179
+ * @param streamId:String 被拉取的流的 id,必选
2180
+ * @param bActive:Boolean true -> 拉取,false -> 不拉取,必选
2181
+ * @return Promise | void
2182
+ */
2183
+ export const activateAudioPlayStream = (streamId, bActive) => {
2184
+ streamIdRtcPlayerInfo1[streamId].audio_type = bActive;
2185
+ return callMethod('ActivateAudioPlayStream', {
2186
+ nChannelIdx: streamIdToPreviewId[streamId],
2187
+ bActive
2188
+ });
2189
+ };
2190
+
2191
+ /**
2192
+ * @function 是否拉取音频流--通过播放器id控制
2193
+ * @param operation:Boolean,必选,true -> 拉取,false -> 不拉取,必选
2194
+ * @param playerId:Number,必选,播放器id
2195
+ * @return Promise | void
2196
+ */
2197
+ export const pullAudioFlow = (playerId, operation, streamid) => {
2198
+ defaultApi.writeLog(`pullAudioFlow -- playerId ${playerId} operation ${operation} streamId ${streamid}`);
2199
+ if (streamid) {
2200
+ if (streamIdToPreviewId[streamid] == undefined) {
2201
+ NOTICE.pullAudioFlowError({ streamid })
2202
+ return;
2203
+ } else {
2204
+ playerId = streamIdToPreviewId[streamid]
2205
+ defaultApi.writeLog(`pullAudioFlow-playerId ${playerId}`);
2206
+ }
2207
+ }
2208
+ let streamId = previewIdToStreamId[playerId];
2209
+ try {
2210
+ streamIdRtcPlayerInfo1[streamId].audio_type = operation;
2211
+ defaultApi.writeLog(`pullAudioFlow ${streamId}`);
2212
+ } catch (e) {
2213
+ defaultApi.writeLog(`pullAudioFlow ${streamId} --error ${JSON.stringify(e)}`, null, 'error');
2214
+ }
2215
+ try {
2216
+ dataReport.setPullVoice({
2217
+ code: +operation,
2218
+ pull_uid: util.getUidByStreamId(streamId),
2219
+ pull_streamid: streamId,
2220
+ playerId
2221
+ // operator:'client'
2222
+ });
2223
+ } catch (e) { };
2224
+ return callMethod('ActivateAudioPlayStream', {
2225
+ bActive: operation,
2226
+ nChannelIdx: playerId
2227
+ });
2228
+ };
2229
+
2230
+ /**
2231
+ * @function 是否拉取画面流
2232
+ * @param streamId:String 被拉取的流的 id,必选
2233
+ * @param bActive:Boolean true -> 拉取,false -> 不拉取,必选
2234
+ * @return Promise | void
2235
+ */
2236
+ export const activateVideoPlayStream = (streamId, bActive) => {
2237
+ try {
2238
+ streamIdRtcPlayerInfo1[streamId].video_type = bActive;
2239
+ defaultApi.writeLog(`'activateVideoPlayStream ${streamId}`);
2240
+ } catch (e) {
2241
+ defaultApi.writeLog(`activateVideoPlayStream ${streamId} --error ${JSON.stringify(e)}`, null, 'error');
2242
+ }
2243
+ return callMethod('ActivateVideoPlayStream', {
2244
+ nChannelIdx: streamIdToPreviewId[streamId],
2245
+ bActive
2246
+ });
2247
+ };
2248
+
2249
+ /**
2250
+ * @function 开启/关闭麦克风音量回调
2251
+ * @param open:Boolean true -> 开启,false -> 关闭,必选
2252
+ * @return void
2253
+ */
2254
+ export const openMicVolumeCb = (open) => {
2255
+ // if (open) {
2256
+ // runMicVolumeCb = true;
2257
+ // } else {
2258
+ // runMicVolumeCb = false;
2259
+ // }
2260
+ };
2261
+
2262
+ /**
2263
+ * @function 监听设备的音量变化
2264
+ * @param deviceType:Number 音频设备类型,0 -> 麦克风,1 -> 扬声器,必选
2265
+ * @param deviceId:String 音频设备 id,必选
2266
+ * @return Promise | void
2267
+ */
2268
+ export const setAudioVolumeNotify = (deviceType, deviceId) => {
2269
+ return callMethod('SetAudioVolumeNotify', {
2270
+ deviceType,
2271
+ deviceId
2272
+ });
2273
+ };
2274
+
2275
+ /**
2276
+ * @function 关闭监听设备的音量变化
2277
+ * @param deviceType:Number 音频设备类型,0 -> 麦克风,1 -> 扬声器,必选
2278
+ * @param deviceId:String 音频设备 id,必选
2279
+ * @return Promise | void
2280
+ */
2281
+ export const stopAudioVolumeNotify = (deviceType, deviceId) => {
2282
+ return callMethod('StopAudioVolumeNotify', {
2283
+ deviceType,
2284
+ deviceId
2285
+ });
2286
+ };
2287
+
2288
+ /**
2289
+ * @function 启动 soundLevel 监听
2290
+ * StartSoundLevelMonitor 后一定要 StopSoundLevelMonitor
2291
+ * @return Promise | void
2292
+ */
2293
+ export const startSoundLevelMonitor = () => {
2294
+ return callMethod('StartSoundLevelMonitor', {});
2295
+ };
2296
+
2297
+ /**
2298
+ * @function 停止 soundLevel 监听
2299
+ * @return Promise | void
2300
+ */
2301
+ export const stopSoundLevelMonitor = () => {
2302
+ return callMethod('StopSoundLevelMonitor', {});
2303
+ };
2304
+
2305
+ /**
2306
+ * @function 设置 soundLevel 的监控周期
2307
+ * @param timeInMS:Number 时间周期,单位为毫秒,取值范围 [100, 3000],必选
2308
+ * @return Promise | void
2309
+ */
2310
+ export const setSoundLevelMonitorCycle = (timeInMS) => {
2311
+ return callMethod('SetSoundLevelMonitorCycle', {
2312
+ timeInMS
2313
+ });
2314
+ };
2315
+
2316
+ /**
2317
+ * @function 单路录制
2318
+ * @param type:String start/stop,必选
2319
+ * @param szOutputStream:转推地址(支持rtmp/avertp),必选
2320
+ * @param szStreamID:推流ID,必选
2321
+ * @return Promise | void
2322
+ */
2323
+ /*export const singleRecord = async (type, szOutputStream, szStreamID, seq = 1) => {
2324
+ defaultApi.writeLog(`avsdk ZEGO::singleRecord szStreamID: ${szStreamID} szOutputStream: ${szOutputStream} type: ${type}`);
2325
+ const zego = window.zbztAVSDK_init_params.zego;
2326
+ let pInputStreamList = [];
2327
+ let nInputStreamCount = 0;
2328
+ if (type === 'start') {
2329
+ pInputStreamList = [{
2330
+ szStreamID,
2331
+ layout: {
2332
+ top: 0,
2333
+ right: zego.previewResolutionWidth,
2334
+ bottom: zego.previewResolutionHeight,
2335
+ left: 0
2336
+ },
2337
+ uSoundLevelID: 0,
2338
+ nContentControl: 0
2339
+ }];
2340
+ nInputStreamCount = 1;
2341
+ }
2342
+ return callMethod('MixStream', {
2343
+ config: {
2344
+ szOutputStream,
2345
+ bOutputIsUrl: true,
2346
+ nOutputFps: zego.previewCaptureFps,
2347
+ nOutputBitrate: zego.previewCaptureBitrate,
2348
+ nOutputAudioBitrate: zego.previewCaptureBitrate,
2349
+ nOutputWidth: zego.previewResolutionWidth,
2350
+ nOutputHeight: zego.previewResolutionHeight,
2351
+ nOutputAudioConfig: 1,
2352
+ pInputStreamList,
2353
+ nInputStreamCount,
2354
+ pUserData: '',
2355
+ nLenOfUserData: 0,
2356
+ nChannels: 0,
2357
+ nOutputBackgroundColor: 0,
2358
+ pOutputBackgroundImage: '',
2359
+ bWithSoundLevel: false
2360
+ },
2361
+ seq
2362
+ });
2363
+ };
2364
+ */
2365
+ export const hasStream = streamId => {
2366
+ return Object.keys(streamIdToPreviewId).includes(streamId);
2367
+ };
2368
+
2369
+ /**
2370
+ * @function 获取当前视频流的通道
2371
+ * @param streamId 流 id
2372
+ * @return channelIndex
2373
+ */
2374
+ export const getChannelIndex = (streamId) => {
2375
+ defaultApi.writeLog(`ZEGO : getChannelIndex streamId: ${streamId} ${JSON.stringify(streamIdToPreviewId)}`);
2376
+ return streamIdToPreviewId[streamId];
2377
+ };
2378
+
2379
+ /**
2380
+ * @function 获取当前视频流所有的通道
2381
+ * @param streamId 流 id
2382
+ * @return channelIndex
2383
+ */
2384
+ export const getAllChannelIndex = () => {
2385
+ defaultApi.writeLog(`ZEGO : getAllChannelIndex ${JSON.stringify(streamIdToPreviewId)}`);
2386
+ return streamIdToPreviewId;
2387
+ };
2388
+
2389
+
2390
+ /**
2391
+ * @function 录制转推对外接口
2392
+ * @param type:String start/stop,必选
2393
+ * @param szOutputStream:转推地址(支持rtmp/avertp),必选
2394
+ * @param szStreamID:推流ID,必选
2395
+ * @return Promise | void
2396
+ */
2397
+ export const singleRecord = async (type, szOutputStream, szStreamID) => {
2398
+ defaultApi.writeLog(`avsdk ZEGO::recordPublishTarget szStreamID: ${szStreamID} szOutputStream: ${szOutputStream} type: ${type}`);
2399
+ const zego = window.zbztAVSDK_init_params.zego;
2400
+ if (!szOutputStream) {
2401
+ const sid = zego.sid;
2402
+ // 拼接转推地址
2403
+ szOutputStream = zego.recordUrl + '/' + sid;
2404
+ }
2405
+ if (!szStreamID) {
2406
+ szStreamID = window.zbztAVSDK_init_params.zego.streamId;
2407
+ }
2408
+ if (type === 'start') {
2409
+ return addPublishTarget(szOutputStream, szStreamID);
2410
+ }
2411
+ if (type === 'stop') {
2412
+ return deletePublishTarget(szOutputStream, szStreamID);
2413
+ }
2414
+ };
2415
+
2416
+ /**
2417
+ * @function 开始转推
2418
+ * @param szTarget:转推地址(支持rtmp/avertp),必选
2419
+ * @param szStreamID:推流ID,必选
2420
+ * @return Promise | void
2421
+ */
2422
+ export const addPublishTarget = async (szTarget, szStreamID) => {
2423
+ defaultApi.writeLog(`avsdk ZEGO::addPublishTarget szStreamID: ${szStreamID} szTarget: ${szTarget}`);
2424
+ let res = await callMethod('AddPublishTarget', {
2425
+ strTarget: szTarget,
2426
+ pszStreamID: szStreamID,
2427
+ });
2428
+ try {
2429
+ dataReport.turnPushResult({
2430
+ errorcode: res == 0 ? 0 : 1,
2431
+ case: 'turn push',
2432
+ streamid: szStreamID
2433
+ });
2434
+ } catch (e) { };
2435
+ return res;
2436
+ };
2437
+
2438
+ /**
2439
+ * @function 结束转推
2440
+ * @param szTarget:转推地址(支持rtmp/avertp),必选
2441
+ * @param szStreamID:推流ID,必选
2442
+ * @param seqNum
2443
+ * @return Promise | void
2444
+ */
2445
+ export const deletePublishTarget = async (szTarget, szStreamID) => {
2446
+ defaultApi.writeLog(`avsdk ZEGO::deletePublishTarget szStreamID: ${szStreamID} szTarget: ${szTarget}`);
2447
+ return callMethod('DeletePublishTarget', {
2448
+ strTarget: szTarget,
2449
+ pszStreamID: szStreamID
2450
+ });
2451
+ };
2452
+
2453
+ /**
2454
+ * @function 开始本地视频录制
2455
+ * @param enableRecord 开始/结束
2456
+ * @param storagePath 录制路径
2457
+ * @return Promise | void
2458
+ */
2459
+ export const localRecordVideo = async (enableRecord, storagePath) => {
2460
+ defaultApi.writeLog(`avsdk ZEGO::localRecordVideo enableRecord: ${enableRecord}, storagePath: ${storagePath}`);
2461
+ if (enableRecord) {
2462
+ return callMethod('StartRecord', {
2463
+ channelIndex: 0,
2464
+ recordType: 3,
2465
+ enableStatusCallback: true,
2466
+ interval: 3000,
2467
+ recordFormat: 2,
2468
+ isFragment: false,
2469
+ storagePath
2470
+ });
2471
+ } else {
2472
+ return callMethod('StopRecord', {
2473
+ channelIndex: 0
2474
+ });
2475
+ }
2476
+ };
2477
+
2478
+ /**
2479
+ * @function 本地音频录制
2480
+ * @param enableRecord 开始/结束
2481
+ * @param storagePath 录制路径
2482
+ * @return Promise | void
2483
+ */
2484
+ export const localRecordAudio = async (enableRecord, storagePath) => {
2485
+ defaultApi.writeLog(`avsdk ZEGO::localRecordAudio enableRecord: ${enableRecord}, storagePath: ${storagePath}`);
2486
+ return callMethod('EnableSelectedAudioRecord', {
2487
+ uMask: 1,
2488
+ nSampleRate: 16000,
2489
+ nChannels: 1,
2490
+ enableRecord,
2491
+ storagePath,
2492
+ });
2493
+ };
2494
+ /**
2495
+ * @function 本地录制
2496
+ * @param {string | undefined} fileName
2497
+ * @param {number} fileType 1:flv 2:mp4
2498
+ * @param {number} idx 0:主流 1:辅流 2:RTMP流
2499
+ * @returns {Promise<any>}
2500
+ */
2501
+ export const startRecord = async (fileName, fileType, idx) => {
2502
+ defaultApi.writeLog(`avsdk ZEGO::startRecord fileName: ${fileName}, fileType: ${fileType}, idx: ${idx}`);
2503
+ if (idx === 1 && !screenStreamId) {
2504
+ defaultApi.writeLog('avsdk ZEGO::startRecord screenStreamId is null', null, 'error');
2505
+ return;
2506
+ }
2507
+ if (!fileName) {
2508
+ const fileNameMap = [localStreamId, screenStreamId, 'rtmp'];
2509
+ fileName = `${fileNameMap[idx]}-${util.currentTimeString().replace(/:/g, '-')}`;
2510
+ }
2511
+ dataReport.startRecord({fileName, fileType, idx});
2512
+ return callMethod('StartRecord', {
2513
+ idx,
2514
+ recordType: 3, // 1:音频 2:视频 3:音视频
2515
+ fileName,
2516
+ recordFormat: fileType,
2517
+ });
2518
+ };
2519
+ /**
2520
+ * 结束音视频录制 channelIndex(number) 录制通道 0主推流通道/ 1辅助推流通道/ 2辅助推流通道
2521
+ * @param {number} idx 0 | 1 | 2
2522
+ * @returns
2523
+ */
2524
+ export const stopRecord = async (idx) => {
2525
+ defaultApi.writeLog(`avsdk ZEGO::stopRecord idx: ${idx}`);
2526
+ dataReport.stopRecord({idx});
2527
+ return callMethod('StopRecord',{idx});
2528
+ };
2529
+ /**
2530
+ * 开启外部音频采集(通知sdk)推流前,调用此接口,publish_channel,number类型,传2代表第三路流
2531
+ * @param {number} idx 0 | 1 | 2
2532
+ * @returns
2533
+ */
2534
+ export const startCapture = async (idx) => {
2535
+ defaultApi.writeLog(`avsdk ZEGO::startCapture idx: ${idx}`);
2536
+ return callMethod('StartCapture',{publish_channel:idx});
2537
+ };
2538
+ /**
2539
+ * 结束外部音频采集(通知sdk)
2540
+ * @param {number} idx 0 | 1 | 2
2541
+ * @returns
2542
+ */
2543
+ export const stopCapture = async (idx) => {
2544
+ defaultApi.writeLog(`avsdk ZEGO::stopCapture idx: ${idx}`);
2545
+ return callMethod('StopCapture',{publish_channel:idx});
2546
+ };
2547
+
2548
+ /**
2549
+ * @function 设置外部采集设备模块
2550
+ * @param bUseVideoCapture 是否开启外部采集设备模块
2551
+ * @attention 必须在 InitSDK 前调用,置空必须在UninitSDK之后
2552
+ * @return Promise | void
2553
+ */
2554
+ const setVideoCaptureFactory = (bUseVideoCapture = false, streamChannel) => {
2555
+ defaultApi.writeLog('info', 'avsdk ZEGO::setVideoCaptureFactory');
2556
+ return callMethod('SetVideoCaptureFactory', {
2557
+ bUseVideoCapture,
2558
+ streamChannel
2559
+ });
2560
+ };
2561
+
2562
+ //设置音频数据来源
2563
+ const setAudioAuxSource = (source) => {
2564
+ defaultApi.writeLog('info', 'avsdk ZEGO::setAudioAuxSource');
2565
+ return callMethod('SetAudioAuxSource', {
2566
+ source
2567
+ });
2568
+ };
2569
+
2570
+ //RTC同屏 辅助通道音频类型 0:静音 / 1:麦克风 / 2:拉流的声音 / 3:1+2 / 4:麦克风+扬声器 / 5:扬声器(不含拉流)
2571
+ const setAUXAudioType = (type) => {
2572
+ defaultApi.writeLog('info', 'avsdk ZEGO::SetAUXAudioType');
2573
+ return callMethod('SetAUXAudioType', {
2574
+ type
2575
+ });
2576
+ };
2577
+
2578
+ //录制通道音频类型 0:静音 / 1:麦克风 / 2:拉流的声音 / 4:1+2 / 8:麦克风+扬声器(不含拉流)
2579
+ const setThirdAudioType = (type) => {
2580
+ defaultApi.writeLog('info', 'avsdk ZEGO::SetThirdAudioType');
2581
+ return callMethod('SetThirdAudioType', {
2582
+ type
2583
+ });
2584
+ };
2585
+
2586
+ //开启音频外部采集 参数:channel 参数类型:int 通道(传1使用辅通道)
2587
+ const startAudioExCapture = (channel) => {
2588
+ defaultApi.writeLog('info', 'avsdk ZEGO::startAudioExCapture');
2589
+ return callMethod('StartAudioExCapture', {
2590
+ channel
2591
+ });
2592
+ };
2593
+
2594
+ //加载截屏插件
2595
+ const LoadCollectionOutputEntry2 = () => {
2596
+ defaultApi.writeLog('info', 'avsdk ZEGO::LoadCollectionOutputEntry2');
2597
+ return callMethod('LoadCollectionOutputEntry2', {});
2598
+ };
2599
+
2600
+ //native调用开启同屏, Web端屏幕共享
2601
+ const startMultiScreen = async () => {
2602
+ defaultApi.writeLog('info', 'avsdk ZEGO::startMultiScreen');
2603
+ // await setVideoCaptureFactory(true,1);
2604
+ await LoadCollectionOutputEntry2();
2605
+ };
2606
+
2607
+
2608
+ /**
2609
+ * @function 设置推流时是否发送视频数据
2610
+ * @param mute true不发送(仅预览),false 发送
2611
+ * @param idx 推流通道索引 0表示主推流通道,默认;1表示第二路流推流通道,无法推出声音
2612
+ * @return Promise | void (0代表设置成功,否则设置失败)
2613
+ */
2614
+ const muteVideoPublish = (mute = true, idx = 0) => {
2615
+ return callMethod('MuteVideoPublish', {
2616
+ mute,
2617
+ idx
2618
+ });
2619
+ };
2620
+
2621
+ /**
2622
+ * @function 开始连麦
2623
+ * @param mode:number 采集器默认, 默认0=站立 1=坐立
2624
+ * @return Promise | void
2625
+ */
2626
+ export const teacherStartLinkMic = async (mode = 0) => {
2627
+ if (mode === 0) {
2628
+ await muteVideoPublish(true, 0);
2629
+ await setMicrophoneDevice({});
2630
+ await enableMic(true);
2631
+ } else {
2632
+ //开始连麦后,需要打开摄像头(开启外部采集器后,不会争抢摄像头),否则学生拉到的小班流会没有画面
2633
+ await enableCamera(true);
2634
+ await enableMic(true);
2635
+ }
2636
+ };
2637
+
2638
+ /**
2639
+ * @function 结束连麦
2640
+ * @param mode:number 采集器默认, 默认0=站立 1=坐立
2641
+ * @return Promise | void
2642
+ */
2643
+ export const teacherStopLinkMic = async (mode = 0) => {
2644
+ // if (mode === 0) {
2645
+ // await muteVideoPublish(false,0);
2646
+ // } else {
2647
+ // await setVideoCaptureFactory(false);
2648
+ // }
2649
+ };
2650
+
2651
+ /**
2652
+ * @function 设置镜像状态(预览)
2653
+ * @param { boolean } type true=开启 false=关闭
2654
+ * @return: Promise
2655
+ */
2656
+ export const setMirrorStatus = (isMirror) => {
2657
+ // return callMethod('SetPreViewMirror', { isMirror });
2658
+ return setVideoMirrorMode(isMirror >> 0);
2659
+ };
2660
+
2661
+ /**
2662
+ * @function 设置拉流镜像状态
2663
+ * @param { boolean } type true=开启 false=关闭
2664
+ * @return: Promise
2665
+ */
2666
+ export const setPlayViewMirror = (isMirror) => {
2667
+ return callMethod('SetPlayViewMirror', { isMirror });
2668
+ };
2669
+
2670
+ /**
2671
+ * @function 设置推流镜像状态
2672
+ * @param { boolean } id 采集器Id
2673
+ * @param { 0 | 1 | 2 | 3 } mode 0: 预览启用镜像,推流不启用镜像; 1: 预览启用镜像,推流启用镜像; 2: 预览不启用镜像,推流不启用镜像; 3: 预览不启用镜像,推流启用镜像
2674
+ * @return: Promise
2675
+ */
2676
+ export const setVideoMirrorMode = (mode, idx = 0) => {
2677
+ let realId = mode == 0 ? 2 : 1;
2678
+ defaultApi.writeLog(`ZEGO: setVideoMirrorMode, mode: ${mode}, idx:${idx}, realId:${realId}`);
2679
+ return callMethod('SetVideoMirrorMode', { idx, mode: realId });
2680
+ };
2681
+
2682
+ //美颜相关
2683
+ /**
2684
+ * @function 开启美颜
2685
+ * @return: Promise
2686
+ */
2687
+ export const startSenseMe = async () => {
2688
+ return callMethod('StartSenseMe', {});
2689
+ };
2690
+ /**
2691
+ * @function 设置美颜参数
2692
+ * * @param { number } type //美颜类型,1、红润强度,3、磨皮强度,4、美白强度,5、大眼,6、瘦脸,7、小脸,8、对比度强度,9、饱和度强度
2693
+ * * @param { number } value //美颜数值,有效值范围0~100
2694
+ * @return: Promise
2695
+ */
2696
+ export const setBeautifyParam = async (type, value) => {
2697
+ return callMethod('SetBeautifyParam', { type, value });
2698
+ };
2699
+ /**
2700
+ * @function 关闭美颜
2701
+ * @return: Promise
2702
+ */
2703
+ export const endSenseMe = async () => {
2704
+ return callMethod('EndSenseMe', {});
2705
+ };
2706
+
2707
+ /**
2708
+ * @function zego40路拉流混音接口
2709
+ * * @param { number } mixMode //混流模式 0=关闭混流 1=开启混流
2710
+ * * @param { array } streamIdArr //表示要突出声音的channel
2711
+ * * @param { number } mixNum //表示要突出channel的个数, 需要与参数'channels'的数组大小相同
2712
+ * @return: Promise
2713
+ */
2714
+ export const setAudioMixMode = async (mixMode, streamIdArr) => {
2715
+ let channelsArr = [];
2716
+ if (streamIdArr.length > 0) {
2717
+ streamIdArr.forEach(item => {
2718
+ channelsArr.push(getChannelIndex(item));
2719
+ });
2720
+ }
2721
+ return callMethod('SetAudioMixMode', { mixMode: mixMode, channels: channelsArr, num: channelsArr.length });
2722
+ };
2723
+
2724
+ // 获取TalMedia.dll版本号
2725
+ export const getSDKVersion = async () => {
2726
+ return callMethod('GetSDKVersion', {});
2727
+ };
2728
+
2729
+ /**
2730
+ * @function 获取摄像头所支持的分辨率
2731
+ * @param deviceId:String 设备id
2732
+ * @return Promise | void
2733
+ */
2734
+ export const getCameraSupportedRes = (deviceId) => {
2735
+ return callMethod('GetCameraSupportedResolution', {
2736
+ deviceId
2737
+ });
2738
+ };
2739
+
2740
+ /**
2741
+ * @function 发送SEI
2742
+ * @param inData: String 需要传输的音视频次要信息数据,外部输入。
2743
+ * @param dataLen: Number 数据长度,不能超过 4096 bytes
2744
+ * @param bPacket: Bool 是否采用外部打包好的包头,填写 false。
2745
+ * @param idx:Number 推流通道 index
2746
+ * 调用频率不能超过帧率,假设推流采用默认帧率15 fps,即调用频率不能超过 1000/15=66.7 ms/次。
2747
+ */
2748
+ export const sendMediaSideInfo = (info) => {
2749
+ defaultApi.writeLog(`SendMediaSideInfo --info${info}`);
2750
+ return callMethod('SendMediaSideInfo', {
2751
+ inData: info,
2752
+ dataLen: info.length,
2753
+ bPacket: false,
2754
+ idx: 0
2755
+ });
2756
+ };
2757
+
2758
+ //判断当前课型是否为zego推拉RTMP小组课
2759
+ export const isZegoGroupClass = () => {
2760
+ defaultApi.writeLog(`test: isZegoGroupClass--currentClassMode--currentGroupSdkType', ${currentClassMode}, ${currentGroupSdkType}`);
2761
+ return currentClassMode == 0 && currentGroupSdkType == 'zego'/*rtmp流为zego*/;
2762
+ };
2763
+ //判断当前课型是否为zego推拉RTMP组合小班课
2764
+ export const isZegoCombinationClass = () => {
2765
+ console.log('test: isZegoCombinationClass--currentClassMode--currentGroupSdkType', currentClassMode, currentGroupSdkType);
2766
+ return currentClassMode == 2 && currentGroupSdkType == 'zego'/*rtmp流为zego*/;
2767
+ };
2768
+ //判断推流类型是否为音频流
2769
+ export const isStreamAudioMuted = () => {
2770
+ return callMethod('IsStreamAudioMuted', {});
2771
+ };
2772
+ //判断推流类型是否为视频流
2773
+ export const isStreamVideoMuted = () => {
2774
+ return callMethod('IsStreamVideoMuted', {});
2775
+ };
2776
+ export const getStreamType = async () => {
2777
+ try {
2778
+ const pushAudio = JSON.parse((await isStreamAudioMuted()).msg).ret;
2779
+ const pushVideo = JSON.parse((await isStreamVideoMuted()).msg).ret;
2780
+ let stream_type = 'both';
2781
+ if (pushAudio && !pushVideo) {
2782
+ stream_type = 'video';
2783
+ }
2784
+ if (!pushAudio && pushVideo) {
2785
+ stream_type = 'audio';
2786
+ }
2787
+ if (pushAudio && pushVideo) {
2788
+ stream_type = 'none';
2789
+ }
2790
+ return stream_type;
2791
+ } catch (e) {
2792
+ let stream_type = 'none';
2793
+ return stream_type;
2794
+ }
2795
+ };
2796
+
2797
+ const heartBeatRealKeys = ['video_fps', 'video_bitrate', 'audio_fps', 'audio_bitrate'];
2798
+
2799
+ const _heartBeatDataReport = () => {
2800
+ // let cpuRate = 0;
2801
+ // let memRate = 0;
2802
+ let rateCount = 0;
2803
+ // let appCpuRate = 0;
2804
+ // let appMemUsed = 0;
2805
+ let rateTimer = setInterval(async () => {
2806
+ rateCount++;
2807
+ // let {cpu_rate, mem_rate, gpus, app_cpu_rate, app_mem_used} = (await toolApi.getCurCpuMemInfo()).msg;
2808
+ // cpu_rate = cpu_rate < 0 ? 0 : cpu_rate;
2809
+ // cpuRate += parseFloat(cpu_rate);
2810
+ // memRate += parseFloat(mem_rate);
2811
+ // if (window.zbztAVSDK_init_params.zego.role === 'student') {
2812
+ // appCpuRate += parseFloat(app_cpu_rate);
2813
+ // appMemUsed += parseFloat(app_mem_used);
2814
+ // }
2815
+
2816
+ if (rateCount >= 3) {
2817
+ // heartBeatRealKeys.forEach(realKey => {
2818
+ // if (heartBeatDataReportObj.hasOwnProperty(realKey) && heartBeatDataReportObj.count > 0) {
2819
+ // heartBeatDataReportObj[realKey] = util.toFixed(heartBeatDataReportObj[realKey]/heartBeatDataReportObj.count);
2820
+ // }
2821
+ // });
2822
+ const pullInfo = [];
2823
+ Object.keys(streamIdRtcPlayerInfo).forEach(streamid => {
2824
+ heartBeatRealKeys.forEach(realKey => {
2825
+ if (!streamIdRtcPlayerInfo[streamid].hasOwnProperty(realKey)) {
2826
+ streamIdRtcPlayerInfo[streamid][realKey] = [];
2827
+ }
2828
+ // if (streamIdRtcPlayerInfo[streamid].count > 0) {
2829
+ // streamIdRtcPlayerInfo[streamid][realKey] = util.toFixed(streamIdRtcPlayerInfo[streamid][realKey]/streamIdRtcPlayerInfo[streamid].count);
2830
+ // }
2831
+ });
2832
+
2833
+ //获取拉流类型,后期可写为函数提出去
2834
+ if (streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2835
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'both';
2836
+ } else if (!streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2837
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'video';
2838
+ } else if (streamIdRtcPlayerInfo1[streamid].audio_type && !streamIdRtcPlayerInfo1[streamid].video_type) {
2839
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'audio';
2840
+ } else {
2841
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'none';
2842
+ }
2843
+ // console.log('hsghsghsg_type_type', streamIdRtcPlayerInfo1[streamid].stream_type);
2844
+
2845
+ // delete streamIdRtcPlayerInfo[streamid].count;
2846
+ pullInfo.push({
2847
+ streamid,
2848
+ // uid: util.getUidByStreamId(streamid),
2849
+ ...streamIdRtcPlayerInfo[streamid],
2850
+ pull_type: streamIdRtcPlayerInfo1[streamid].stream_type,
2851
+ volume: streamIdRtcPlayerInfo[streamid].volume.slice(0, streamIdRtcPlayerInfo[streamid].volume.length - 1)
2852
+ });
2853
+ resetStreamIdRtcPlayerInfo(streamid);
2854
+ });
2855
+ // delete heartBeatDataReportObj.count;
2856
+ if (isFirstHeartBeatReport && rateCount > 0) {
2857
+ try {
2858
+ //静音推流时过滤掉音频帧率和码率,上报为0;
2859
+ // if (!isNoticeMicVolumeZego) {
2860
+ // heartBeatDataReportObj['audio_fps'] = [];
2861
+ // heartBeatDataReportObj['audio_bitrate'] = [];
2862
+ // }
2863
+
2864
+ //获取推流类型,后期可写为函数提出去
2865
+ if (zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2866
+ zbztsdk.deviceStatus.stream_type = 'both';
2867
+ } else if (!zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2868
+ zbztsdk.deviceStatus.stream_type = 'audio';
2869
+ } else if (zbztsdk.deviceStatus.camera && !zbztsdk.deviceStatus.microphone) {
2870
+ zbztsdk.deviceStatus.stream_type = 'video';
2871
+ } else {
2872
+ zbztsdk.deviceStatus.stream_type = 'none';
2873
+ };
2874
+ // console.log('push_type222',zbztsdk.deviceStatus,zbztsdk.deviceStatus.stream_type);
2875
+ defaultApi.writeLog(`push_type_zego,camera: ${zbztsdk.deviceStatus.camera},microphone: ${zbztsdk.deviceStatus.microphone},type: ${zbztsdk.deviceStatus.stream_type},a_fps: ${dataZegoCapture.afps}, a_bit: ${dataZegoCapture.akbps}, v_fps: ${dataZegoCapture.fps}, v_bit: ${dataZegoCapture.kbps}`);
2876
+ // if (window.zbztAVSDK_init_params.zego.role === 'teacher') {
2877
+ dataReport.heartbeat({
2878
+ ...{ ...heartBeatDataReportObj, push_type: zbztsdk.deviceStatus.stream_type, volume: heartBeatDataReportObj.volume.slice(0, heartBeatDataReportObj.volume.length - 1) },
2879
+ // pull_info: JSON.stringify(pullInfo),
2880
+ pull_info: pullInfo,
2881
+ // cpu_rate: util.toFixed(cpuRate/rateCount),
2882
+ // mem_rate: util.toFixed(memRate/rateCount),
2883
+ });
2884
+ // } else {
2885
+ // dataReport.heartbeat({
2886
+ // ...heartBeatDataReportObj,
2887
+ // pull_info: JSON.stringify(pullInfo),
2888
+ // cpu_rate: util.toFixed(cpuRate/rateCount),
2889
+ // mem_rate: util.toFixed(memRate/rateCount),
2890
+ // app_cpu: util.toFixed(appCpuRate/rateCount),
2891
+ // app_mem: util.toFixed(appMemUsed/rateCount),
2892
+ // video_mem: gpus
2893
+ // });
2894
+ // }
2895
+ } catch (e) {
2896
+ console.log(e);
2897
+ }
2898
+ }
2899
+ resetHeartBeatDataReportObj();
2900
+ rateCount = 0;
2901
+ // cpuRate = 0;
2902
+ // memRate = 0;
2903
+ // appCpuRate = 0;
2904
+ // appMemUsed = 0;
2905
+
2906
+ clearInterval(rateTimer);
2907
+ }
2908
+ }, 10 * 1000);
2909
+ };
2910
+
2911
+ const heartBeatDataReport = (type) => {
2912
+ try {
2913
+ if (type === 'start' && !heartBeatDataReportTimer) {
2914
+ _heartBeatDataReport();
2915
+ heartBeatDataReportTimer = setInterval(() => {
2916
+ _heartBeatDataReport();
2917
+ }, 30 * 1000);
2918
+ }
2919
+ if (type === 'stop') {
2920
+ clearInterval(heartBeatDataReportTimer);
2921
+ heartBeatDataReportTimer = null;
2922
+ }
2923
+ } catch (error) {
2924
+ console.log(error);
2925
+ }
2926
+ };
2927
+
2928
+ const heartBeatDataReportCalc = (name, _d, streamid) => {
2929
+ // 拉流
2930
+ const pullKeys = ['fps', 'kbps', 'afps', 'akbps'];
2931
+ if (name === 'OnPlayQulityUpdate') {
2932
+ if (streamIdRtcPlayerInfo && streamIdRtcPlayerInfo.hasOwnProperty(streamid)) {
2933
+ let isReport = true;
2934
+ // streamIdRtcPlayerInfo[streamid].count++;
2935
+ heartBeatRealKeys.forEach((realKey, index) => {
2936
+ if (_d.hasOwnProperty(pullKeys[index])) {
2937
+ if (streamIdRtcPlayerInfo[streamid][realKey] === undefined) {
2938
+ streamIdRtcPlayerInfo[streamid][realKey] = [];
2939
+ isReport = false;
2940
+ }
2941
+ // streamIdRtcPlayerInfo[streamid][realKey].push(parseFloat(parseInt(_d[pullKeys[index]])));
2942
+ }
2943
+ });
2944
+ if (isReport) {
2945
+ let audio_fps_zego_pull = 0;
2946
+ let audio_bitrate_zego_pull = 0;
2947
+ let video_fps_zego_pull = 0;
2948
+ let video_bitrate_zego_pull = 0;
2949
+
2950
+ if (streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2951
+ audio_fps_zego_pull = parseFloat(parseInt(_d.afps));
2952
+ audio_bitrate_zego_pull = parseFloat(parseInt(_d.akbps));
2953
+ video_fps_zego_pull = parseFloat(parseInt(_d.fps));
2954
+ video_bitrate_zego_pull = parseFloat(parseInt(_d.kbps));
2955
+ } else if (!streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2956
+ video_fps_zego_pull = parseFloat(parseInt(_d.fps));
2957
+ video_bitrate_zego_pull = parseFloat(parseInt(_d.kbps));
2958
+ } else if (streamIdRtcPlayerInfo1[streamid].audio_type && !streamIdRtcPlayerInfo1[streamid].video_type) {
2959
+ audio_fps_zego_pull = parseFloat(parseInt(_d.afps));
2960
+ audio_bitrate_zego_pull = parseFloat(parseInt(_d.akbps));
2961
+ }
2962
+ streamIdRtcPlayerInfo[streamid].audio_fps.push(audio_fps_zego_pull);
2963
+ streamIdRtcPlayerInfo[streamid].audio_bitrate.push(audio_bitrate_zego_pull);
2964
+ streamIdRtcPlayerInfo[streamid].video_fps.push(video_fps_zego_pull);
2965
+ streamIdRtcPlayerInfo[streamid].video_bitrate.push(video_bitrate_zego_pull);
2966
+
2967
+ streamIdRtcPlayerInfo[streamid].ctime.push(Math.round((new Date().getTime() + dataReport.timestamp) / 1000));
2968
+ streamIdRtcPlayerInfo[streamid].avtimestampdiff.push(_d.avTimestampDiff);
2969
+ streamIdRtcPlayerInfo[streamid].pull_loss.push(_d.pktLostRate);
2970
+ streamIdRtcPlayerInfo[streamid].pull_delay.push(_d.rtt);
2971
+ }
2972
+ }
2973
+ }
2974
+ // 推流
2975
+ const pushKeys = ['fps', 'kbps', 'afps', 'akbps'];
2976
+ if (name === 'OnPublishQualityUpdate') {
2977
+ // heartBeatDataReportObj.count++;
2978
+ // heartBeatRealKeys.forEach((realKey, index) => {
2979
+ // if (heartBeatDataReportObj.hasOwnProperty(realKey) && _d.hasOwnProperty(pushKeys[index])) {
2980
+ // heartBeatDataReportObj[realKey].push(parseFloat(parseInt(_d[pushKeys[index]])));
2981
+ // }
2982
+ // });
2983
+ let audio_fps_zego_push = 0;
2984
+ let audio_bitrate_zego_push = 0;
2985
+ let video_fps_zego_push = 0;
2986
+ let video_bitrate_zego_push = 0;
2987
+ dataZegoCapture = _d;
2988
+
2989
+ if (zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2990
+ audio_fps_zego_push = parseFloat(parseInt(_d.afps));
2991
+ audio_bitrate_zego_push = parseFloat(parseInt(_d.akbps));
2992
+ video_fps_zego_push = parseFloat(parseInt(_d.fps));
2993
+ video_bitrate_zego_push = parseFloat(parseInt(_d.kbps));
2994
+ } else if (!zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2995
+ audio_fps_zego_push = parseFloat(parseInt(_d.afps));
2996
+ audio_bitrate_zego_push = parseFloat(parseInt(_d.akbps));
2997
+ } else if (zbztsdk.deviceStatus.camera && !zbztsdk.deviceStatus.microphone) {
2998
+ video_fps_zego_push = parseFloat(parseInt(_d.fps));
2999
+ video_bitrate_zego_push = parseFloat(parseInt(_d.kbps));
3000
+ }
3001
+ heartBeatDataReportObj.audio_fps.push(audio_fps_zego_push);
3002
+ heartBeatDataReportObj.audio_bitrate.push(audio_bitrate_zego_push);
3003
+ heartBeatDataReportObj.video_fps.push(video_fps_zego_push);
3004
+ heartBeatDataReportObj.video_bitrate.push(video_bitrate_zego_push);
3005
+
3006
+ heartBeatDataReportObj.push_loss.push(_d.pktLostRate);
3007
+ heartBeatDataReportObj.push_delay.push(_d.rtt);
3008
+ heartBeatDataReportObj.ctime.push(Math.round((new Date().getTime() + dataReport.timestamp) / 1000));
3009
+ }
3010
+ };
3011
+ //推流字段
3012
+ const resetHeartBeatDataReportObj = () => {
3013
+ heartBeatDataReportObj = {
3014
+ ctime: [],
3015
+ push_type: 'none',
3016
+ // video_fps: 0,
3017
+ // video_bitrate: 0,
3018
+ // audio_fps: 0,
3019
+ // audio_bitrate: 0,
3020
+ video_fps: [],
3021
+ video_bitrate: [],
3022
+ audio_fps: [],
3023
+ audio_bitrate: [],
3024
+ push_loss: [],
3025
+ push_delay: [],
3026
+ // count: 0,
3027
+ volume: ''
3028
+ };
3029
+ };
3030
+
3031
+ //记录拉流类型,用作数据上报
3032
+ const resetStreamIdRtcPlayerInfo1 = (streamId) => {
3033
+ streamIdRtcPlayerInfo1[streamId] = {
3034
+ audio_type: false,
3035
+ video_type: false,
3036
+ stream_type: 'none'
3037
+ };
3038
+ };
3039
+
3040
+ resetHeartBeatDataReportObj();
3041
+
3042
+ //拉流字段
3043
+ const resetStreamIdRtcPlayerInfo = (streamId) => {
3044
+ streamIdRtcPlayerInfo[streamId] = {
3045
+ pull_uid: util.getUidByStreamId(streamId),
3046
+ streamid: streamId,
3047
+ ctime: [],
3048
+ pull_type: streamIdRtcPlayerInfo1[streamId].stream_type,
3049
+ volume: '',
3050
+ // 平均值
3051
+ // count: 0,
3052
+ // video_fps: 0,
3053
+ // video_bitrate: 0,
3054
+ // audio_fps: 0,
3055
+ // audio_bitrate: 0,
3056
+ video_fps: [],
3057
+ video_bitrate: [],
3058
+ audio_fps: [],
3059
+ audio_bitrate: [],
3060
+ pull_loss: [],
3061
+ pull_delay: [],
3062
+ //音画不同步字段
3063
+ avtimestampdiff: [],
3064
+ // 累加
3065
+ audio_ifg: 0,
3066
+ video_ifg: 0
3067
+ };
3068
+ };
3069
+
3070
+ export default {
3071
+ startEngine,
3072
+ destroyEngine,
3073
+ setDefaultDevice,
3074
+ getVideoDeviceList,
3075
+ setVideoDevice,
3076
+ enableCamera,
3077
+ enableMic,
3078
+ setAudioSpeakerCapture,
3079
+ getAudioDeviceList,
3080
+ setAudioDevice,
3081
+ getSpeakerDeviceList,
3082
+ setSpeakerDevice,
3083
+ getCurrentSpeakerDevice,
3084
+ getSpeakerDeviceVolume,
3085
+ setSpeakerDeviceVolume,
3086
+ setSpeakerDeviceMute,
3087
+ getMicrophoneDeviceList,
3088
+ setMicrophoneDevice,
3089
+ getMicDeviceVolume,
3090
+ setMicDeviceVolume,
3091
+ setMicDeviceMute,
3092
+ getSpeakerSimpleVolume,
3093
+ setSpeakerSimpleVolume,
3094
+ setSpeakerSimpleMute,
3095
+ setPreviewView,
3096
+ startPreview,
3097
+ startLocalOrRemotePreview,
3098
+ setVideoFPS,
3099
+ setVideoBitrate,
3100
+ setAudioBitrate,
3101
+ setVideoCaptureResolution,
3102
+ setCameraParam,
3103
+ setVideoEncodeResolution,
3104
+ init,
3105
+ startPublish2,
3106
+ stopPublish,
3107
+ initPullFlow,
3108
+ playStream,
3109
+ stopPlayStream,
3110
+ stopAllPlayStream,
3111
+ leaveRoom,
3112
+ activateAudioPlayStream,
3113
+ pullAudioFlow,
3114
+ activateVideoPlayStream,
3115
+ setAudioVolumeNotify,
3116
+ stopAudioVolumeNotify,
3117
+ openMicVolumeCb,
3118
+ startSoundLevelMonitor,
3119
+ stopSoundLevelMonitor,
3120
+ setSoundLevelMonitorCycle,
3121
+ setMirrorStatus,
3122
+ getStreamType,
3123
+ setPlayViewMirror,
3124
+ setMuteStreamAudio,
3125
+ setMuteStreamVideo,
3126
+ teacherStartLinkMic,
3127
+ teacherStopLinkMic,
3128
+ getSDKVersion,
3129
+ getCameraSupportedRes,
3130
+ setVideoMirrorMode,
3131
+ startMultiScreen,
3132
+ addListener,
3133
+ };