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,2854 @@
1
+ /**
2
+ * @File: Rtc 音视频 SDK
3
+ * @Author: xuyuanrui
4
+ * @Email: raywhbxyr@163.com
5
+ * @Date: 2018-08-10 10:22:47
6
+ **/
7
+ import dataReport from '../network/dataReport.js';
8
+ import {dabanDataReport} from '../network/api.js';
9
+ import util from '../util/util.js';
10
+ import defaultApi from '../default/index.js';
11
+ import toolApi from '../tool/index.js';
12
+ import NOTICE from '../notice.js';
13
+ import { deviceListReport } from './device.js';
14
+ import zbztsdk from '../zbzt-live-sdk.js';
15
+ // 扩展标识
16
+ const extensionId = 'live';
17
+ // 端提供的 API 入口
18
+ const EM = window.EM;
19
+ // 维护的一份播放器的 rtcPlayerId 与 streamId 的映射
20
+ let streamIdToRtcPlayerId = {};
21
+ // let streamIdToBlobUrl = {};
22
+ let rtcPlayerIdToStreamId = {};
23
+ // 已经停止的播放器
24
+ let stopedRtcPlayers = [];
25
+ // 播放器 id 缓存
26
+ let rtcPlayerIds = [];
27
+ // rtc 当前正在使用的摄像头的设备 id
28
+ let rtcNowUseCamera = '';
29
+ // 是否执行麦克风音量回调的标记
30
+ let runMicVolumeCb = false;
31
+ // 是否创建了用于设备检测的采集器的标记
32
+ let deviceCheckerCaptureInit = false;
33
+ // 是否执行过 Rtc 的 AddListener 的标志
34
+ let hasAddListener = false;
35
+ // 是否在课中的标志
36
+ let isInRoom = false;
37
+ // 是否处于网络错误状态中的标志
38
+ let hasNetWrong = false;
39
+ // 是否加入/离开 rtc room 成功
40
+ let hasJoinRtcRoom = false;
41
+ let hasLeaveRtcRoom = false;
42
+ // rtc 底层流媒体数据上报地址配置
43
+
44
+ let _confId = null;
45
+ // rtc小班课=0;rtc大班课=1
46
+ const classType = 0;
47
+ // 监听id
48
+ let EMListenerId = 0;
49
+
50
+ //静音推流时,音量值是否上抛上层标志 false=没有声音不往上层通知/true=有声音有上层通知
51
+ let isNoticeMicVolumeRtc = false;
52
+ let isNoticeCarVolumeRtc = false;
53
+
54
+ /*
55
+ 1001--网络错误
56
+ 1002--播放器内部错误
57
+ 1003--调度服务器错误
58
+ 1004--转发服务器错误
59
+ 1005--无可用转发服务器
60
+ 2003--对端尚未进入教室
61
+ 2013–网络断开
62
+ */
63
+ const rtcPlayerErrorCodes = ['1001', '1002', '1003', '1004', '1005', '2003', '2013', '2008', '1006'];
64
+
65
+ /*
66
+ 2001-- 网络错误,通知业务层检查网络设置和推流地址, 对于直播, id与AddPushUrl返回值对应
67
+ 2002-- 网络恢复, 对于直播, id与AddPushUrl返回值对应
68
+ 2003--网络断开
69
+ 2004--转发服务器错误
70
+ 2005--调度服务器错误
71
+ 2006--无可用转发服务器
72
+ 2007--转发服务器能力不足
73
+ 2008--摄像头视频宽高错误
74
+ 2009--视频编码器初始化错误
75
+ 2010--错误的摄像头ID
76
+ 2011--错误的录音设备ID
77
+ 2012--抓屏参数错误
78
+ 2013--打开摄像头失败,一种可能是摄像头被其它进程占用
79
+ 2014–-打开麦克风失败
80
+ 2015--打开播放文件失败
81
+ 3206--推流ID被占用
82
+ 3309--只要 10 秒内和服务器无法建立连接就会触发一次且仅触发一次(仅互动流)
83
+ */
84
+ const rtcCaptureErrorCodes = ['2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2012', '2013', '3206', '3309'];
85
+
86
+ // 心跳
87
+ let heartBeatDataReportObj = {};
88
+ let heartBeatDataReportTimer = null;
89
+ let isFirstHeartBeatReport = false;
90
+ let streamIdRtcPlayerInfo = {};
91
+ let streamIdRtcPlayerInfo1 = {};
92
+ const rtcPlayerCodeToNames = {
93
+ '1002': 'err_core',
94
+ '1003': 'err_schedule_server',
95
+ '1004': 'err_relay_server',
96
+ '1005': 'err_no_available_relay_server',
97
+ '2003': 'st_streamNotReady',
98
+ '2013': 'network_disconnect'
99
+ };
100
+
101
+ //上报拼接状态
102
+ //window.zbztAVSDK_init_params
103
+ let paramInfo ;
104
+ let captureBefore ;//运控获取,一直不变(拼接前摄像头采集分辨率)
105
+ let captureEncodeBefore;//摄像头拼接前编码分辨率云控拿取
106
+ let screenEncodeBefore;//截屏窗拼接前编码分辨率 东奇提供
107
+ // let screenBefore;//拼接前截屏窗采集分辨率
108
+
109
+ let captureAfter ;//一直不变(拼接前摄像头采集分辨率同上captureBefore)
110
+ let captureEncodeAfter;//摄像头拼接后编码分辨率
111
+ let screenEncodeAfter;//
112
+ // let screenAfter;//
113
+
114
+ let currStreamIdRtcPlayerInfo ;
115
+ let stStreamNotReadyReport = {};
116
+ //记录底层推流回调的值
117
+ let dataRtcCapture = {};
118
+ /**
119
+ * @function 调用端提供的回调方法
120
+ * @param name:String 回调方法名,必选
121
+ * @param args:Object 回调参数,必选
122
+ * @return Promise | void
123
+ */
124
+ const callMethod = (name, args) => {
125
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
126
+ if (EM) {
127
+ return new Promise((resolve, reject) => {
128
+ let noneCamera = (name === 'SetCameraDevice' && !args.close && !args.deviceID);
129
+ let noneMicrophone = (name === 'SetAudioDevice' && !args.deviceID);
130
+ let noneSpeaker = (name === 'SetSpeakerDevice' && !args.speakId);
131
+ if (noneCamera || noneMicrophone || noneSpeaker) {
132
+ return resolve();
133
+ }
134
+ EM.CallMethod(
135
+ extensionId,
136
+ name,
137
+ JSON.stringify({...args, classType}),
138
+ (code, msg) => {
139
+ resolve({
140
+ code,
141
+ msg
142
+ });
143
+ defaultApi.writeLog(`${name} Code: ${code}\nParams: ${JSON.stringify({...args, classType})}\nMessage: ${msg}`);
144
+ let _msg = msg && JSON.parse(msg);
145
+ // 数据上报
146
+ switch (name) {
147
+ case 'SetAppId':
148
+ break;
149
+ case 'SetConfId':
150
+ break;
151
+ case 'SetAudioDevice':
152
+ if (code === 0 && _msg.ret === true) {
153
+ window.zbztAVSDK_device_checker_init.microphone.use = args.deviceID;
154
+ }
155
+ break;
156
+ case 'SetCameraDevice':
157
+ if (code === 0 && _msg.ret === true) {
158
+ window.zbztAVSDK_device_checker_init.camera.use = args.deviceID;
159
+ if (args.deviceID) {
160
+ rtcNowUseCamera = args.deviceID;
161
+ }
162
+ }
163
+ break;
164
+ case 'SetSpeakerDevice':
165
+ if (code === 0) {
166
+ window.zbztAVSDK_device_checker_init.speaker.use = args.speakId;
167
+ }
168
+ break;
169
+ case 'CreateRtcCapture':
170
+ if (code === 0 && args.renderid === 'deviceCheckerInit') {
171
+ deviceCheckerCaptureInit = true;
172
+ }
173
+ break;
174
+ }
175
+ }
176
+ );
177
+ });
178
+ }
179
+ };
180
+
181
+ /**
182
+ * @function 加载 Rtc 扩展
183
+ * @param extensionVersion:String 扩展版本号,必选
184
+ * @return Promise | void
185
+ */
186
+ export const loadRtc = (extensionVersion, cb) => {
187
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
188
+ if (EM) {
189
+ return new Promise((resolve, reject) => {
190
+ removerListener();
191
+ EM.Load(
192
+ extensionId,
193
+ extensionVersion,
194
+ false,
195
+ (code, msg) => {
196
+ defaultApi.writeLog(`loadRtc Code: ${code}\nMessage: ${msg}`);
197
+ addListener();
198
+ resolve();
199
+ }
200
+ );
201
+ });
202
+ }
203
+ };
204
+
205
+ /**
206
+ * @function 卸载 Rtc 扩展
207
+ * @return Promise | void
208
+ */
209
+ export const unloadRtc = () => {
210
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
211
+ if (EM) {
212
+ return new Promise((resolve, reject) => {
213
+ EM.UnLoad(
214
+ extensionId,
215
+ (code, msg) => {
216
+ defaultApi.writeLog(`unloadRtc Code: ${code}\nMessage: ${msg}`);
217
+ resolve();
218
+ }
219
+ );
220
+ });
221
+ }
222
+ };
223
+
224
+ /**
225
+ * @function 添加扩展监听机制
226
+ * @return void
227
+ */
228
+ const addListener = () => {
229
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
230
+ if (EM && !hasAddListener) {
231
+ hasAddListener = true;
232
+ EM.AddListener(extensionId, (event, data) => {
233
+ if (data && data.indexOf(extensionId) > -1) {
234
+ try {
235
+ const _data = JSON.parse(data);
236
+ if (_data[extensionId] !== undefined && EMListenerId == 0) {
237
+ EMListenerId = _data[extensionId];
238
+ defaultApi.writeLog(`RTC::addListener-- EMListenerId: ${EMListenerId}`);
239
+ }
240
+ } catch (error) {}
241
+ }
242
+ if (!event || !data) {
243
+ return;
244
+ }
245
+ let _d = JSON.parse(data);
246
+ let _e = JSON.parse(event);
247
+ if (_d && _d.classType === 1) {
248
+ return false;
249
+ }
250
+ if (_e.hasOwnProperty('event_name')) {
251
+ let name = _e.event_name;
252
+ currStreamIdRtcPlayerInfo = streamIdRtcPlayerInfo[_d.streamid];
253
+ switch (name) {
254
+ case 'deviceStateChanged':
255
+ {
256
+ const deviceType = _d.deviceType;
257
+ // 0=添加设备 1=移除设备 string
258
+ let state = _d.deviceState;
259
+ let deviceNameCamera = '';
260
+ let deviceNameMic = '';
261
+ let deviceNameSpeak = '';
262
+ switch (deviceType) {
263
+ // 摄像头热插拔
264
+ case '1':
265
+ {
266
+ setCameraDevice({deviceId: state == 1 ? '' : _d.deviceID, close: false, operationType: 'hotPlug', deviceState: state, changedDeviceId: _d.deviceID, changedDeviceName: _d.deviceName});
267
+ deviceNameCamera = _d.deviceName;
268
+ }
269
+ break;
270
+ // 麦克风热插拔
271
+ case '2':
272
+ {
273
+ setMicrophoneDevice({deviceId: state == 1 ? '' : _d.deviceID, operationType: 'hotPlug', deviceState: state, changedDeviceId: _d.deviceID, changedDeviceName: _d.deviceName});
274
+ deviceNameMic = _d.deviceName;
275
+ }
276
+ break;
277
+ // 扬声器热插拔,暂时不做处理
278
+ case '3':
279
+ {
280
+ // console.log('hsghsghsg扬声器热插拔',_d,state);
281
+ setSpeakerDevice({
282
+ speakId: state == 1 ? '' : _d.deviceID,
283
+ operationType: 'hotPlug',
284
+ deviceState: state,
285
+ changedDeviceId: _d.deviceID,
286
+ changedDeviceName: _d.deviceName});
287
+ deviceNameSpeak = _d.deviceName;
288
+ }
289
+ break;
290
+ }
291
+ // try {
292
+ // dataReport.deviceTest({
293
+ // device: deviceType,
294
+ // fore_state: state == '0' ? 1 : 2 ,
295
+ // camera_name: deviceNameCamera,
296
+ // microphone_name: deviceNameMic,
297
+ // speaker_name: deviceNameSpeak
298
+ // });
299
+ // } catch (e){
300
+ // };
301
+ }
302
+ break;
303
+ case 'rtcCaptureCycleDataReport'://推流 fps、bitrate
304
+ {
305
+ var keys = Object.keys(_d);
306
+ if (isNoticeMicVolumeRtc) {
307
+ if (keys.indexOf('volum') > -1
308
+ && window.zbztAVSDK_init_sdk_type === 'rtc') {
309
+ NOTICE.captureMicVolumeChanged({
310
+ volume: +_d.volum
311
+ });
312
+ }
313
+ }
314
+ if (keys.indexOf('volum') > -1) {
315
+ // heartBeatDataReportObj.volume.push(_d.volum);
316
+ // console.log('声音回调',`${new Date().getMinutes()}:${new Date().getSeconds()}`,_d.volum);
317
+ heartBeatDataReportObj.volume = heartBeatDataReportObj.volume + _d.volum + ',';
318
+ }
319
+ }
320
+ // 拉流
321
+ case 'rtcPlayCycleDataReport':
322
+ {
323
+ if (_d.errorcode && _d.errorcode == 7000) {
324
+ NOTICE.playerVolumeChanged({
325
+ userId: util.getUidByStreamId(_d.streamid),
326
+ streamId: _d.streamid,
327
+ volume: _d.volume
328
+ });
329
+ // currStreamIdRtcPlayerInfo && currStreamIdRtcPlayerInfo.volume.push(_d.volume);
330
+ // streamIdRtcPlayerInfo[_d.streamid] && streamIdRtcPlayerInfo[_d.streamid].volume.push(_d.volume);
331
+ if(streamIdRtcPlayerInfo[_d.streamid]) {
332
+ streamIdRtcPlayerInfo[_d.streamid].volume = streamIdRtcPlayerInfo[_d.streamid].volume + _d.volume + ',';
333
+ }
334
+ };
335
+ if (_d.hasOwnProperty('codecBitRate')) {
336
+ if (name === 'rtcPlayCycleDataReport') {
337
+ NOTICE.pullQuality({
338
+ video: {
339
+ userId: util.getUidByStreamId(_d.streamid),
340
+ streamId: _d.streamid,
341
+ bitrate: Math.round(_d.codecBitRate),
342
+ fps: Math.round(_d.codecFrameRate),
343
+ volume: _d.volume,
344
+ realTimeVolume: _d.realTimeVolume
345
+ }
346
+ });
347
+ NOTICE.playLossAndDelay({
348
+ userId: util.getUidByStreamId(_d.streamid),
349
+ delay:_d.delay,
350
+ lostrate:_d.lostrate
351
+ });
352
+ }
353
+ if (name === 'rtcCaptureCycleDataReport') {
354
+ NOTICE.pushQuality({
355
+ video: {
356
+ bitrate: Math.round(_d.codecBitRate),
357
+ fps: Math.round(_d.codecFrameRate)
358
+ }
359
+ });
360
+ NOTICE.pushLossAndDelay({
361
+ userId: util.getUidByStreamId(_d.streamid),
362
+ delay:_d.delay,
363
+ lostrate:_d.lostrate
364
+ });
365
+ }
366
+ heartBeatDataReportCalc(name, _d);
367
+ }
368
+ if (_d.hasOwnProperty('realTimeVolume') || _d.hasOwnProperty('volume')) {
369
+ NOTICE.volumeChange({
370
+ userId: util.getUidByStreamId(_d.streamid),
371
+ streamId: _d.streamid,
372
+ volume: _d.volume
373
+ });
374
+ }
375
+ }
376
+ break;
377
+ case 'OnLiveCaptureEvent':
378
+ break;
379
+ case 'OnRtcCaptureEvent':
380
+ {
381
+ if (_d && _d.hasOwnProperty('errorcode')) {
382
+ let code = _d.errorcode;
383
+ switch (code) {
384
+ case '1003':
385
+ if (window.zbztAVSDK_init_params.rtc.isTurnPush) {
386
+ sendRecordingMsg({ cmd: 'start' });
387
+ }
388
+ if (hasNetWrong) {
389
+ hasNetWrong = false;
390
+ NOTICE.networkRecovery({
391
+ message: 'Network recovery'
392
+ });
393
+ }
394
+ try {
395
+ dataReport.publishResult({
396
+ code: '0',
397
+ // publish_streamid: window.zbztAVSDK_init_params.rtc.streamId,
398
+ });
399
+ NOTICE.pushFlowSuccess({code:0,publish_streamid: _d.streamid});
400
+ } catch (e) {};
401
+ break;
402
+ case '1005': // 摄像头设备打开成功
403
+ // 大班数据上报
404
+ try {
405
+ dabanDataReport({
406
+ action: 'open_camera',
407
+ camera_status: 1,
408
+ uid: window.zbztAVSDK_init_params.rtc.userId
409
+ });
410
+ } catch(e) {
411
+ }
412
+ break;
413
+ case '2011': // 摄像头设备打开失败
414
+ // 大班数据上报
415
+ try {
416
+ dabanDataReport({
417
+ action: 'open_camera',
418
+ camera_status: 0,
419
+ uid: window.zbztAVSDK_init_params.rtc.userId
420
+ });
421
+ } catch(e){}
422
+
423
+ break;
424
+ case '2008': // 错误的摄像头ID
425
+ setCameraDevice({deviceId: '', close: false, operationType: 'deviceError'});
426
+ break;
427
+ case '1006': // 麦克风设备打开成功
428
+ break;
429
+ case '2010': // 麦克风设备打开失败
430
+ case '2013': // 麦克风设备打开失败
431
+ case '2012': // 麦克风设备打开失败
432
+ case '2009': // 错误的录音设备ID
433
+ setMicrophoneDevice({deviceId: '', operationType: 'deviceError'});
434
+ break;
435
+ // 重试推流
436
+ case '2003':
437
+ case '2004':
438
+ case '2005':
439
+ case '2006':
440
+ case '2007':
441
+ // pushFlowExceptionHandler();
442
+ break;
443
+ case '2001':
444
+ hasNetWrong = true;
445
+ defaultApi.writeLog('error', 'Network error');
446
+ NOTICE.networkError({
447
+ message: 'Network error'
448
+ });
449
+ break;
450
+ }
451
+ if (rtcCaptureErrorCodes.includes(code)) {
452
+ try {
453
+ dataReport.publishResult({
454
+ code: code,
455
+ // publish_streamid: window.zbztAVSDK_init_params.rtc.streamId,
456
+ });
457
+ } catch (e) {};
458
+ }
459
+ }
460
+ }
461
+ break;
462
+ case 'OnSingleRecordResponse':
463
+ {
464
+ NOTICE.recordResponse(_d);
465
+ }
466
+ break;
467
+ case 'live_recovery_start':
468
+ {
469
+ console.log('live_recovery_start');
470
+ NOTICE.liveRecoveryStart();
471
+ }
472
+ break;
473
+ case 'recordingMsg':
474
+ {
475
+ if (_d.cmd === 0) {
476
+ const {errorcode, streamId} = _d;
477
+ try {
478
+ dataReport.turnPushResult({
479
+ errorcode,
480
+ case: 'turn push',
481
+ streamid: streamId
482
+ });
483
+ } catch (e) {};
484
+ }
485
+ }
486
+ break;
487
+ case 'OnRecvMediaSideInfo':
488
+ {
489
+ console.log('我是sei',_data);
490
+ NOTICE.seiReceived({data: _data});
491
+ }
492
+ break;
493
+ case 'VideoFrameInterval':
494
+ {
495
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.video_ifg += _d.video_ifg);
496
+ }
497
+ break;
498
+ case 'AudioFrameInterval':
499
+ {
500
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.audio_ifg += _d.audio_ifg);
501
+ }
502
+ break;
503
+ case 'OnRtcPlayError':
504
+ {
505
+ if (_d && _d.hasOwnProperty('errorcode')) {
506
+ let code = _d.errorcode;
507
+ switch (code) {
508
+ // 重试拉流
509
+ case '1002':
510
+ case '1003':
511
+ case '1004':
512
+ case '1005':
513
+ case '1006':
514
+ case '1007':
515
+ // pullFlowExceptionHandler(_d.streamid);
516
+ NOTICE.playError({
517
+ userId: util.getUidByStreamId(_d.streamid),
518
+ streamId: _d.streamid,
519
+ message: 'play error'
520
+ });
521
+ break;
522
+ case '1001':
523
+ hasNetWrong = true;
524
+ writeLog('error', 'Network error');
525
+ NOTICE.networkError({
526
+ message: 'Network error'
527
+ });
528
+ break;
529
+ }
530
+ if (rtcPlayerErrorCodes.includes(code)) {
531
+ pullResultReport(code, _d.streamid);
532
+ }
533
+ NOTICE.playErrorDetail({
534
+ type: rtcPlayerCodeToNames[code],
535
+ data: {
536
+ userId: util.getUidByStreamId(_d.streamid),
537
+ streamId: _d.streamid,
538
+ allData: _d
539
+ }
540
+ });
541
+ }
542
+ }
543
+ break;
544
+ case 'OnRtcPlayStatus':
545
+ {
546
+ if (_d && _d.hasOwnProperty('errorcode')) {
547
+ const code = _d.errorcode;
548
+ switch (code) {
549
+ case '2004':
550
+ if (window.zbztAVSDK_init_params.rtc.role === 'student') {
551
+ // 大班数据上报
552
+ try {
553
+ dabanDataReport({
554
+ action: 'interact_play',
555
+ teammate_streamid: _d.streamid,
556
+ uid: window.zbztAVSDK_init_params.rtc.userId
557
+ });
558
+ } catch(e) {
559
+ }
560
+ }
561
+ try{
562
+ NOTICE.firstVideoSize({
563
+ userId: util.getUidByStreamId(_d.streamid),
564
+ streamId: _d.streamid,
565
+ allData: _d
566
+ });
567
+ dataReport.firstVideoSize({
568
+ pull_streamid: _d.streamid,
569
+ pull_uid: util.getUidByStreamIdDr(_d.streamid),
570
+ code:'0'
571
+ });
572
+ } catch (e) { };
573
+ pullResultReport(0, _d.streamid);
574
+ defaultApi.writeLog(`RTC: pullStream success & haveFirstVideoSize streamId: ${_d.streamid}`);
575
+ break;
576
+ case '2014':
577
+ try{
578
+ NOTICE.firstAudioSize({
579
+ userId: util.getUidByStreamId(_d.streamid),
580
+ streamId: _d.streamid,
581
+ allData: _d
582
+ });
583
+ dataReport.firstAudioSize({
584
+ pull_streamid: _d.streamid,
585
+ pull_uid: util.getUidByStreamIdDr(_d.streamid),
586
+ code:'0'
587
+ });
588
+ } catch (e) { };
589
+ break;
590
+ default:
591
+ break;
592
+ }
593
+ if (rtcPlayerErrorCodes.includes(code)) {
594
+ if (code == 2003) { //对端未推流
595
+ let first_time_marker = new Date().getTime();
596
+ if (!stStreamNotReadyReport.hasOwnProperty(_d.streamid)) {
597
+ stStreamNotReadyReport[_d.streamid] = new Date().getTime();
598
+ pullResultReport(code, _d.streamid);
599
+ } else {
600
+ if (first_time_marker - stStreamNotReadyReport[_d.streamid] >= 10*1000) {
601
+ pullResultReport(code, _d.streamid);
602
+ stStreamNotReadyReport[_d.streamid] = new Date().getTime();
603
+ }
604
+ }
605
+ } else {
606
+ pullResultReport(code, _d.streamid);
607
+ }
608
+ };
609
+ NOTICE.playErrorDetail({
610
+ type: rtcPlayerCodeToNames[code],
611
+ data: {
612
+ userId: util.getUidByStreamId(_d.streamid),
613
+ streamId: _d.streamid,
614
+ allData: _d
615
+ }
616
+ });
617
+ }
618
+ }
619
+ break;
620
+ case 'beforeCombineCapInfoMsg':
621
+ {
622
+ screenEncodeBefore = _d.width+'*'+_d.height;
623
+ try {
624
+ dataReport.splitState({
625
+ camera_split_start_resolution : captureBefore ,//云控取一直不变ok
626
+ camera_split_start_encode_resolution : captureEncodeBefore ,//摄像头拼接前编码分辨率云控拿取
627
+ screen_split_start_encode_resolution: screenEncodeBefore ,//截屏窗拼接前编码分辨率 东奇提供
628
+ screen_split_start_resolution :screenEncodeBefore ,//截屏窗拼接前采集分辨率
629
+ split:'开始拼接'
630
+ });
631
+ } catch (e){};
632
+ }
633
+ break;
634
+ case 'afterCombineInfoMsg':
635
+ {
636
+ captureEncodeAfter = _d.head_width+ '*'+ _d.head_height;
637
+ screenEncodeAfter = _d.cap_width+'*'+_d.cap_height;
638
+ try {
639
+ dataReport.splitState({
640
+ camera_split_end_resolution : captureAfter ,//云控取一直不变ok
641
+ camera_split_end_encode_resolution : captureEncodeAfter ,//摄像头拼接后编码分辨率
642
+ screen_split_end_encode_resolution: screenEncodeAfter ,//截屏窗拼接后编码分辨率
643
+ screen_split_end_resolution :screenEncodeAfter,//截屏窗拼接后采集分辨率
644
+ split:'拼接完成'
645
+ });
646
+ } catch (e){};
647
+ }
648
+ break;
649
+ }
650
+ // 去掉声音回调日志
651
+ if(zbztsdk.openListenerLog) {
652
+ console.log(`[zbzt-live-sdk]--RTC::Listener:: event: ${name}, data: ${data}`);
653
+ }
654
+ }
655
+ });
656
+ }
657
+ };
658
+
659
+ //拉流上报
660
+ const pullResultReport = (code, streamid) => {
661
+ try {
662
+ dataReport.pullResult({
663
+ code: code,
664
+ pull_uid: util.getUidByStreamId(streamid),
665
+ pull_streamid: streamid
666
+ });
667
+ NOTICE.pullFlowResult({code:code,pull_streamid: streamid});
668
+ } catch (e) {};
669
+ };
670
+
671
+
672
+ /**
673
+ * @function 添加扩展监听机制
674
+ * @return void
675
+ */
676
+ const removerListener = () => {
677
+ hasAddListener = false;
678
+ defaultApi.writeLog(`RTC::action--removerListener EMListenerId:${EMListenerId}`);
679
+ EM.RemoverListener(extensionId, EMListenerId, (ec, content) => {});
680
+ EMListenerId = 0;
681
+ };
682
+
683
+
684
+ /**
685
+ * @function 推流异常恢复
686
+ */
687
+ export const pushFlowExceptionHandler = async () => {
688
+ await new Promise((resolve, reject) => {
689
+ setTimeout(() => {
690
+ resolve();
691
+ }, 1000);
692
+ });
693
+ defaultApi.writeLog('断网重推');
694
+ defaultApi.writeLog('avsdk RTC::try to pushFlow again');
695
+ await stopPush();
696
+ await startPush();
697
+ };
698
+
699
+ /**
700
+ * @function 拉流异常恢复
701
+ */
702
+ export const pullFlowExceptionHandler = async (streamId) => {
703
+ await new Promise((resolve, reject) => {
704
+ setTimeout(() => {
705
+ resolve();
706
+ }, 1000);
707
+ });
708
+ defaultApi.writeLog('断网重拉');
709
+ defaultApi.writeLog(`avsdk RTC::try to pullFlow again, streamId : ${streamId}`);
710
+ await stop(streamId);
711
+ await play(streamId);
712
+ };
713
+
714
+ /**
715
+ * @function 设置 appId
716
+ * @param appId:String 长度不能大于 100,必选
717
+ * @return Promise | void
718
+ */
719
+ export const setAppId = (appId) => {
720
+ return callMethod('SetAppId', {
721
+ appId
722
+ });
723
+ };
724
+
725
+ /**
726
+ * @function 设置用户名
727
+ * @param userName:String 用户名,必选
728
+ * @return Promise | void
729
+ */
730
+ export const setUserName = (userName) => {
731
+ return callMethod('SetUserName', {
732
+ userName
733
+ });
734
+ };
735
+
736
+ /**
737
+ * @function 设置用户 id
738
+ * @param userId:Number 用户 id,必选
739
+ * @return Promise | void
740
+ */
741
+ export const setUserId = (userId) => {
742
+ return callMethod('SetUserId', {
743
+ userId: userId + ''
744
+ });
745
+ };
746
+
747
+ /**
748
+ * @function 设置课节 id
749
+ * @param confId:String 长度不能大于 100
750
+ * @return Promise | void
751
+ */
752
+ export const setConfId = (confId) => {
753
+ defaultApi.writeLog(`RTC SetConfId: ${confId}`);
754
+ _confId = confId;
755
+ return callMethod('SetConfId', {
756
+ confId
757
+ });
758
+ };
759
+
760
+ /**
761
+ * @function 进入音视频房间
762
+ * @return Promise | void
763
+ */
764
+ export const joinRtcRoom = async () => {
765
+ await callMethod('JoinRoom', {});
766
+ return new Promise((resolve, reject) => {
767
+ let timer = setInterval(() => {
768
+ if (hasJoinRtcRoom) {
769
+ clearInterval(timer);
770
+ resolve();
771
+ }
772
+ }, 50);
773
+ });
774
+ };
775
+
776
+ /**
777
+ * @function 退出音视频房间
778
+ * @return Promise | void
779
+ */
780
+ export const leaveRtcRoom = async () => {
781
+ await callMethod('LeaveRoom', {});
782
+ return new Promise((resolve, reject) => {
783
+ let timer = setInterval(() => {
784
+ if (hasLeaveRtcRoom) {
785
+ clearInterval(timer);
786
+ resolve();
787
+ }
788
+ }, 50);
789
+ });
790
+ };
791
+
792
+ /**
793
+ * @function 开始混流
794
+ * @param args:Object 混流设置信息
795
+ * @return Promise | void
796
+ * {
797
+ 'sequence':x,//混流任务序列号
798
+ 'inputStreams':[
799
+ {
800
+ 'confId':'xxx',
801
+ 'streamId':'xxxx',
802
+ 'mediaControl':x,//0所有1音频2视频
803
+ 'left':x,
804
+ 'top':x,
805
+ 'right':x,
806
+ 'bottom':x
807
+ }
808
+ ],
809
+ 'outputStream':{
810
+ 'pushType';x,
811
+ 'rtmpUrls';'xxx',
812
+ 'videoFps':x,//视频帧率
813
+ 'videoRate':x,//视频码率
814
+ 'audioRate':x,//音频码率
815
+ 'videoWidth':x,//合成视频宽度
816
+ 'videoHeight':x,//合成视频高度
817
+ 'audioFormat':x,//音频格式,0aac
818
+ 'audioChannels':x,//音频声道数目
819
+ 'backgroudColor':x//背景色10进制?
820
+ }
821
+ }
822
+ */
823
+ export const startRoomMixRecord = (args) => {
824
+ return callMethod('StartRoomMixRecord', args);
825
+ };
826
+
827
+ /**
828
+ * @function 开始混流 id
829
+ * @param args: Object 停止混流设置信息
830
+ * {'sequence':x}//混流任务序列号
831
+ * @return Promise | void
832
+ */
833
+ export const stopRoomMixRecord = (args) => {
834
+ return callMethod('StopRoomMixRecord', args);
835
+ };
836
+
837
+ /**
838
+ * @function 开始单路录制--暂停使用
839
+ * @param sequence: String
840
+ * @param streamId: String 流 id
841
+ * @return Promise | void
842
+ */
843
+ export const startSingleRecord = (sequence = '', streamId) => {
844
+ return callMethod('StartSingleRecord', { sequence, streamId, confId: _getConfId(streamId) });
845
+ };
846
+
847
+ /**
848
+ * @function 停止单路录制--暂停使用
849
+ * @param streamId: String 停止混流设置信息
850
+ * @return Promise | void
851
+ */
852
+ export const stopSingleRecord = (streamId) => {
853
+ return callMethod('StopSingleRecord', { streamId, confId: _getConfId(streamId) });
854
+ };
855
+
856
+ /**
857
+ * @function 创建 Rtc Capture对象
858
+ * @param renderId:String 采集器的渲染 id,必选
859
+ * @return Promise | void
860
+ */
861
+ export const createRtcCapture = (renderId) => {
862
+ if (renderId === 'deviceCheckerInit' && deviceCheckerCaptureInit) {
863
+ return;
864
+ }
865
+ return callMethod('CreateRtcCapture', {
866
+ source: 'camera',
867
+ renderid: renderId
868
+ });
869
+ };
870
+
871
+ // 设置采集器配置
872
+ const setRtcCaptureParams = async (args ,from) => {
873
+ if (!from) {
874
+ await setCaptureRenderID(args.streamId);
875
+ await setCaptureStreamId(args.streamId);
876
+ }
877
+ await setCameraParam(args.previewResolutionWidth, args.previewResolutionHeight, args.previewCaptureFps);
878
+ await setEncodeParam(args.encodedResolutionWidth, args.encodedResolutionHeight, args.encodeCaptureFps);
879
+ await setBitRate(args.encodeCaptureBitrate);
880
+ };
881
+
882
+ /**
883
+ * @function 加载采集插件的输入数据 //调用后,rtc 可以向采集插件传送摄像头数据,用于拼接
884
+ * @return: Promise
885
+ */
886
+ const rtcLoadCollectionEntry = () => {
887
+ return callMethod('RtcLoadCollectionEntry', {});
888
+ };
889
+
890
+ /**
891
+ * @function 加载采集插件的输出数据 //调用后,rtc 可以向采集插件传送学生流数据(加载截屏插件,获取截屏插件设置拉流头像回调函数)
892
+ * @param stream_ids array 设置需要拼接的学生头像流id,按数组顺序拼接
893
+ * @return: Promise
894
+ */
895
+ export const rtcLoadCollectionEntry2 = (stream_ids) => {
896
+ return callMethod('RtcLoadCollectionEntry2', {stream_ids});
897
+ };
898
+
899
+ /**
900
+ * @function 获取摄像头个数
901
+ * @return Promise | void
902
+ */
903
+ export const getCameraDeviceCount = () => {
904
+ return callMethod('GetCameraDeviceCount', {});
905
+ };
906
+
907
+ /**
908
+ * @function 获取摄像头列表
909
+ * @return Promise | void
910
+ */
911
+ export const getCameraDevice = async () => {
912
+ let cameraListObject = JSON.parse((await callMethod('GetCameraDevice', {})).msg);
913
+ let cameraKeys = [];
914
+ if (cameraListObject) {
915
+ cameraKeys = Object.keys(cameraListObject);
916
+ }
917
+ let cameraList = [];
918
+ for (let i = 0, len = cameraKeys.length; i < len; i++) {
919
+ cameraList.push({
920
+ deviceId: cameraListObject[cameraKeys[i]].deviceID,
921
+ deviceName: cameraListObject[cameraKeys[i]].deviceName,
922
+ isDefault: cameraListObject[cameraKeys[i]].bDefault
923
+ });
924
+ deviceListReport.cameraList[cameraListObject[cameraKeys[i]].deviceID] = cameraListObject[cameraKeys[i]].deviceName;
925
+ // console.log('hsghsghsg_9',deviceListReport.cameraList);
926
+ }
927
+ if (!window.zbztAVSDK_device_checker_init) {
928
+ window.zbztAVSDK_device_checker_init = {};
929
+ }
930
+ if (!window.zbztAVSDK_device_checker_init.camera) {
931
+ window.zbztAVSDK_device_checker_init.camera = {};
932
+ }
933
+ window.zbztAVSDK_device_checker_init.camera.hasTest = true;
934
+ window.zbztAVSDK_device_checker_init.camera.list = cameraList;
935
+ return cameraList;
936
+ };
937
+
938
+ /**
939
+ * @function 获取扬声器个数
940
+ * @return Promise | void
941
+ */
942
+ export const getSpeakerDeviceCount = () => {
943
+ return callMethod('GetSpeakerDeviceCount', {});
944
+ };
945
+
946
+ /**
947
+ * @function 获取扬声器列表
948
+ * @return Promise | void
949
+ */
950
+ export const getSpeakerDevice = async () => {
951
+ let speakerListObject = JSON.parse((await callMethod('GetSpeakerDevice', {})).msg);
952
+ let speakerKeys = [];
953
+ if (speakerListObject) {
954
+ speakerKeys = Object.keys(speakerListObject);
955
+ }
956
+ let speakerList = [];
957
+ for (let i = 0, len = speakerKeys.length; i < len; i++) {
958
+ speakerList.push({
959
+ deviceId: speakerListObject[speakerKeys[i]].deviceID,
960
+ deviceName: speakerListObject[speakerKeys[i]].deviceName,
961
+ isDefault: speakerListObject[speakerKeys[i]].bDefault
962
+ });
963
+ deviceListReport.speakerList[speakerListObject[speakerKeys[i]].deviceID] = speakerListObject[speakerKeys[i]].deviceName;
964
+ // console.log('hsghsghsg_8',deviceListReport.speakerList);
965
+ }
966
+ if (!window.zbztAVSDK_device_checker_init) {
967
+ window.zbztAVSDK_device_checker_init = {};
968
+ }
969
+ if (!window.zbztAVSDK_device_checker_init.speaker) {
970
+ window.zbztAVSDK_device_checker_init.speaker = {};
971
+ }
972
+ window.zbztAVSDK_device_checker_init.speaker.hasTest = true;
973
+ window.zbztAVSDK_device_checker_init.speaker.list = speakerList;
974
+ return speakerList;
975
+ };
976
+
977
+ /**
978
+ * @function 获取麦克风个数
979
+ * @return Promise | void
980
+ */
981
+ export const getMicrophoneDeviceCount = () => {
982
+ return callMethod('GetMicrophoneDeviceCount', {});
983
+ };
984
+
985
+ /**
986
+ * @function 获取麦克风列表
987
+ * @return Promise | void
988
+ */
989
+ export const getMicrophoneDevice = async () => {
990
+ let microphoneListObject = JSON.parse((await callMethod('GetMicrophoneDevice', {})).msg);
991
+ let microphoneKeys = [];
992
+ if (microphoneListObject) {
993
+ microphoneKeys = Object.keys(microphoneListObject);
994
+ }
995
+ let microphoneList = [];
996
+ for (let i = 0, len = microphoneKeys.length; i < len; i++) {
997
+ microphoneList.push({
998
+ deviceId: microphoneListObject[microphoneKeys[i]].deviceID,
999
+ deviceName: microphoneListObject[microphoneKeys[i]].deviceName,
1000
+ isDefault: microphoneListObject[microphoneKeys[i]].bDefault
1001
+ });
1002
+ deviceListReport.micList[microphoneListObject[microphoneKeys[i]].deviceID] = microphoneListObject[microphoneKeys[i]].deviceName;
1003
+ }
1004
+ if (!window.zbztAVSDK_device_checker_init) {
1005
+ window.zbztAVSDK_device_checker_init = {};
1006
+ }
1007
+ if (!window.zbztAVSDK_device_checker_init.microphone) {
1008
+ window.zbztAVSDK_device_checker_init.microphone = {};
1009
+ }
1010
+ window.zbztAVSDK_device_checker_init.microphone.hasTest = true;
1011
+ window.zbztAVSDK_device_checker_init.microphone.list = microphoneList;
1012
+ return microphoneList;
1013
+ };
1014
+
1015
+ /**
1016
+ * @function 指定麦克风设备
1017
+ * @param deviceId:String 麦克风设备 id,必选
1018
+ * @param operationType:String 操作类型,可选
1019
+ * 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
1020
+ * 不传即是普通的设置麦克风设备的行为
1021
+ * @return Promise | void
1022
+ */
1023
+ export const setMicrophoneDevice = async (args) => {
1024
+ let {deviceId, operationType, deviceState, changedDeviceId} = args;
1025
+ let deviceName = '';
1026
+ let microPhoneData;
1027
+ if (!deviceId) {
1028
+ microPhoneData = await getMicrophoneDevice();
1029
+ if (microPhoneData.length) {
1030
+ let hasGetMicrophone = false;
1031
+ for (let item of microPhoneData) {
1032
+ if (item.isDefault) {
1033
+ deviceId = item.deviceId;
1034
+ deviceName = item.deviceName;
1035
+ hasGetMicrophone = true;
1036
+ break;
1037
+ }
1038
+ }
1039
+ if (!hasGetMicrophone) {
1040
+ deviceId = microPhoneData[0].deviceId;
1041
+ deviceName = microPhoneData[0].deviceName;
1042
+ }
1043
+ } else {
1044
+ deviceId = '';
1045
+ }
1046
+ if (deviceId === '') {
1047
+ NOTICE.noDevice({
1048
+ deviceType: 'microphone'
1049
+ });
1050
+ }
1051
+ }
1052
+ try {
1053
+ dataReport.setDevice({
1054
+ device_type:2,
1055
+ device_id:deviceId,
1056
+ device_name:deviceListReport.micList[deviceId],
1057
+ operationType,
1058
+ fore_state: operationType == 'hotPlug' ? +deviceState+1 : '-'
1059
+ });
1060
+ window.zbztAVSDK_device_checker_init.microphone.name = deviceListReport.micList[deviceId];
1061
+ } catch (e) {};
1062
+ await callMethod('SetAudioDevice', {
1063
+ deviceID: deviceId
1064
+ });
1065
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
1066
+ if(!microPhoneData){
1067
+ microPhoneData = await getMicrophoneDevice();
1068
+ deviceName = deviceListReport.micList[deviceId];
1069
+ }
1070
+ NOTICE[operationType]({
1071
+ deviceType: 'microphone',
1072
+ useDeviceId: deviceId,
1073
+ useDeviceName: deviceName,
1074
+ deviceList: microPhoneData,
1075
+ deviceState,
1076
+ changedDeviceId
1077
+ });
1078
+ }
1079
+ };
1080
+
1081
+ /**
1082
+ * @function 获取麦克风音量
1083
+ * @return Promise | void
1084
+ */
1085
+ export const getMicrophoneVolume = () => {
1086
+ return callMethod('GetMicrophoneVolume', {});
1087
+ };
1088
+
1089
+ /**
1090
+ * @function 设置麦克风音量
1091
+ * @param volume:Number 音量,必选
1092
+ * @param bMuteDevice:Boolean 是否静音,可选
1093
+ * 不传的话默认为 false 不静音
1094
+ * @return Promise | void
1095
+ */
1096
+ export const setMicrophoneVolume = (volume, bMuteDevice) => {
1097
+ if (typeof bMuteDevice === 'undefined') {
1098
+ bMuteDevice = false;
1099
+ }
1100
+ return callMethod('SetMicrophoneVolume', {
1101
+ bMuteDevice,
1102
+ volume
1103
+ });
1104
+ };
1105
+
1106
+ /**
1107
+ * @function 开启/关闭麦克风音量回调
1108
+ * @param open:Boolean true -> 开启,false -> 关闭,必选
1109
+ * @return void
1110
+ */
1111
+ export const openMicVolumeCb = (open) => {
1112
+ // if (open) {
1113
+ // runMicVolumeCb = true;
1114
+ // } else {
1115
+ // runMicVolumeCb = false;
1116
+ // }
1117
+ };
1118
+
1119
+ /**
1120
+ * @function 获取当前应用程序音量
1121
+ * @return Promise | void
1122
+ */
1123
+ export const getCurrentAppSessionVolume = () => {
1124
+ return callMethod('GetCurrentAppSessionVolume', {});
1125
+ };
1126
+
1127
+ /**
1128
+ * @function 设置当前应用程序音量
1129
+ * @param volume:Number 音量,必选
1130
+ * @param mute:Boolean 是否静音,可选
1131
+ * 不传的话默认为 false 不静音
1132
+ * @return Promise | void
1133
+ */
1134
+ export const setCurrentAppSessionVolume = (volume, mute) => {
1135
+ if (typeof mute === 'undefined') {
1136
+ mute = false;
1137
+ }
1138
+ return callMethod('SetCurrentAppSessionVolume', {
1139
+ muted: mute,
1140
+ volume
1141
+ });
1142
+ };
1143
+
1144
+ /**
1145
+ * @function 设置当前应用程序静音
1146
+ * @param mute:Boolean 是否静音,必选
1147
+ * @return Promise | void
1148
+ */
1149
+ export const setApplicationMute = (mute) => {
1150
+ return callMethod('SetApplicationMute', {
1151
+ muted: mute
1152
+ });
1153
+ };
1154
+
1155
+ /**
1156
+ * @function 设置预览窗口
1157
+ * @param x:Number x 坐标,必选,推荐 0
1158
+ * @param y:Number y 坐标,必选,推荐 0
1159
+ * @param width:Number 宽,必选,推荐 300
1160
+ * @param height:Number 高,必选,推荐 300
1161
+ * @return Promise | void
1162
+ */
1163
+ export const setPreviewPos = (x, y, width, height) => {
1164
+ return callMethod('SetPreviewPos', {
1165
+ x,
1166
+ y,
1167
+ width,
1168
+ height
1169
+ });
1170
+ };
1171
+
1172
+ /**
1173
+ * @function 指定摄像头设备
1174
+ * @param deviceId:String 摄像头设备 id,必选
1175
+ * @param close:Boolean true -> 关闭摄像头,false -> 不关闭摄像头
1176
+ * Rtc 关闭摄像头是通过指定空的设备来实现的,因此需要做特化
1177
+ * @param operationType:String 操作类型,可选
1178
+ * 'device_error' -> 设备出错处理,'plug_and_unplug' -> 热插拔处理,
1179
+ * 不传即是普通的设置摄像头设备的行为
1180
+ * @return Promise | void
1181
+ */
1182
+ export const setCameraDevice = async (args) => {
1183
+ defaultApi.writeLog(`sdk action : setCameraDevice args:${JSON.stringify(args)}`);
1184
+ let {deviceId, close, operationType, deviceState, changedDeviceId} = args;
1185
+ let deviceName = '';
1186
+ let cameraData;
1187
+ if (!deviceId && !close) {
1188
+ cameraData = await getCameraDevice();
1189
+ if (cameraData.length) {
1190
+ let hasGetCamare = false;
1191
+ for (let item of cameraData) {
1192
+ if (item.isDefault) {
1193
+ deviceId = item.deviceId;
1194
+ deviceName = item.deviceName;
1195
+ hasGetCamare = true;
1196
+ break;
1197
+ }
1198
+ }
1199
+ if (!hasGetCamare) {
1200
+ deviceId = cameraData[0].deviceId;
1201
+ deviceName = cameraData[0].deviceName;
1202
+ }
1203
+ deviceId = cameraData[0].deviceId;
1204
+ deviceName = cameraData[0].deviceName;
1205
+ } else {
1206
+ deviceId = '';
1207
+ }
1208
+ if (deviceId === '') {
1209
+ NOTICE.noDevice({
1210
+ deviceType: 'camera'
1211
+ });
1212
+ }
1213
+ }
1214
+ try {
1215
+ dataReport.setDevice({
1216
+ device_type:1,
1217
+ device_id:deviceId,
1218
+ device_name:deviceListReport.cameraList[deviceId],
1219
+ operationType,
1220
+ fore_state: operationType == 'hotPlug' ? +deviceState+1 : '-'
1221
+ });
1222
+ window.zbztAVSDK_device_checker_init.camera.name = deviceListReport.cameraList[deviceId];
1223
+ } catch (e) {};
1224
+ await callMethod('SetCameraDevice', {
1225
+ deviceID: deviceId,
1226
+ close
1227
+ });
1228
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
1229
+ if(!cameraData){
1230
+ cameraData = await getCameraDevice();
1231
+ deviceName = deviceListReport.cameraList[deviceId];
1232
+ }
1233
+ NOTICE[operationType]({
1234
+ deviceType: 'camera',
1235
+ useDeviceId: deviceId,
1236
+ useDeviceName: deviceName,
1237
+ deviceList: cameraData,
1238
+ deviceState,
1239
+ changedDeviceId
1240
+ });
1241
+ }
1242
+ try {
1243
+ NOTICE.useredCamera({
1244
+ deviceId,
1245
+ deviceName
1246
+ });
1247
+ } catch (e){ };
1248
+ };
1249
+
1250
+ /**
1251
+ * @function 获取摄像头所支持的分辨率
1252
+ * @param deviceId:String 设备id
1253
+ * @return Promise | void
1254
+ */
1255
+ export const getCameraSupportedRes = (deviceId) => {
1256
+ return callMethod('GetCameraSupportedResolution', {
1257
+ deviceId
1258
+ });
1259
+ };
1260
+
1261
+ /**
1262
+ * @function 设置事件上报链接
1263
+ * @param reportSvr:String 上报服务器链接,必选
1264
+ * @return Promise | void
1265
+ */
1266
+ export const setEventReportSvr = (reportSvr) => {
1267
+ return callMethod('SetEventReportSvr', {
1268
+ reportSvr
1269
+ });
1270
+ };
1271
+
1272
+ /**
1273
+ * @function 设置摄像头参数
1274
+ * @param width:Number 分辨率宽,必选,推荐 1280
1275
+ * @param height:Number 分辨率高,必选,推荐 720
1276
+ * @param frameRate:Number 帧率,必选,推荐 15
1277
+ * @return Promise | void
1278
+ */
1279
+ export const setCameraParam = (width, height, frameRate) => {
1280
+ return callMethod('SetCameraParam', {
1281
+ width,
1282
+ height,
1283
+ frameRate
1284
+ });
1285
+ };
1286
+
1287
+ /**
1288
+ * @function 指定扬声器
1289
+ * @param speakId:String 扬声器 id,必选
1290
+ * @return Promise | void
1291
+ */
1292
+ export const setSpeakerDevice = async (args) => {
1293
+ defaultApi.writeLog(`sdk action : setSpeakerDevice args:${JSON.stringify(args)}`);
1294
+ let {speakId, operationType, deviceState, changedDeviceId} = args;
1295
+ let deviceName = '';
1296
+ let speakerData;
1297
+ if (!speakId) {
1298
+ speakerData = await getSpeakerDevice();
1299
+ if (speakerData.length) {
1300
+ let hasGetSpeaker = false;
1301
+ for (let item of speakerData) {
1302
+ if (item.isDefault) {
1303
+ speakId = item.deviceId;
1304
+ deviceName = item.deviceName;
1305
+ hasGetSpeaker = true;
1306
+ break;
1307
+ }
1308
+ }
1309
+ if (!hasGetSpeaker) {
1310
+ speakId = speakerData[0].deviceId;
1311
+ deviceName = speakerData[0].deviceName;
1312
+ }
1313
+ } else {
1314
+ speakId = '';
1315
+ }
1316
+ if (speakId === '') {
1317
+ NOTICE.noDevice({
1318
+ deviceType: 'speaker'
1319
+ });
1320
+ }
1321
+ }
1322
+ try {
1323
+ dataReport.setDevice({
1324
+ device_type:3,
1325
+ device_id:speakId,
1326
+ device_name:deviceListReport.speakerList[speakId],
1327
+ operationType,
1328
+ fore_state: operationType == 'hotPlug' ? +deviceState+1 : '-'
1329
+ });
1330
+ window.zbztAVSDK_device_checker_init.speaker.name = deviceListReport.speakerList[speakId];
1331
+ } catch (e) {
1332
+ console.error('error',e);
1333
+ };
1334
+ // console.log('hsghsghsg3',speakId);
1335
+ await callMethod('SetSpeakerDevice', {
1336
+ speakId
1337
+ });
1338
+ if (operationType == 'hotPlug' || operationType == 'deviceError') {
1339
+ if(!speakerData){
1340
+ speakerData = await getSpeakerDevice();
1341
+ deviceName = deviceListReport.speakerList[speakId];
1342
+ }
1343
+ NOTICE[operationType]({
1344
+ deviceType: 'speaker',
1345
+ useDeviceId: speakId,
1346
+ useDeviceName: deviceName,
1347
+ deviceList: speakerData,
1348
+ deviceState,
1349
+ changedDeviceId
1350
+ });
1351
+ }
1352
+ };
1353
+
1354
+ /**
1355
+ * @function 设置扬声器音量
1356
+ * @param volume:Number 音量,必选
1357
+ * @param muted:Boolean 是否静音,可选
1358
+ * 不传的话就默认为 false 不静音
1359
+ * @return Promise | void
1360
+ */
1361
+ export const setSpeakerVolume = (volume, muted) => {
1362
+ if (typeof muted === 'undefined') {
1363
+ muted = false;
1364
+ }
1365
+ return callMethod('SetSpeakerVolume', {
1366
+ muted,
1367
+ volume
1368
+ });
1369
+ };
1370
+
1371
+ /**
1372
+ * @function 设置扬声器静音
1373
+ * @param mute:Boolean 是否静音,可选
1374
+ * @return Promise | void
1375
+ */
1376
+ export const setSpeakerMute = (mute) => {
1377
+ // try {
1378
+ // dataReport.deviceChange({
1379
+ // device: 3,
1380
+ // device_state: mute ? 0 :1
1381
+ // });
1382
+ // } catch (e){};
1383
+ return callMethod('SetSpeakerMute', {
1384
+ muted: mute
1385
+ });
1386
+ };
1387
+
1388
+ /**
1389
+ * @function 获取扬声器音量
1390
+ * @return Promise | void
1391
+ */
1392
+ export const getSpeakerVolume = () => {
1393
+ return callMethod('GetSpeakerVolume', {});
1394
+ };
1395
+
1396
+ /**
1397
+ * @function 设置拉流的播放器静音
1398
+ * @param streamId:String 被拉取的流的 id,必选
1399
+ * @param mute:Boolean 是否静音,必选 true 静音| false不静音
1400
+ * @return Promise | void
1401
+ */
1402
+ export const setMute = (streamId, mute) => {
1403
+ const rtcPlayerId = streamIdToRtcPlayerId[streamId];
1404
+ return pullAudioFlow(rtcPlayerId, mute);
1405
+ };
1406
+
1407
+ /**
1408
+ * @function 是否拉取音频流--通过播放器id控制
1409
+ * @param operation:Boolean,必选,true 静音| false不静音
1410
+ * @param playerId:Number,必选,播放器id
1411
+ * @return Promise | void
1412
+ */
1413
+ export const pullAudioFlow = (playerId, operation, operator, streamid) => {
1414
+ defaultApi.writeLog(`pullAudioFlow -- playerId ${playerId} operation ${operation} streamId ${streamid}`);
1415
+ if(streamid){
1416
+ if(streamIdToRtcPlayerId[streamid] == undefined) {
1417
+ NOTICE.pullAudioFlowError({streamid})
1418
+ return
1419
+ }else{
1420
+ playerId = streamIdToRtcPlayerId[streamid]
1421
+ console.log('pullAudioFlow-playerId',playerId,streamIdToPreviewId)
1422
+ }
1423
+ }
1424
+ let streamId = rtcPlayerIdToStreamId[playerId];
1425
+ try {
1426
+ streamIdRtcPlayerInfo1[streamId].audio_type = !operation;
1427
+ console.log('pullAudioFlow_rtc ::rtcPlayerIdToStreamId',streamId,rtcPlayerIdToStreamId)
1428
+ console.log('pullAudioFlow_rtc ::streamIdRtcPlayerInfo1',streamId,streamIdRtcPlayerInfo1);
1429
+ } catch (e) {
1430
+ console.log('pullAudioFlow_rtc ::streamIdRtcPlayerInfo1--error',e);
1431
+ };
1432
+ // console.log('hghghg',streamIdRtcPlayerInfo1[streamId]);
1433
+ try {
1434
+ if(operator) {
1435
+ dataReport.setPullVoice({
1436
+ code:+!operation,
1437
+ pull_uid: util.getUidByStreamId(streamId),
1438
+ pull_streamid:streamId,
1439
+ playerId
1440
+ });
1441
+ }
1442
+ } catch (e) {};
1443
+ return callMethod('SetMute', {
1444
+ muted: operation,
1445
+ id: playerId
1446
+ });
1447
+ };
1448
+
1449
+ /**
1450
+ * @function 控制只拉音频流
1451
+ * @param streamId:String 被拉取的流的 id,必选
1452
+ * @param audioOnly:Boolean 是否只拉音频流,必选,true -> 只拉音频流,false -> 音视频都拉
1453
+ * @return Promise | void
1454
+ */
1455
+ export const controlPullAudioOnly = (streamId, audioOnly) => {
1456
+ try {
1457
+ streamIdRtcPlayerInfo1[streamId].video_type = !audioOnly;
1458
+ console.log('controlPullAudioOnly_rtc ::streamIdRtcPlayerInfo1',streamId,streamIdRtcPlayerInfo1);
1459
+ } catch (e) {
1460
+ console.log('controlPullAudioOnly_rtc ::streamIdRtcPlayerInfo1--error',e);
1461
+ }
1462
+ const rtcPlayerId = streamIdToRtcPlayerId[streamId];
1463
+ return callMethod('ControlPullAudioOnly', {
1464
+ id: rtcPlayerId,
1465
+ audioOnly
1466
+ });
1467
+ };
1468
+
1469
+ /**
1470
+ * @function 启动摄像头
1471
+ * @return Promise | void
1472
+ */
1473
+ export const startPreview = () => {
1474
+ // try {
1475
+ // dataReport.deviceChange({
1476
+ // device: 1,
1477
+ // device_state: 1
1478
+ // });
1479
+ // } catch (e){};
1480
+ return callMethod('StartPreview', {});
1481
+ };
1482
+
1483
+ /**
1484
+ * @function 设置推流的编码参数
1485
+ * @param width:Number 宽,必须,推荐 1280
1486
+ * @param height:Number 高,必须,推荐 720
1487
+ * @param frameRate:Number 码率,必须,推荐 15
1488
+ * @return Promise | void
1489
+ */
1490
+ export const setEncodeParam = (width, height, frameRate) => {
1491
+ return callMethod('SetEncodeParam', {
1492
+ width,
1493
+ height,
1494
+ frameRate
1495
+ });
1496
+ };
1497
+
1498
+ /**
1499
+ * @function 设置推流的比特率
1500
+ * @param bps:Number 码率,必选,推荐 512000
1501
+ * @return Promise | void
1502
+ */
1503
+ export const setBitRate = (bps) => {
1504
+ return callMethod('SetBitRate', {
1505
+ bps
1506
+ });
1507
+ };
1508
+
1509
+ /**
1510
+ * @function 设置推流的的 streamId
1511
+ * @param streamId:String 推流 id,必选,长度不能超过100个字符
1512
+ * @return Promise | void
1513
+ */
1514
+ export const setCaptureStreamId = (streamId) => {
1515
+ return callMethod('SetCaptureStreamId', {
1516
+ streamid: streamId
1517
+ });
1518
+ };
1519
+
1520
+ /**
1521
+ * @function 设置本地摄像头采集器的渲染 id
1522
+ * @param renderId:String 渲染 id,传入推流 id 即可,必选
1523
+ * @return Promise | void
1524
+ */
1525
+ export const setCaptureRenderID = (renderId) => {
1526
+
1527
+ return callMethod('SetCaptureRenderID', {
1528
+ renderid: renderId
1529
+ });
1530
+ };
1531
+
1532
+ /**
1533
+ * @function 开始推流到服务器
1534
+ * 如果收到 error,SDK 回到 startPush 之前的状态,
1535
+ * 应用程序需要重新设置正确的参数,并 startPush
1536
+ * @return Promise | void
1537
+ */
1538
+ export const startPush = () => {
1539
+ if (!isFirstHeartBeatReport) {
1540
+ isFirstHeartBeatReport = true;
1541
+ heartBeatDataReport('start');
1542
+ }
1543
+ return callMethod('StartPush', {});
1544
+ };
1545
+
1546
+ /**
1547
+ * @function 停止推流
1548
+ * @return Promise | void
1549
+ */
1550
+ export const stopPush = () => {
1551
+ // try {
1552
+ // dataReport.stopPublish({publish_streamid:window.zbztAVSDK_init_params.rtc.streamId});
1553
+ // } catch (error) {
1554
+ // }
1555
+ return callMethod('StopPush', {});
1556
+ };
1557
+
1558
+ /**
1559
+ * @function 关闭摄像头
1560
+ * @return Promise | void
1561
+ */
1562
+ export const stopPreview = () => {
1563
+ // try {
1564
+ // dataReport.deviceChange({
1565
+ // device: 1,
1566
+ // device_state: 0
1567
+ // });
1568
+ // } catch (e){};
1569
+ return callMethod('StopPreview', {});
1570
+ };
1571
+
1572
+ /**
1573
+ * @function 销毁采集器对象
1574
+ * @return Promise | void
1575
+ */
1576
+ export const captureDestroy = async () => {
1577
+ await stopPreview();
1578
+ return callMethod('CaptureDestroy', {});
1579
+ };
1580
+
1581
+ /**
1582
+ * @function 销毁引擎
1583
+ * @return Promise | void
1584
+ */
1585
+ export const destroyEngine = () => {
1586
+ return callMethod('DestroyEngine', {});
1587
+ };
1588
+
1589
+ /**
1590
+ * @function 创建视频播放器
1591
+ * @param pos:Object
1592
+ * {
1593
+ * x, // Number,x 坐标,必选,推荐 500
1594
+ * y, // Number,y 坐标,必选,推荐 500
1595
+ * width, // Number,宽,必选,推荐 300
1596
+ * height // Number,高,必选,推荐 300
1597
+ * }
1598
+ * @param renderId:String,渲染 id,必选
1599
+ * @return Promise | void
1600
+ */
1601
+ export const createRtcPlayer = (pos, renderId) => {
1602
+ return callMethod('CreateRtcPlayer', {
1603
+ pos,
1604
+ renderid: renderId
1605
+ });
1606
+ };
1607
+
1608
+ /**
1609
+ * @function 设置被拉取的流的 id
1610
+ * @param streamId:String 被拉取的流的 id,必选
1611
+ * @return Promise | void
1612
+ */
1613
+ export const setPlayerStreamId = (rtcPlayerId, streamId) => {
1614
+ const args = {
1615
+ streamid: streamId,
1616
+ id: rtcPlayerId,
1617
+ // 跨组拉流
1618
+ confId: _getConfId(streamId)
1619
+ };
1620
+
1621
+ defaultApi.writeLog(`RTC::SetPlayerStreamId streamId: ${streamId} id: ${rtcPlayerId} confId:
1622
+ ${util.getDataFromStreamUrl('roomId', streamId)}
1623
+ args : ${JSON.stringify(args)}
1624
+ `);
1625
+
1626
+ return callMethod('SetPlayerStreamId', args);
1627
+ };
1628
+
1629
+ /**
1630
+ * @function 设置被拉取的流的渲染 id
1631
+ * @param renderId:String 拉流的渲染 id,必选,传入被拉取的流的 id 即可
1632
+ * @return Promise | void
1633
+ */
1634
+ export const setPlayRenderID = (rtcPlayerId, renderId) => {
1635
+ defaultApi.writeLog(`RTC::SetPlayRenderID streamId: ${renderId} id: ${rtcPlayerId}`);
1636
+ return callMethod('SetPlayRenderID', {
1637
+ renderid: renderId,
1638
+ id: rtcPlayerId
1639
+ });
1640
+ };
1641
+
1642
+ /**
1643
+ * @function 关闭客户端
1644
+ * @param streamId:String 被拉取的流的 id,必选
1645
+ * @return Promise | void
1646
+ */
1647
+ export const playDestroy = (streamId) => {
1648
+ const rtcPlayerId = streamIdToRtcPlayerId[streamId];
1649
+ defaultApi.writeLog(`RTC::PlayDestroy streamId: ${streamId} id: ${rtcPlayerId}`);
1650
+ delete streamIdToRtcPlayerId[streamId];
1651
+ delete streamIdRtcPlayerInfo[streamId];
1652
+ return callMethod('PlayDestroy', {
1653
+ id: rtcPlayerId
1654
+ });
1655
+ };
1656
+
1657
+ /**
1658
+ * @function 开启本地或者远程的视频视图
1659
+ * @param isLocal:Boolean 是否是本地的视频预览,必选
1660
+ * @param streamId:String 要拉取的视频流的 id,可选,只有拉取远程的视频流的时候才是必选的
1661
+ * @param domId:String <video> 标签的 id,可选
1662
+ * 如果传了 domId,就把视频绑定到对应的 <video> 标签上
1663
+ * @return Promise | void,可从 Promise 中获取 src,Promise.then((src) => {})
1664
+ */
1665
+ export const startLocalOrRemotePreview = async (isLocal, streamId, domId, rtcPlayerId) => {
1666
+ defaultApi.writeLog(`${streamId}----streamId-rtc----`);
1667
+ let isUpdateChromeVersion = await util.getChromeVersion();
1668
+ // 预览本地视频的话,流 id 从全局配置中获取
1669
+ if (isLocal) {
1670
+ streamId = isInRoom ? (window.zbztAVSDK_init_params && window.zbztAVSDK_init_params.rtc.streamId)
1671
+ : 'deviceCheckerInit';
1672
+ }
1673
+ const externalConstraints = {
1674
+ audio: false,
1675
+ video: {
1676
+ mandatory: {
1677
+ chromeMediaSource: 'external',
1678
+ chromeMediaSourceId: `ems://TM/${streamId}`
1679
+ }
1680
+ }
1681
+ };
1682
+
1683
+ return new Promise((resolve, reject) => {
1684
+ const handleExternalSuccess = (stream) => {
1685
+ defaultApi.writeLog(`${stream}----stream-rtc----`);
1686
+ stream.oninactive = () => {
1687
+ defaultApi.writeLog('Stream inactive');
1688
+ };
1689
+ const src = isUpdateChromeVersion? stream : window.URL.createObjectURL(stream);
1690
+ console.log('内核升级', isUpdateChromeVersion);
1691
+ if (domId && document.querySelector(domId)) {
1692
+ if(isUpdateChromeVersion) {
1693
+ console.log('内核升级1');
1694
+ document.querySelector(domId).srcObject = src;
1695
+ } else {
1696
+ console.log('内核升级2');
1697
+ document.querySelector(domId).src = src;
1698
+ }
1699
+ }
1700
+ defaultApi.writeLog(`setVidoeSrc, rtcPlayerId: ${rtcPlayerId}, streamId:${streamId}, domId: ${domId}, src: ${src}`);
1701
+ resolve(src);
1702
+ };
1703
+
1704
+ const handleExternalError = (error) => {
1705
+ if (error.name === 'ConstraintNotSatisfiedError') {
1706
+ console.error('ConstraintNotSatisfiedError');
1707
+ } else if (error.name === 'PermissionDeniedError') {
1708
+ console.error(
1709
+ 'Permissions have not been granted to use your camera and '
1710
+ + 'microphone, you need to allow the page access to your devices in '
1711
+ + 'order for the demo to work.'
1712
+ );
1713
+ }
1714
+ console.error(`getUserMedia error: ${error.name}`, error);
1715
+ if (domId) {
1716
+ document.querySelector(domId).src = '';
1717
+ }
1718
+ reject('');
1719
+ };
1720
+
1721
+ if (navigator.webkitGetUserMedia) {
1722
+ navigator.webkitGetUserMedia(
1723
+ externalConstraints,
1724
+ handleExternalSuccess,
1725
+ handleExternalError
1726
+ );
1727
+ }
1728
+ });
1729
+ };
1730
+
1731
+ /**
1732
+ * @function 初始化
1733
+ * @param args:Object
1734
+ * {
1735
+ * extensionVersion, // String,扩展版本号,必选
1736
+ * appId, // String,Rtc 秘钥,必选
1737
+ * userName, // String,用户名,必选
1738
+ * userId, // Number,用户 id,必选
1739
+ * roomId, // String,房间 id,必选
1740
+ * streamId // String,流 id,必选
1741
+ * }
1742
+ * @return Promise | void
1743
+ */
1744
+ export const init = async (args) => {
1745
+ const usedDevices = window.zbztAVSDK_device_checker_init;
1746
+ let devices = args.devices;
1747
+ args.devices = {
1748
+ camera: (devices && devices.camera) || (usedDevices && usedDevices.camera && usedDevices.camera.use) || '',
1749
+ microphone: (devices && devices.microphone) || (usedDevices && usedDevices.microphone && usedDevices.microphone.use) || '',
1750
+ speaker: (devices && devices.speaker) || (usedDevices && usedDevices.speaker && usedDevices.speaker.use) || ''
1751
+ };
1752
+ await loadRtc(args.extensionVersion);
1753
+ // setStatisticsInterval(1000);
1754
+ addListener();
1755
+ await setAppId(args.appId);
1756
+ await setUserName(args.userName);
1757
+ await setUserId(args.userId);
1758
+ await setConfId(args.confId);
1759
+ // await joinRtcRoom();
1760
+ if (deviceCheckerCaptureInit) {
1761
+ await captureDestroy();
1762
+ deviceCheckerCaptureInit = false;
1763
+ }
1764
+ // if (args.role === 'teacher' && args.classMode === 1) {
1765
+ // await setUserRole(1);
1766
+ // }
1767
+ //小班课 需要加载采集插件的输入数据,为了拼接rtc头像
1768
+ if (args.classMode === 1 || args.classMode === 2){
1769
+ rtcLoadCollectionEntry();
1770
+ };
1771
+ await createRtcCapture(args.streamId);
1772
+ await setDefaultDevice(args.devices,'default');
1773
+ await setRtcCaptureParams(args);
1774
+ await setPreviewMute(true);
1775
+ await muteLocalVideo(true);
1776
+ await startPreview();
1777
+ isInRoom = true;
1778
+ window.current_sdk_type = 'rtc';
1779
+ defaultApi.writeLog('rtc init finished current_sdk_type : rtc');
1780
+ paramInfo = window.zbztAVSDK_init_params.rtc;
1781
+ captureBefore = paramInfo.encodedResolutionWidth+'*'+paramInfo.encodedResolutionHeight;//运控获取,一直不变(拼接前摄像头采集分辨率)
1782
+ captureEncodeBefore = paramInfo.previewResolutionWidth+'*'+paramInfo.previewResolutionHeight;//摄像头拼接前编码分辨率云控拿取
1783
+ captureAfter = captureBefore;
1784
+ };
1785
+
1786
+ /**
1787
+ * @function 恢复
1788
+ */
1789
+ export const recoverSdk = async (args) => {
1790
+ addListener();
1791
+ await setRtcCaptureParams(args);
1792
+ await setPreviewMute(true);
1793
+ _confId = args.confId;
1794
+ const zbzt_sdk_rtcPlayerIds = localStorage.getItem('zbzt_sdk_rtcPlayerIds');
1795
+ if (zbzt_sdk_rtcPlayerIds) {
1796
+ rtcPlayerIds = zbzt_sdk_rtcPlayerIds.split(',').map(item => +item);
1797
+ defaultApi.writeLog(`RTC sdk action : recoverSdk --> PlayDestroy --> rtcPlayerIds: ${rtcPlayerIds}`);
1798
+ if (rtcPlayerIds.length > 0) {
1799
+ for (let i = 0, len = rtcPlayerIds.length; i < len; i++) {
1800
+ await callMethod('PlayDestroy', {
1801
+ id: rtcPlayerIds[i]
1802
+ });
1803
+ }
1804
+ }
1805
+ }
1806
+ localStorage.removeItem('zbzt_sdk_rtcPlayerIds');
1807
+ isInRoom = true;
1808
+ window.current_sdk_type = 'rtc';
1809
+ defaultApi.writeLog('rtc recoverSdk finished current_sdk_type : rtc');
1810
+ };
1811
+
1812
+ export const stopCheckDevice = () => {
1813
+ deviceCheckerCaptureInit = false;
1814
+ removerListener();
1815
+ defaultApi.writeLog('rtc stopCheckDevice and removerListener and captureDestroy');
1816
+ return captureDestroy();
1817
+ };
1818
+
1819
+ //设置拉流质量监控周期
1820
+ const setStatisticsInterval = (interval) =>{
1821
+ return callMethod('SetStatisticsInterval',{interval});
1822
+ };
1823
+
1824
+ /**
1825
+ * @function 设置默认的硬件设备,包括摄像头、麦克风以及扬声器
1826
+ * @return Promise | void
1827
+ */
1828
+ export const setDefaultDevice = async (devices, operationType) => {
1829
+ // 设置默认的摄像头
1830
+ if (devices && devices.camera) {
1831
+ await setCameraDevice({deviceId: devices.camera, operationType:`${operationType}_1`});
1832
+ } else {
1833
+ const cameraData = await getCameraDevice();
1834
+ if (cameraData.length) {
1835
+ let hasSetCamera = false;
1836
+ for (let item of cameraData) {
1837
+ if (item.isDefault) {
1838
+ await setCameraDevice({deviceId: item.deviceId, operationType:`${operationType}_2`});
1839
+ hasSetCamera = true;
1840
+ break;
1841
+ }
1842
+ }
1843
+ if (!hasSetCamera) {
1844
+ await setCameraDevice({deviceId: cameraData[0].deviceId, operationType:`${operationType}_3`});
1845
+ }
1846
+ }
1847
+ }
1848
+ // 设置默认的麦克风
1849
+ if (devices && devices.microphone) {
1850
+ await setMicrophoneDevice({deviceId: devices.microphone, operationType:`${operationType}_1`});
1851
+ } else {
1852
+ const microPhoneData = await getMicrophoneDevice();
1853
+ if (microPhoneData.length) {
1854
+ let hasSetMicrophone = false;
1855
+ for (let item of microPhoneData) {
1856
+ if (item.isDefault) {
1857
+ await setMicrophoneDevice({deviceId: item.deviceId, operationType:`${operationType}_2`});
1858
+ hasSetMicrophone = true;
1859
+ break;
1860
+ }
1861
+ }
1862
+ if (!hasSetMicrophone) {
1863
+ await setMicrophoneDevice({deviceId: microPhoneData[0].deviceId, operationType:`${operationType}_3`});
1864
+ }
1865
+ }
1866
+ }
1867
+ // 设置默认的扬声器
1868
+ if (devices && devices.speaker) {
1869
+ await setSpeakerDevice({speakId: devices.speaker, operationType:`${operationType}_1`});
1870
+ } else {
1871
+ const speakerData = await getSpeakerDevice();
1872
+ if (speakerData.length) {
1873
+ let hasSetSpeaker = false;
1874
+ for (let item of speakerData) {
1875
+ if (item.isDefault) {
1876
+ await setSpeakerDevice({speakId: item.deviceId, operationType:`${operationType}_2`});
1877
+ hasSetSpeaker = true;
1878
+ break;
1879
+ }
1880
+ }
1881
+ if (!hasSetSpeaker) {
1882
+ await setSpeakerDevice({speakId: speakerData[0].deviceId, operationType:`${operationType}_3`});
1883
+ }
1884
+ }
1885
+ }
1886
+ };
1887
+
1888
+ /**
1889
+ * @function 设置是否只推音频流
1890
+ * @param audioOnly:Boolean 必选
1891
+ * @return Promise | void
1892
+ */
1893
+ export const controlPushAudioOnly = (audioOnly) => {
1894
+ return callMethod('ControlPushAudioOnly', {
1895
+ audioOnly
1896
+ });
1897
+ };
1898
+
1899
+ /**
1900
+ * @function 设置用户角色,新小班独有逻辑
1901
+ * @param {number} userRole 必选 用户角色 1=老师
1902
+ * @return Promise | void
1903
+ */
1904
+ export const setUserRole = (userRole) => {
1905
+ return callMethod('SetUserRole', {
1906
+ userRole
1907
+ });
1908
+ };
1909
+
1910
+ /**
1911
+ * @function 开启或者关闭摄像头
1912
+ * @param operation:Boolean 操作类型,false -> 关闭,true -> 打开,必选
1913
+ * @return Promise | void
1914
+ */
1915
+ export const openOrCloseCamera = async (operation) => {
1916
+ // await controlPushAudioOnly(!operation);
1917
+ // await muteStreamVideo(!operation);
1918
+ isNoticeCarVolumeRtc = operation;
1919
+ await muteLocalVideo(!operation);
1920
+ if (operation) {
1921
+ if (window.zbztAVSDK_init_params && window.zbztAVSDK_init_params.rtc) {
1922
+ const rtc = window.zbztAVSDK_init_params.rtc;
1923
+ await setRtcCaptureParams(rtc, 'deviceCheckerInit');
1924
+ }
1925
+ // 打开原本正在使用的摄像头
1926
+ if (rtcNowUseCamera) {
1927
+ await setCameraDevice({deviceId: rtcNowUseCamera});
1928
+ } else {
1929
+ await setCameraDevice({});
1930
+ }
1931
+ // await startPreview();
1932
+ }
1933
+ // else {
1934
+ // await setCameraDevice({deviceId: '', close: true});
1935
+ // // await stopPreview();
1936
+ // }
1937
+ };
1938
+
1939
+ /**
1940
+ * @function 开启或者关闭摄像头以及麦克风
1941
+ * @param operation:Boolean 操作类型,false -> 关闭,true -> 打开,必选
1942
+ * @return Promise | void
1943
+ */
1944
+ export const openOrCloseCameraAndMicrophone = async (operation) => {
1945
+ if (operation) {
1946
+ await startPreview();
1947
+ } else {
1948
+ await stopPreview();
1949
+ }
1950
+ };
1951
+
1952
+ /**
1953
+ * @function 控制本地视频预览的声音,即播放自己麦克风录到的声音
1954
+ * @param mute:Boolean 操作类型,false -> 不 mute,true -> mute,必选
1955
+ * @return Promise | void
1956
+ */
1957
+ export const setPreviewMute = (mute) => {
1958
+ return callMethod('SetPreviewMute', {
1959
+ mute
1960
+ });
1961
+ };
1962
+
1963
+ /**
1964
+ * @function 设置麦克风静音
1965
+ * @param mute:Boolean false -> 不静音,true -> 静音,必选
1966
+ * @return Promise | void
1967
+ */
1968
+ export const setRealTimeAudioMute = async (mute) => {
1969
+ isNoticeMicVolumeRtc = !mute;
1970
+ // await muteStreamAudio(mute);
1971
+ await muteLocalAudio(mute);
1972
+ // return callMethod('SetRealTimeAudioMute', {
1973
+ // mute
1974
+ // });
1975
+ };
1976
+
1977
+ /**
1978
+ * @function 初始化拉流
1979
+ * @param streamId:String 被拉取的流的 id,必选
1980
+ * @param domId:String <video> 标签的 id,可选
1981
+ * 如果传了就把视频绑定到对应的 <video> 标签上
1982
+ * @return src:String 视频预览地址
1983
+ */
1984
+ export const initPullFlow = async (streamId, domId, mute, renderId, notAutoPlay, audioOnly, needScale, scaleParams) => {
1985
+ defaultApi.writeLog(`RTC:: initPullFlow_start ,streamId :${streamId}`);
1986
+ let rtcPlayerId;
1987
+ const _renderId = renderId || streamId;
1988
+ resetStreamIdRtcPlayerInfo1(streamId);
1989
+ resetStreamIdRtcPlayerInfo(streamId);
1990
+ try {
1991
+ if (!isFirstHeartBeatReport) {
1992
+ isFirstHeartBeatReport = true;
1993
+ heartBeatDataReport('start');
1994
+ }
1995
+ } catch (error) {
1996
+
1997
+ }
1998
+ if (streamIdToRtcPlayerId[streamId] && !renderId) {
1999
+ defaultApi.writeLog('RTC:: The streamId queue contains this streamId');
2000
+ rtcPlayerId = streamIdToRtcPlayerId[streamId];
2001
+ await stop(streamId);
2002
+ resetStreamIdRtcPlayerInfo(streamId);
2003
+ console.log('streamIdIsExitedRtc',rtcPlayerId,streamIdToRtcPlayerId[streamId]);
2004
+ } else {
2005
+ defaultApi.writeLog('RTC:: The streamId queue does not contain this streamId');
2006
+ if (stopedRtcPlayers.length > 0) {
2007
+ rtcPlayerId = stopedRtcPlayers.pop();
2008
+ console.log('streamIdIsNoExitedRtc',rtcPlayerId,streamIdToRtcPlayerId[streamId]);
2009
+ } else {
2010
+ rtcPlayerId = JSON.parse(
2011
+ (await createRtcPlayer(
2012
+ {
2013
+ x: 500,
2014
+ y: 500,
2015
+ width: 500,
2016
+ height: 500
2017
+ },
2018
+ _renderId
2019
+ )
2020
+ ).msg
2021
+ ).id;
2022
+ }
2023
+ streamIdToRtcPlayerId[streamId] = rtcPlayerId;
2024
+ }
2025
+ if (rtcPlayerIds.indexOf(rtcPlayerId) < 0) {
2026
+ rtcPlayerIds.push(rtcPlayerId);
2027
+ localStorage.setItem('zbzt_sdk_rtcPlayerIds', rtcPlayerIds.join(','));
2028
+ }
2029
+ // 判断是否创建或者获取窗口ID成功,不成功就删掉重试
2030
+ if (!rtcPlayerId) {
2031
+ delete streamIdToRtcPlayerId[streamId];
2032
+ // delete streamIdToBlobUrl[streamId];
2033
+ return initPullFlow(streamId, domId, mute, renderId);
2034
+ }
2035
+ if (needScale) {
2036
+ setRtcXBScale(rtcPlayerId, scaleParams);
2037
+ }
2038
+ rtcPlayerIdToStreamId[rtcPlayerId] = streamId;
2039
+ // 静音拉流
2040
+ await pullAudioFlow(rtcPlayerId, !!mute);
2041
+ // 只拉音频
2042
+ await controlPullAudioOnly(streamId, !!audioOnly);
2043
+ await setPlayRenderID(rtcPlayerId, _renderId);
2044
+ await setPlayerStreamId(rtcPlayerId, streamId);
2045
+ if (!notAutoPlay) {
2046
+ await play(streamId);
2047
+ }
2048
+ const videoSrc = await startLocalOrRemotePreview(false, _renderId, domId, rtcPlayerId);
2049
+ return {
2050
+ videoSrc,
2051
+ playerId: rtcPlayerId
2052
+ };
2053
+ };
2054
+
2055
+ /**
2056
+ * @function 切换播放流
2057
+ * @param streamId:String 需要被替换的流的 id,必选
2058
+ * @param toStreamId:String 被拉取的流的 id,必选
2059
+ * @param toDomId:String <video> 标签的 id,可选
2060
+ * 如果传了就把视频绑定到对应的 <video> 标签上
2061
+ * @return src:String 视频预览地址
2062
+ */
2063
+ export const changePullFlow = async (streamId, toStreamId, toDomId) => {
2064
+ await stop(streamId, true);
2065
+ return initPullFlow(toStreamId, toDomId);
2066
+ };
2067
+
2068
+ /**
2069
+ * @function 是否需要缩放
2070
+ * @param { nunber } id 窗口id,必选
2071
+ * @param { object } scaleParams
2072
+ * @param { number } scaleParams.is_need_xb_scale 是否开启缩放
2073
+ * @param { number } scaleParams.height 高
2074
+ * @param { number } scaleParams.width 宽
2075
+ * @return Promise | void
2076
+ */
2077
+ const setRtcXBScale = async (id, scaleParams) => {
2078
+ defaultApi.writeLog(`RTC::SetRtcXBScale id: ${id} scaleParams: ${JSON.stringify(scaleParams)}`);
2079
+ await callMethod('SetRtcXBScale', {
2080
+ ...scaleParams,
2081
+ id
2082
+ });
2083
+ };
2084
+
2085
+ /**
2086
+ * @function 恢复拉指定的流
2087
+ * @param streamId:String 被拉取的流的 id,必选
2088
+ * @return Promise | void
2089
+ */
2090
+ export const play = async (streamId) => {
2091
+ const id = streamIdToRtcPlayerId[streamId];
2092
+ defaultApi.writeLog(`RTC::Play streamId: ${streamId} id: ${id}`);
2093
+ await callMethod('Play', {
2094
+ streamId,
2095
+ id
2096
+ });
2097
+ };
2098
+
2099
+ /**
2100
+ * @function 停止拉指定的流
2101
+ * @param streamId:String 被拉取的流的 id,必选
2102
+ * @param recovery:Boolean 是否回收播放器, 可选
2103
+ * @return Promise | void
2104
+ */
2105
+ export const stop = async (streamId, recovery) => {
2106
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.video_ifg = 0);
2107
+ currStreamIdRtcPlayerInfo && (currStreamIdRtcPlayerInfo.audio_ifg = 0);
2108
+ const id = streamIdToRtcPlayerId[streamId];
2109
+ delete streamIdRtcPlayerInfo[streamId];
2110
+ if (recovery && id && !stopedRtcPlayers.includes(id)) {
2111
+ stopedRtcPlayers.push(id);
2112
+ delete streamIdToRtcPlayerId[streamId];
2113
+ // delete streamIdToBlobUrl[streamId];
2114
+ }
2115
+ return callMethod('Stop', {
2116
+ id
2117
+ });
2118
+ };
2119
+
2120
+ /**
2121
+ * @function 停止并回收所有拉流
2122
+ * @return Promise | void
2123
+ */
2124
+ export const stopAllPullFlow = () => {
2125
+ const toRecoveryArr = [];
2126
+ for (let streamId in streamIdToRtcPlayerId) {
2127
+ if (streamIdToRtcPlayerId.hasOwnProperty(streamId)) {
2128
+ const id = streamIdToRtcPlayerId[streamId];
2129
+ if (id && !stopedRtcPlayers.includes(id)) {
2130
+ stopedRtcPlayers.push(id);
2131
+ toRecoveryArr.push(callMethod('Stop', {
2132
+ id
2133
+ }));
2134
+ }
2135
+ }
2136
+ }
2137
+ streamIdToRtcPlayerId = {};
2138
+ return Promise.all(toRecoveryArr);
2139
+ };
2140
+
2141
+ /**
2142
+ * @function 停止拉指定的流并销毁播放器
2143
+ * @param streamId:String 被拉取的流的 id,必选
2144
+ * @return Promise
2145
+ */
2146
+ export const stopPullFlow = async (streamId) => {
2147
+ await stop(streamId);
2148
+ await playDestroy(streamId);
2149
+ };
2150
+
2151
+ /**
2152
+ * @function 发送转推命令
2153
+ * @param args: Object
2154
+ * {
2155
+ * @param cmd:String 必选,'start' | 'stop' | 'pause' | 'resume'
2156
+ * @param liveId:String 房间 id,可选,可从 window 的初始化参数中获取
2157
+ * @param rtmpAddr:String 字符串(转推地址使用分号隔开),可选,sdk 可以内部拼接
2158
+ * @param bSaveMp4:Boolean 是否保存为 mp4 文件,可选,默认为 false
2159
+ * @param bPushRtmp:Boolean 是否推 rtmp 流,可选,默认为 true
2160
+ * @param bPushAllRtmp:Boolean 是否全部推 rtmp 流,可选,默认为 false
2161
+ * @param confId:String 分组id,可选,默认为 sdk初始化分组id
2162
+ * }
2163
+ * @return Promise | void
2164
+ */
2165
+ export const sendRecordingMsg = (args) => {
2166
+ let { cmd, liveId, rtmpAddr, bSaveMp4, bPushRtmp, bPushAllRtmp, confId } = args;
2167
+ const rtc = window.zbztAVSDK_init_params.rtc;
2168
+ if (typeof liveId === 'undefined') {
2169
+ liveId = rtc.streamId;
2170
+ }
2171
+ if (typeof rtmpAddr === 'undefined') {
2172
+ // 转推的流 id,从全局的初始化参数中获取
2173
+ const sid = rtc.sid;
2174
+ // 拼接转推地址
2175
+ rtmpAddr = rtc.recordUrl + '/' + sid;
2176
+ }
2177
+ if (typeof bSaveMp4 === 'undefined') {
2178
+ bSaveMp4 = false;
2179
+ }
2180
+ if (typeof bPushRtmp === 'undefined') {
2181
+ bPushRtmp = true;
2182
+ }
2183
+ if (typeof bPushAllRtmp === 'undefined') {
2184
+ bPushAllRtmp = true;
2185
+ }
2186
+ const params = {
2187
+ cmd,
2188
+ liveId,
2189
+ rtmpAddr,
2190
+ bSaveMp4,
2191
+ bPushRtmp,
2192
+ bPushAllRtmp,
2193
+ confId
2194
+ };
2195
+ defaultApi.writeLog(`SendRecordingMsg ${JSON.stringify(params)}`);
2196
+ return callMethod('SendRecordingMsg', params);
2197
+ };
2198
+
2199
+ /**
2200
+ * @function 退出房间
2201
+ * @return Promise
2202
+ */
2203
+ export const leaveRoom = async () => {
2204
+ await stopPush();
2205
+ await captureDestroy();
2206
+ for (let i = 0, len = rtcPlayerIds.length; i < len; i++) {
2207
+ await callMethod('PlayDestroy', {
2208
+ id: rtcPlayerIds[i]
2209
+ });
2210
+ }
2211
+ removerListener();
2212
+ heartBeatDataReport('stop');
2213
+ isFirstHeartBeatReport = false;
2214
+ rtcPlayerIds = [];
2215
+ streamIdToRtcPlayerId = {};
2216
+ rtcPlayerIdToStreamId = {};
2217
+ streamIdRtcPlayerInfo = {};
2218
+ streamIdRtcPlayerInfo1 = {};
2219
+ // heartBeatDataReportObj = {};
2220
+ stopedRtcPlayers = [];
2221
+ isInRoom = false;
2222
+ };
2223
+
2224
+ export const hasStream = streamId => {
2225
+ return Object.keys(streamIdToRtcPlayerId).includes(streamId);
2226
+ };
2227
+
2228
+ function _getConfId(streamId) {
2229
+ // 如果没有传streamId,取公共confId
2230
+ if (!streamId) {
2231
+ return _confId;
2232
+ }
2233
+ const institutionId = util.getDataFromStreamUrl('orgId', streamId);
2234
+ const roomId = util.getDataFromStreamUrl('roomId', streamId);
2235
+ // 传入streamId,通过roomId_机构id拼接得到confId,用于跨组拉流
2236
+ return util.getConfId(institutionId, roomId);
2237
+ }
2238
+ /**
2239
+ * @function 开始本地视频录制
2240
+ * @param enableRecord 开始/结束
2241
+ * @param pathFile 录制路径
2242
+ * @return Promise | void
2243
+ */
2244
+ export const localRecordVideo = async (enableRecord, pathFile) => {
2245
+ defaultApi.writeLog(`avsdk RTC::localRecordVideo enableRecord: ${enableRecord}, storagePath: ${pathFile}`);
2246
+ if (enableRecord) {
2247
+ await callMethod('SetRecordType', {
2248
+ type: 'type.mp4',
2249
+ bAudioOnly: false
2250
+ });
2251
+ await callMethod('SetRecordPathFile', {
2252
+ pathFile
2253
+ });
2254
+ return callMethod('StartRecord', {});
2255
+ } else {
2256
+ return callMethod('StopRecord', {});
2257
+ }
2258
+ };
2259
+
2260
+ /**
2261
+ * @function 本地音频录制
2262
+ * @param enableRecord 开始/结束
2263
+ * @param storagePath 录制路径
2264
+ * @return Promise | void
2265
+ */
2266
+ export const localRecordAudio = async (enableRecord, storagePath) => {
2267
+ defaultApi.writeLog(`avsdk RTC::localRecordAudio enableRecord: ${enableRecord}, storagePath: ${storagePath}`);
2268
+ return callMethod('EnableSelectedAudioRecord', {
2269
+ enable: true,
2270
+ sampleRate: 16000,
2271
+ channels: 1,
2272
+ mode: 0,
2273
+ samplesPerCall: 320,
2274
+ enableRecord,
2275
+ storagePath
2276
+ });
2277
+ };
2278
+ //推不推视频(是否推画面)
2279
+ export const muteStreamVideo = (mute = false) => {
2280
+ return callMethod('MuteStreamVideo', {
2281
+ mute
2282
+ });
2283
+ };
2284
+ //推不推视频(是否采集,这个方法直接不采集画面)
2285
+ export const muteLocalVideo = (mute = false) => {
2286
+ return callMethod('MuteLocalVideo', {
2287
+ mute
2288
+ });
2289
+ };
2290
+
2291
+ //推不推声音 (是否推声音)
2292
+ export const muteStreamAudio = (mute = false) => {
2293
+ // try {
2294
+ // dataReport.deviceChange({
2295
+ // device: 2,
2296
+ // device_state: mute ? 0 :1
2297
+ // });
2298
+ // } catch (e){};
2299
+ return callMethod('MuteStreamAudio', {
2300
+ mute
2301
+ });
2302
+ };
2303
+ //推不推声音 (是否采集,这个方法直接不采集声音)
2304
+ export const muteLocalAudio = (mute = false) => {
2305
+ return callMethod('MuteLocalAudio', {
2306
+ mute
2307
+ });
2308
+ };
2309
+
2310
+ /**
2311
+ * @function 开始连麦
2312
+ * @param mode:number 采集器默认, 默认0=站立 1=坐立
2313
+ * @return Promise | void
2314
+ */
2315
+ export const teacherStartLinkMic = async (mode = 0) => {
2316
+ if (mode === 0) {
2317
+ await muteStreamVideo(true);
2318
+ await setMicrophoneDevice({});
2319
+ // await muteStreamAudio(false);
2320
+ await muteLocalAudio(false);
2321
+ } else {
2322
+ // await muteLocalVideo(false);
2323
+ await muteLocalAudio(false);
2324
+ }
2325
+ };
2326
+
2327
+ /**
2328
+ * @function 结束连麦
2329
+ * @param mode:number 采集器默认, 默认0=站立 1=坐立
2330
+ * @return Promise | void
2331
+ */
2332
+ export const teacherStopLinkMic = async (mode = 0) => {
2333
+ if (mode === 0) {
2334
+ await muteStreamVideo(false);
2335
+ await setMicrophoneDevice({deviceId: ''});
2336
+ }
2337
+ // else {
2338
+ // await muteLocalVideo(true);
2339
+ // }
2340
+ };
2341
+
2342
+ /**
2343
+ * @function 设置采集扬声器声音(rtc)
2344
+ * @param { string } deviceId 设备id
2345
+ * @param {boolean} speaker 采集扬声器声音=true/不采集=false
2346
+ * @return: Promise
2347
+ */
2348
+ export const setAudioSpeakerCapture = async (deviceId,speaker) => {
2349
+ return callMethod('SetAudioSpeakerCapture', {
2350
+ deviceID:deviceId,
2351
+ bMixSpeaker:speaker
2352
+ });
2353
+ };
2354
+
2355
+ /**
2356
+ * @function 设置混流和背景色
2357
+ * @param { number } type 0=不拼接/1=截屏窗+背景图/2=截屏窗+背景图+头像
2358
+ * @param { number } id 需要混合的采集器id
2359
+ * @param { object } rgb
2360
+ * @param { number } rgb.r
2361
+ * @param { number } rgb.g
2362
+ * @param { number } rgb.b
2363
+ * @return: Promise
2364
+ */
2365
+ export const setMixStream = async (type, id, rgb) => {
2366
+ await callMethod('SetIsNeedCombineCap', {
2367
+ isNeedCombine: type,
2368
+ id
2369
+ });
2370
+ if (rgb) {
2371
+ await callMethod('SetCombinePadRGB', rgb);
2372
+ }
2373
+ if(!type){
2374
+ try {
2375
+ dataReport.splitState({
2376
+ camera_split_start_resolution : captureAfter ,
2377
+ camera_split_start_encode_resolution : captureEncodeAfter ,//摄像头拼接前编码分辨率
2378
+ camera_split_end_resolution : captureBefore ,
2379
+ camera_split_end_encode_resolution : captureEncodeBefore ,//摄像头拼接后编码分辨率
2380
+ screen_split_start_encode_resolution: screenEncodeAfter ,//截屏窗拼接前编码分辨率
2381
+ screen_split_start_resolution :screenEncodeAfter ,//截屏窗拼接前采集分辨率
2382
+ screen_split_end_encode_resolution: screenEncodeBefore ,//截屏窗拼接后编码分辨率
2383
+ screen_split_end_resolution :screenEncodeBefore,//截屏窗拼接后采集分辨率
2384
+ split:'结束拼接' //拼接状态 不拼接
2385
+ });
2386
+ } catch (e){ };
2387
+ }
2388
+ };
2389
+
2390
+ /**
2391
+ * @function 采集器截图
2392
+ * @param { string } fileName 文件名,需要后缀名。例如:333.jpg
2393
+ * @return: Promise
2394
+ */
2395
+ export const captureSnapShot = (file_name) => {
2396
+ return callMethod('SnapShot', {quality: 70, file_name});
2397
+ };
2398
+ /**
2399
+ * @function 播放器截图
2400
+ * @param { string } fileName 文件名,需要后缀名。例如:333.jpg
2401
+ * @return: Promise
2402
+ */
2403
+ export const playerSnapShot = (id, file_name) => {
2404
+ return callMethod('PlayerSnapShot', {id, quality: 70, file_name});
2405
+ };
2406
+
2407
+ /**
2408
+ * @function 设置镜像状态(预览)
2409
+ * @param { boolean } isMirror true=开启 false=关闭
2410
+ * @return: Promise
2411
+ */
2412
+ export const setMirrorStatus = (isMirror) => {
2413
+ return callMethod('SetRTCPreViewMirror', {isMirror});
2414
+ };
2415
+
2416
+ /**
2417
+ * @function 设置推流镜像状态
2418
+ * @param { boolean } id 采集器Id
2419
+ * @param { boolean } mode 1=开启 0=关闭
2420
+ * @return: Promise
2421
+ */
2422
+ export const setMirrorMode = (mode,id = 0) => {
2423
+ let realId = mode == 0 ? 0 : 2;
2424
+ defaultApi.writeLog(`RTC: setMirrorMode, mode: ${mode}, id:${id}, realId:${realId}`);
2425
+ return callMethod('SetMirrorMode', {id, mode:realId});
2426
+ };
2427
+
2428
+ /**
2429
+ * @function 设置拉流镜像状态
2430
+ * @param { boolean } isMirror true=开启 false=关闭
2431
+ * @return: Promise
2432
+ */
2433
+ export const setRTCPlayViewMirror = (isMirror, id) => {
2434
+ return callMethod('SetRTCPlayViewMirror', {isMirror, id});
2435
+ };
2436
+
2437
+ //美颜相关
2438
+ /**
2439
+ * @function 开启美颜
2440
+ * @return: Promise
2441
+ */
2442
+ export const startSenseMe = async () => {
2443
+ return callMethod('StartSenseMe', {});
2444
+ };
2445
+ /**
2446
+ * @function 设置美颜参数
2447
+ * * @param { number } type //美颜类型,1、红润强度,3、磨皮强度,4、美白强度,5、大眼,6、瘦脸,7、小脸,8、对比度强度,9、饱和度强度
2448
+ * * @param { number } value //美颜数值,有效值范围0~100
2449
+ * @return: Promise
2450
+ */
2451
+ export const setBeautifyParam = async (type, value) => {
2452
+ return callMethod('SetBeautifyParam', {type, value});
2453
+ };
2454
+ /**
2455
+ * @function 关闭美颜
2456
+ * @return: Promise
2457
+ */
2458
+ export const endSenseMe = async () => {
2459
+ return callMethod('EndSenseMe', {});
2460
+ };
2461
+
2462
+ /**
2463
+ * @function 发送SEI
2464
+ * @return: Promise
2465
+ */
2466
+ export const sendMediaSideInfo = async (text) => {
2467
+ return callMethod('SendMediaSideInfo', {id, text});
2468
+ };
2469
+
2470
+ // 获取TalMedia.dll版本号
2471
+ export const getSDKVersion = async () => {
2472
+ return callMethod('GetSDKVersion', {});
2473
+ };
2474
+
2475
+ const heartBeatRealKeys = ['video_fps', 'video_bitrate', 'audio_fps', 'audio_bitrate'];
2476
+ const _heartBeatDataReport = () => {
2477
+ // let cpuRate = 0;
2478
+ // let memRate = 0;
2479
+ let rateCount = 0;
2480
+ // let appCpuRate = 0;
2481
+ // let appMemUsed = 0;
2482
+ let rateTimer = setInterval(async () => {
2483
+ rateCount++;
2484
+ // let {cpu_rate, mem_rate, gpus, app_cpu_rate, app_mem_used} = (await toolApi.getCurCpuMemInfo()).msg;
2485
+ // cpu_rate = cpu_rate < 0 ? 0 : cpu_rate;
2486
+ // cpuRate += parseFloat(cpu_rate);
2487
+ // memRate += parseFloat(mem_rate);
2488
+ // if (window.zbztAVSDK_init_params.rtc.role === 'student') {
2489
+ // appCpuRate += parseFloat(app_cpu_rate);
2490
+ // appMemUsed += parseFloat(app_mem_used);
2491
+ // }
2492
+ if (rateCount >= 3) {
2493
+ // heartBeatRealKeys.forEach(realKey => {
2494
+ // if (heartBeatDataReportObj.hasOwnProperty(realKey) && heartBeatDataReportObj.count > 0) {
2495
+ // heartBeatDataReportObj[realKey] = util.toFixed(heartBeatDataReportObj[realKey]/heartBeatDataReportObj.count);
2496
+ // }
2497
+ // });
2498
+ // heartBeatDataReportObj.volume = heartBeatDataReportObj.volume.join(',');
2499
+ const pullInfo = [];
2500
+ Object.keys(streamIdRtcPlayerInfo).forEach(streamid => {
2501
+ heartBeatRealKeys.forEach(realKey => {
2502
+ if (!streamIdRtcPlayerInfo[streamid].hasOwnProperty(realKey)) {
2503
+ streamIdRtcPlayerInfo[streamid][realKey] = [];
2504
+ }
2505
+ // if (streamIdRtcPlayerInfo[streamid].count > 0) {
2506
+ // streamIdRtcPlayerInfo[streamid][realKey] = util.toFixed(streamIdRtcPlayerInfo[streamid][realKey]/streamIdRtcPlayerInfo[streamid].count);
2507
+ // }
2508
+ });
2509
+
2510
+ //获取拉流类型,后期可写为函数提出去
2511
+ if(streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2512
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'both';
2513
+ } else if(!streamIdRtcPlayerInfo1[streamid].audio_type && streamIdRtcPlayerInfo1[streamid].video_type) {
2514
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'video';
2515
+ } else if(streamIdRtcPlayerInfo1[streamid].audio_type && !streamIdRtcPlayerInfo1[streamid].video_type) {
2516
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'audio';
2517
+ } else {
2518
+ streamIdRtcPlayerInfo1[streamid].stream_type = 'none';
2519
+ }
2520
+ // console.log('hsghsghsg_type_type', streamIdRtcPlayerInfo1[streamid].stream_type);
2521
+
2522
+ // streamIdRtcPlayerInfo[streamid].volume = streamIdRtcPlayerInfo[streamid].volume.join(',');
2523
+ // delete streamIdRtcPlayerInfo[streamid].count;
2524
+ pullInfo.push({
2525
+ streamid,
2526
+ ...streamIdRtcPlayerInfo[streamid],
2527
+ pull_type: streamIdRtcPlayerInfo1[streamid].stream_type,
2528
+ volume: streamIdRtcPlayerInfo[streamid].volume.slice(0,streamIdRtcPlayerInfo[streamid].volume.length-1)
2529
+ });
2530
+ resetStreamIdRtcPlayerInfo(streamid);
2531
+ });
2532
+ // delete heartBeatDataReportObj.count;
2533
+ if (isFirstHeartBeatReport && rateCount > 0) {
2534
+ try {
2535
+ //静音推流时过滤掉音频帧率和码率,上报为0;
2536
+ // if (!isNoticeMicVolumeRtc) {
2537
+ // heartBeatDataReportObj['audio_fps'] = [];
2538
+ // heartBeatDataReportObj['audio_bitrate'] = [];
2539
+ // };
2540
+ //获取推流类型,后期可写为函数提出去
2541
+ if(zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2542
+ zbztsdk.deviceStatus.stream_type = 'both';
2543
+ } else if(!zbztsdk.deviceStatus.camera && zbztsdk.deviceStatus.microphone) {
2544
+ zbztsdk.deviceStatus.stream_type = 'audio';
2545
+ } else if(zbztsdk.deviceStatus.camera && !zbztsdk.deviceStatus.microphone) {
2546
+ zbztsdk.deviceStatus.stream_type = 'video';
2547
+ } else {
2548
+ zbztsdk.deviceStatus.stream_type = 'none';
2549
+ };
2550
+ defaultApi.writeLog(`push_type_rtc zbztsdk.deviceStatus.camera: ${zbztsdk.deviceStatus.camera},zbztsdk.deviceStatus.microphone: ${zbztsdk.deviceStatus.microphone}, type: ${zbztsdk.deviceStatus.stream_type}`);
2551
+ defaultApi.writeLog(`push_type_rtc carema: ${isNoticeCarVolumeRtc},mic: ${isNoticeMicVolumeRtc}, a_fps: ${dataRtcCapture.audioInputframes}, a_bit: ${dataRtcCapture.audioencoderate}, v_fps: ${dataRtcCapture.videoInputframes}, v_bit: ${dataRtcCapture.videoencoderate}`);
2552
+ // if (window.zbztAVSDK_init_params.rtc.role === 'teacher') {
2553
+ dataReport.heartbeat({
2554
+ ...{...heartBeatDataReportObj, push_type: zbztsdk.deviceStatus.stream_type, volume: heartBeatDataReportObj.volume.slice(0,heartBeatDataReportObj.volume.length-1)},
2555
+ // pull_info: JSON.stringify(pullInfo),
2556
+ pull_info: pullInfo,
2557
+ // cpu_rate: util.toFixed(cpuRate/rateCount),
2558
+ // mem_rate: util.toFixed(memRate/rateCount),
2559
+ });
2560
+ // } else {
2561
+ // dataReport.heartbeat({
2562
+ // ...heartBeatDataReportObj,
2563
+ // pull_info: JSON.stringify(pullInfo),
2564
+ // cpu_rate: util.toFixed(cpuRate/rateCount),
2565
+ // mem_rate: util.toFixed(memRate/rateCount),
2566
+ // app_cpu: util.toFixed(appCpuRate/rateCount),
2567
+ // app_mem: util.toFixed(appMemUsed/rateCount),
2568
+ // video_mem: gpus
2569
+ // });
2570
+ // }
2571
+ } catch (e) {
2572
+ console.error('hsghsg_error',e);
2573
+ }
2574
+ }
2575
+ resetHeartBeatDataReportObj();
2576
+ rateCount = 0;
2577
+ // cpuRate = 0;
2578
+ // memRate = 0;
2579
+ // appCpuRate = 0;
2580
+ // appMemUsed = 0;
2581
+ clearInterval(rateTimer);
2582
+ }
2583
+ }, 10 * 1000);
2584
+ };
2585
+
2586
+ const heartBeatDataReport = (type) => {
2587
+ try {
2588
+ if (type === 'start' && !heartBeatDataReportTimer) {
2589
+ resetHeartBeatDataReportObj();
2590
+ _heartBeatDataReport();
2591
+ heartBeatDataReportTimer = setInterval(() => {
2592
+ _heartBeatDataReport();
2593
+ }, 30 * 1000);
2594
+ }
2595
+ if (type === 'stop') {
2596
+ clearInterval(heartBeatDataReportTimer);
2597
+ heartBeatDataReportTimer = null;
2598
+ }
2599
+ } catch (error) {
2600
+ console.error(error);
2601
+ }
2602
+ };
2603
+
2604
+ const heartBeatDataReportCalc = (name, _d) => {
2605
+ // 拉流
2606
+ const pullKeys = ['videoRenderFrameRate', 'videoCodeRate', 'audioRenderFrameRate', 'audioCodeRate'];
2607
+ if (name === 'rtcPlayCycleDataReport') {
2608
+ // console.log('hsg_tdddd',_d);
2609
+ if (streamIdRtcPlayerInfo && streamIdRtcPlayerInfo.hasOwnProperty(_d.streamid)) {
2610
+ let isReport = true;
2611
+ // streamIdRtcPlayerInfo[_d.streamid].count++;
2612
+ heartBeatRealKeys.forEach((realKey, index) => {
2613
+ if (_d.hasOwnProperty(pullKeys[index])) {
2614
+ if (streamIdRtcPlayerInfo[_d.streamid][realKey] === undefined) {
2615
+ streamIdRtcPlayerInfo[_d.streamid][realKey] = [];
2616
+ isReport = false;
2617
+ }
2618
+ // streamIdRtcPlayerInfo[_d.streamid][realKey].push(parseFloat(parseInt(_d[pullKeys[index]])));
2619
+ }
2620
+ });
2621
+ if (isReport) {
2622
+ let audio_fps_rtc_pull = 0;
2623
+ let audio_bitrate_rtc_pull = 0;
2624
+ let video_fps_rtc_pull = 0;
2625
+ let video_bitrate_rtc_pull = 0;
2626
+
2627
+ if(streamIdRtcPlayerInfo1[_d.streamid].audio_type && streamIdRtcPlayerInfo1[_d.streamid].video_type) {
2628
+ audio_fps_rtc_pull = parseFloat(parseInt(_d.audioRenderFrameRate));
2629
+ audio_bitrate_rtc_pull = parseFloat(parseInt(_d.audioCodeRate));
2630
+ video_fps_rtc_pull = parseFloat(parseInt(_d.videoRenderFrameRate));
2631
+ video_bitrate_rtc_pull = parseFloat(parseInt(_d.videoCodeRate));
2632
+ } else if(!streamIdRtcPlayerInfo1[_d.streamid].audio_type && streamIdRtcPlayerInfo1[_d.streamid].video_type) {
2633
+ video_fps_rtc_pull = parseFloat(parseInt(_d.videoRenderFrameRate));
2634
+ video_bitrate_rtc_pull = parseFloat(parseInt(_d.videoCodeRate));
2635
+ } else if(streamIdRtcPlayerInfo1[_d.streamid].audio_type && !streamIdRtcPlayerInfo1[_d.streamid].video_type) {
2636
+ audio_fps_rtc_pull = parseFloat(parseInt(_d.audioRenderFrameRate));
2637
+ audio_bitrate_rtc_pull = parseFloat(parseInt(_d.audioCodeRate));
2638
+ }
2639
+ streamIdRtcPlayerInfo[_d.streamid].audio_fps.push(audio_fps_rtc_pull);
2640
+ streamIdRtcPlayerInfo[_d.streamid].audio_bitrate.push(audio_bitrate_rtc_pull);
2641
+ streamIdRtcPlayerInfo[_d.streamid].video_fps.push(video_fps_rtc_pull);
2642
+ streamIdRtcPlayerInfo[_d.streamid].video_bitrate.push(video_bitrate_rtc_pull);
2643
+ streamIdRtcPlayerInfo[_d.streamid].pull_loss.push(_d.lostrate);
2644
+ streamIdRtcPlayerInfo[_d.streamid].pull_delay.push(_d.delay);
2645
+
2646
+ streamIdRtcPlayerInfo[_d.streamid].ctime.push(Math.round((new Date().getTime()+dataReport.timestamp)/1000));
2647
+ // console.log('hsg_tpull_keys',JSON.parse(JSON.stringify(streamIdRtcPlayerInfo[_d.streamid])));
2648
+ }
2649
+ // streamIdRtcPlayerInfo[_d.streamid].ctime.push(Math.round((new Date().getTime()+util.diffTime)/1000).toString());
2650
+ // console.log('hsg_tpull_keys',JSON.parse(JSON.stringify(streamIdRtcPlayerInfo[_d.streamid])));
2651
+ }
2652
+ }
2653
+ // 推流
2654
+ const pushKeys = ['videoInputframes', 'videoencoderate', 'audioInputframes', 'audioencoderate'];
2655
+ if (name === 'rtcCaptureCycleDataReport') {
2656
+ let audio_fps_rtc_push = 0;
2657
+ let audio_bitrate_rtc_push = 0;
2658
+ let video_fps_rtc_push = 0;
2659
+ let video_bitrate_rtc_push = 0;
2660
+ dataRtcCapture = _d;
2661
+ // console.log('hsg_d5555',_d,isNoticeMicVolumeRtc,isNoticeCarVolumeRtc);
2662
+ // heartBeatDataReportObj.count++;
2663
+ // heartBeatRealKeys.forEach((realKey, index) => {
2664
+ // if (!heartBeatDataReportObj.hasOwnProperty(realKey) && !_d.hasOwnProperty(pushKeys[index])) {
2665
+
2666
+ // heartBeatDataReportObj[realKey] += parseFloat(_d[pushKeys[index]]);
2667
+ if (isNoticeMicVolumeRtc && isNoticeCarVolumeRtc) {
2668
+ audio_fps_rtc_push = parseFloat(parseInt(_d.audioInputframes));
2669
+ audio_bitrate_rtc_push = parseFloat(parseInt(_d.audioencoderate));
2670
+ video_fps_rtc_push = parseFloat(parseInt(_d.videoInputframes));
2671
+ video_bitrate_rtc_push= parseFloat(parseInt(_d.videoencoderate));
2672
+ // heartBeatDataReportObj[realKey].push(parseFloat(parseInt(_d[pushKeys[index]])));
2673
+ } else if(!isNoticeMicVolumeRtc && isNoticeCarVolumeRtc) {
2674
+
2675
+ video_fps_rtc_push = parseFloat(parseInt(_d.videoInputframes));
2676
+ video_bitrate_rtc_push = parseFloat(parseInt(_d.videoencoderate));
2677
+ // heartBeatDataReportObj.audio_fps.push(0);
2678
+ // heartBeatDataReportObj.audio_bitrate.push(0);
2679
+ // heartBeatDataReportObj.video_fps.push(parseFloat(parseInt(_d.videoInputframes)));
2680
+ // heartBeatDataReportObj.video_bitrate.push(parseFloat(parseInt(_d.videoencoderate)));
2681
+ } else if(!isNoticeCarVolumeRtc && isNoticeMicVolumeRtc) {
2682
+ audio_fps_rtc_push = parseFloat(parseInt(_d.audioInputframes));
2683
+ audio_bitrate_rtc_push = parseFloat(parseInt(_d.audioencoderate));
2684
+ // heartBeatDataReportObj.audio_fps.push(parseFloat(parseInt(_d.videoInputframes)));
2685
+ // heartBeatDataReportObj.audio_bitrate.push(parseFloat(parseInt(_d.videoInputframes)));
2686
+ // heartBeatDataReportObj.video_fps.push(0);
2687
+ // heartBeatDataReportObj.video_bitrate.push(0);
2688
+ }
2689
+ heartBeatDataReportObj.audio_fps.push(audio_fps_rtc_push);
2690
+ heartBeatDataReportObj.audio_bitrate.push(audio_bitrate_rtc_push);
2691
+ heartBeatDataReportObj.video_fps.push(video_fps_rtc_push);
2692
+ heartBeatDataReportObj.video_bitrate.push(video_bitrate_rtc_push);
2693
+ heartBeatDataReportObj.push_loss.push(_d.lostrate);
2694
+ heartBeatDataReportObj.push_delay.push(_d.delay);
2695
+ // }
2696
+ // });
2697
+ //
2698
+ heartBeatDataReportObj.ctime.push(Math.round((new Date().getTime()+dataReport.timestamp)/1000));
2699
+ // console.log('hsg_d6',JSON.parse(JSON.stringify(heartBeatDataReportObj)));
2700
+ // console.log('hsg_push_keys',JSON.parse(JSON.stringify(heartBeatDataReportObj)));
2701
+ }
2702
+ };
2703
+
2704
+ //推流字段
2705
+ const resetHeartBeatDataReportObj = () => {
2706
+ // console.log('hsg_d55556重置');
2707
+ heartBeatDataReportObj = {
2708
+ ctime: [],
2709
+ // push_type: zbztsdk ? zbztsdk.deviceStatus.stream_type : 'none',
2710
+ push_type: 'none',
2711
+ // video_fps: 0,
2712
+ // video_bitrate: 0,
2713
+ // audio_fps: 0,
2714
+ // audio_bitrate: 0,
2715
+ video_fps: [],
2716
+ video_bitrate: [],
2717
+ audio_fps: [],
2718
+ audio_bitrate: [],
2719
+ push_loss: [],
2720
+ push_delay: [],
2721
+ // count: 0,
2722
+ volume: ''
2723
+ };
2724
+ };
2725
+
2726
+ //记录拉流类型,用作数据上报
2727
+ const resetStreamIdRtcPlayerInfo1 = (streamId) => {
2728
+ streamIdRtcPlayerInfo1[streamId] = {
2729
+ audio_type: false,
2730
+ video_type: false,
2731
+ stream_type: 'none'
2732
+ };
2733
+ // console.log('hsgshgs_heartbeat',streamIdRtcPlayerInfo1);
2734
+ };
2735
+
2736
+ resetHeartBeatDataReportObj();
2737
+
2738
+ //拉流字段
2739
+ const resetStreamIdRtcPlayerInfo = (streamId) => {
2740
+ streamIdRtcPlayerInfo[streamId] = {
2741
+ pull_uid: util.getUidByStreamId(streamId),
2742
+ streamid: streamId,
2743
+ ctime: [],
2744
+ pull_type: streamIdRtcPlayerInfo1[streamId].stream_type,
2745
+ volume: '',
2746
+ // 平均值
2747
+ // count: 0,
2748
+ // video_fps: 0,
2749
+ // video_bitrate: 0,
2750
+ // audio_fps: 0,
2751
+ // audio_bitrate: 0,
2752
+ video_fps: [],
2753
+ video_bitrate: [],
2754
+ audio_fps: [],
2755
+ audio_bitrate: [],
2756
+ pull_loss: [],
2757
+ pull_delay: [],
2758
+ // 累加
2759
+ audio_ifg: 0,
2760
+ video_ifg: 0
2761
+ };
2762
+ };
2763
+
2764
+ export default {
2765
+ loadRtc,
2766
+ unloadRtc,
2767
+ setAppId,
2768
+ setUserName,
2769
+ setUserId,
2770
+ setConfId,
2771
+ createRtcCapture,
2772
+ getCameraDeviceCount,
2773
+ getCameraDevice,
2774
+ setCameraDevice,
2775
+ getCameraSupportedRes,
2776
+ setCameraParam,
2777
+ setEventReportSvr,
2778
+ getSpeakerDeviceCount,
2779
+ getSpeakerDevice,
2780
+ setSpeakerDevice,
2781
+ setSpeakerVolume,
2782
+ setSpeakerMute,
2783
+ getSpeakerVolume,
2784
+ setMute,
2785
+ pullAudioFlow,
2786
+ getMicrophoneDeviceCount,
2787
+ getMicrophoneDevice,
2788
+ setMicrophoneDevice,
2789
+ getMicrophoneVolume,
2790
+ setMicrophoneVolume,
2791
+ setRealTimeAudioMute,
2792
+ getCurrentAppSessionVolume,
2793
+ setCurrentAppSessionVolume,
2794
+ setApplicationMute,
2795
+ setPreviewPos,
2796
+ startPreview,
2797
+ setEncodeParam,
2798
+ setBitRate,
2799
+ setCaptureStreamId,
2800
+ setCaptureRenderID,
2801
+ startPush,
2802
+ stopPush,
2803
+ stopPreview,
2804
+ captureDestroy,
2805
+ createRtcPlayer,
2806
+ setPlayerStreamId,
2807
+ setPlayRenderID,
2808
+ play,
2809
+ stop,
2810
+ playDestroy,
2811
+ startLocalOrRemotePreview,
2812
+ init,
2813
+ setDefaultDevice,
2814
+ openOrCloseCamera,
2815
+ setPreviewMute,
2816
+ openOrCloseCameraAndMicrophone,
2817
+ initPullFlow,
2818
+ stopPullFlow,
2819
+ stopAllPullFlow,
2820
+ changePullFlow,
2821
+ leaveRoom,
2822
+ sendRecordingMsg,
2823
+ controlPullAudioOnly,
2824
+ openMicVolumeCb,
2825
+ startRoomMixRecord,
2826
+ stopRoomMixRecord,
2827
+ startSingleRecord,
2828
+ stopSingleRecord,
2829
+ hasStream,
2830
+ localRecordAudio,
2831
+ localRecordVideo,
2832
+ teacherStartLinkMic,
2833
+ teacherStopLinkMic,
2834
+ setAudioSpeakerCapture,
2835
+ setMixStream,
2836
+ recoverSdk,
2837
+ captureSnapShot,
2838
+ playerSnapShot,
2839
+ setMirrorStatus,
2840
+ stopCheckDevice,
2841
+ startSenseMe,
2842
+ setBeautifyParam,
2843
+ endSenseMe,
2844
+ setRTCPlayViewMirror,
2845
+ muteStreamVideo,
2846
+ muteLocalVideo,
2847
+ muteStreamAudio,
2848
+ muteLocalAudio,
2849
+ getSDKVersion,
2850
+ setMirrorMode,
2851
+ destroyEngine,
2852
+ rtcLoadCollectionEntry2,
2853
+ sendMediaSideInfo
2854
+ };