zby-live-sdk 1.0.49-beta-talrtc0922 → 1.0.49-beta-talrtc1014

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 (51) hide show
  1. package/.babelrc +5 -5
  2. package/.editorconfig +13 -13
  3. package/.eslintrc.js +29 -29
  4. package/CHANGELOG.md +381 -370
  5. package/README.md +276 -276
  6. package/dist/zby-live-sdk.cjs.js +4 -3
  7. package/dist/zby-live-sdk.esm.js +4 -3
  8. package/dist/zby-live-sdk.umd.js +4 -3
  9. package/package.json +1 -1
  10. package/src/channel/getSendMsgParams.js +66 -66
  11. package/src/channel/index.js +138 -138
  12. package/src/channel/pomelo/index.js +184 -184
  13. package/src/channel/pomelo/latestQueue.js +151 -151
  14. package/src/channel/pomelo/polemo.js +749 -749
  15. package/src/channel/pomelo/util.js +54 -54
  16. package/src/channel/sdk-cb.js +73 -73
  17. package/src/channel/stream-msg.js +97 -97
  18. package/src/channel/zby/index.js +74 -74
  19. package/src/channel/zby/interactWithChannel.js +4 -4
  20. package/src/channel/zby/interactWithChannelControl.js +1568 -1568
  21. package/src/channel/zby/interactWithChannelEntry.js +318 -318
  22. package/src/config/config.js +153 -153
  23. package/src/default/base.js +70 -70
  24. package/src/default/extend.js +36 -36
  25. package/src/default/index.js +9 -9
  26. package/src/live/base.js +42 -42
  27. package/src/live/call-method.js +9 -9
  28. package/src/live/extend.js +53 -53
  29. package/src/live/index.js +9 -9
  30. package/src/network/api.js +50 -50
  31. package/src/network/commonFetch.js +66 -66
  32. package/src/network/dataReport.js +429 -429
  33. package/src/notice.js +394 -394
  34. package/src/tool/base.js +74 -74
  35. package/src/tool/call-method.js +9 -9
  36. package/src/tool/extend.js +42 -42
  37. package/src/tool/index.js +9 -9
  38. package/src/util/bridge.js +87 -87
  39. package/src/util/bridge1.js +46 -46
  40. package/src/util/dict.js +51 -51
  41. package/src/util/sessionStorage.js +29 -29
  42. package/src/util/sha256.js +482 -482
  43. package/src/util/util.js +308 -308
  44. package/src/zby-av-sdk/agora-sdk.js +711 -711
  45. package/src/zby-av-sdk/device.js +145 -145
  46. package/src/zby-av-sdk/rtc-sdk.js +2839 -2839
  47. package/src/zby-av-sdk/talrtc-sdk.js +2392 -2348
  48. package/src/zby-av-sdk/trtc-sdk.js +1801 -1801
  49. package/src/zby-av-sdk/zby-av-sdk.js +1891 -1891
  50. package/src/zby-av-sdk/zego-sdk.js +2987 -2987
  51. package/src/zby-live-sdk.js +1561 -1557
@@ -1,711 +1,711 @@
1
- /**
2
- * @File: Agora 音视频 SDK
3
- * @Author: xuyuanrui
4
- * @Email: raywhbxyr@163.com
5
- * @Date: 2018-08-06 11:00:29
6
- **/
7
-
8
- // 扩展标识
9
- const extensionId = 'agora_ext';
10
- // 端提供的 API 入口
11
- const EM = window.EM;
12
-
13
- /**
14
- * @function 调用端提供的回调方法
15
- * @param name:String 回调方法名,必选
16
- * @param args:Object 回调参数,必选
17
- * @return Promise | void
18
- */
19
- const callMethod = (name, args) => {
20
- // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
21
- if (EM) {
22
- return new Promise((resolve, reject) => {
23
- EM.CallMethod(
24
- extensionId,
25
- name,
26
- JSON.stringify(args),
27
- (code, msg) => {
28
- console.log(`${name} Code: ${code}\nMessage: ${msg}`);
29
- resolve({
30
- code,
31
- msg
32
- });
33
- }
34
- );
35
- });
36
- }
37
- };
38
-
39
- /**
40
- * @function 加载声网扩展
41
- * @param extensionVersion:String 扩展版本号,必选
42
- * @return Promise | void
43
- */
44
- export const loadAgora = (extensionVersion) => {
45
- // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
46
- if (EM) {
47
- return new Promise((resolve, reject) => {
48
- EM.Load(
49
- extensionId,
50
- extensionVersion,
51
- false,
52
- (code, msg) => {
53
- console.log(`loadAgora Code: ${code}\nMessage: ${msg}`);
54
- resolve();
55
- }
56
- );
57
- });
58
- }
59
- };
60
-
61
- /**
62
- * @function 卸载声网扩展
63
- * @return Promise | void
64
- */
65
- export const unloadAgora = () => {
66
- // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
67
- if (EM) {
68
- return new Promise((resolve, reject) => {
69
- EM.UnLoad(
70
- extensionId,
71
- (code, msg) => {
72
- console.log(`unloadAgora Code: ${code}\nMessage: ${msg}`);
73
- resolve();
74
- }
75
- );
76
- });
77
- }
78
- };
79
-
80
- /**
81
- * @function 添加扩展监听机制
82
- * @return void
83
- */
84
- const addListener = () => {
85
- // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
86
- if (EM) {
87
- EM.AddListener(extensionId, (event, data) => {
88
- console.log(`AddListener Event: ${event}\nData: ${data}`);
89
- });
90
- }
91
- };
92
-
93
- /**
94
- * @function 创建 IRtcEngine 对象
95
- * @param appId:String Agora 秘钥,必选
96
- * @return Promise | void
97
- */
98
- export const startEngine = (appId) => {
99
- return callMethod('StartEngine', {
100
- appId
101
- });
102
- };
103
-
104
- /**
105
- * @function 设置频道属性
106
- * 该方法用于设置频道模式(profile),
107
- * Agora RtcEngine 需知道应用程序的使用场景(例如通信模式或直播模式),
108
- * 从而使用不同的优化手段。
109
- * @param profile 频道模式,可选,默认 0,即使用通信模式,
110
- * 用于常见的一对一或群聊,频道中的任何用户可以自由说话
111
- * @return Promise | void
112
- */
113
- export const setChannelProfile = (profile) => {
114
- if (typeof profile === 'undefined') {
115
- profile = 0;
116
- }
117
- return callMethod('SetChannelProfile', {
118
- profile
119
- });
120
- };
121
-
122
- /**
123
- * @function 打开视频模式
124
- * 可以在加入频道前或者通话中调用,在加入频道前调用,
125
- * 则自动开启视频模式,在通话中调用则由音频模式切换为视频模式。
126
- * 调用 disableVideo() 方法可关闭视频模式。
127
- * @return Promise | void
128
- */
129
- export const enableVideo = () => {
130
- return callMethod('EnableVideo', {});
131
- };
132
-
133
- /**
134
- * @function 关闭视频模式
135
- * 可以在加入频道前或者通话中调用,在加入频道前调用,
136
- * 则自动开启纯音频模式,在通话中调用则由视频模式切换为纯音频频模式。
137
- * 调用 enableVideo() 方法可开启视频模式。
138
- * @return Promise | void
139
- */
140
- export const disableVideo = () => {
141
- return callMethod('DisableVideo', {});
142
- };
143
-
144
- /**
145
- * @function 设置本地视频显示属性
146
- * @param userId:Number 用户 id
147
- * @return Promise | void
148
- */
149
- export const setupLocalVideo = (userId) => {
150
- return callMethod('SetupLocalVideo', {
151
- uid: userId
152
- });
153
- };
154
-
155
- /**
156
- * @function 设置远端视频显示属性
157
- * @param userId:Number 用户 id
158
- * @return Promise | void
159
- */
160
- export const setupRemoteVideo = (userId) => {
161
- return callMethod('SetupRemoteVideo', {
162
- uid: userId
163
- });
164
- };
165
-
166
- /**
167
- * @function 设置本地视频编码属性
168
- * 应在调用 enableVideo 后设置视频属性
169
- * 应在调用 joinChannel/startPreview 前设置视频属性
170
- * @param profile:Number 视频分辨率、帧率和码率,可选,默认 30
171
- * @param swapWidthAndHeight:Boolean 是否交换宽和高,可选,默认 false
172
- * @return Promise | void
173
- */
174
- export const setVideoProfile = (profile, swapWidthAndHeight) => {
175
- if (typeof profile === 'undefined') {
176
- profile = 30;
177
- }
178
- if (typeof swapWidthAndHeight === 'undefined') {
179
- swapWidthAndHeight = false;
180
- }
181
- return callMethod('SetVideoProfile', {
182
- profile,
183
- swapWidthAndHeight
184
- });
185
- };
186
-
187
- /**
188
- * @function 开启本地视频预览
189
- * @return Promise | void
190
- */
191
- export const startPreview = () => {
192
- return callMethod('StartPreview', {});
193
- };
194
-
195
- /**
196
- * @function 停止本地视频预览
197
- * @return Promise | void
198
- */
199
- export const stopPreview = () => {
200
- return callMethod('StopPreview', {});
201
- };
202
-
203
- /**
204
- * @function 加入频道
205
- * @param userId:Number 用户 id,必选
206
- * @param channelId:String 用课节 id 标识的频道号,必选
207
- * @param token:String Agora 提供的 token,必选
208
- * @return Promise | void
209
- */
210
- export const joinChannel = (userId, channelId, token) => {
211
- return callMethod('JoinChannel', {
212
- uid: userId,
213
- channelId,
214
- token
215
- });
216
- };
217
-
218
- /**
219
- * @function 离开频道
220
- * @return Promise | void
221
- */
222
- export const leaveChannel = () => {
223
- return callMethod('LeaveChannel', {});
224
- };
225
-
226
- /**
227
- * @function 启用本地视频
228
- * @param enabled:Boolean
229
- * @return Promise | void
230
- */
231
- export const enableLocalVideo = (enabled) => {
232
- return callMethod('REPS.EnableLocalVideo', {
233
- enabled
234
- });
235
- };
236
-
237
- /**
238
- * @function 获取系统中所有的摄像头列表
239
- * @return Promise | void
240
- */
241
- export const enumerateVideoDevices = () => {
242
- return callMethod('IVDM.EnumerateVideoDevices', {});
243
- };
244
-
245
- /**
246
- * @function 指定使用的摄像头
247
- * @param deviceId:String 摄像头 id
248
- * @return Promise | void
249
- */
250
- export const setCameraDevice = (deviceId) => {
251
- return callMethod('IVDM.SetDevice', {
252
- deviceId
253
- });
254
- };
255
-
256
- /**
257
- * @function 静音/取消静音。暂停/开始发送音频流
258
- * 将自己静音/取消静音,该方法用于禁止/允许往网络发送本地音频流
259
- * @param mute:Boolean
260
- * @return Promise | void
261
- */
262
- export const muteLocalAudioStream = (mute) => {
263
- return callMethod('REPS.MuteLocalAudioStream', {
264
- mute
265
- });
266
- };
267
-
268
- /**
269
- * @function 暂停/开始发送视频流
270
- * 该方法不影响本地视频流获取,没有禁用摄像头。
271
- * @param mute:Boolean
272
- * @return Promise | void
273
- */
274
- export const muteLocalVideoStream = (mute) => {
275
- return callMethod('REPS.MuteLocalVideoStream', {
276
- mute
277
- });
278
- };
279
-
280
- /**
281
- * @function 打开音频
282
- * @return Promise | void
283
- */
284
- export const enableAudio = () => {
285
- return callMethod('EnableAudio', {});
286
- };
287
-
288
- /**
289
- * @function 关闭音频
290
- * @return Promise | void
291
- */
292
- export const disableAudio = () => {
293
- return callMethod('DisableAudio', {});
294
- };
295
-
296
- /**
297
- * @function 获取系统中所有的扬声器列表
298
- * @return Promise | void
299
- */
300
- export const enumeratePlaybackDevices = () => {
301
- return callMethod('IADM.EnumeratePlaybackDevices', {});
302
- };
303
-
304
- /**
305
- * @function 指定扬声器
306
- * @param deviceId:String 扬声器的 Device ID,必选
307
- * 可通过 enumeratePlaybackDevices() 获取
308
- * 插拔设备不会影响 deviceId
309
- * @return Promise | void
310
- */
311
- export const setPlaybackDevice = (deviceId) => {
312
- return callMethod('IADM.SetPlaybackDevice', {
313
- deviceId
314
- });
315
- };
316
-
317
- /**
318
- * @function 获取扬声器音量
319
- * @return Promise | void
320
- */
321
- export const getPlaybackDeviceVolume = () => {
322
- return callMethod('IADM.GetPlaybackDeviceVolume', {});
323
- };
324
-
325
- /**
326
- * @function 设置扬声器音量
327
- * @param volume:Number 扬声器音量,取值 [0, 255],必选
328
- * @return Promise | void
329
- */
330
- export const setPlaybackDeviceVolume = (volume) => {
331
- return callMethod('IADM.SetPlaybackDeviceVolume', {
332
- volume
333
- });
334
- };
335
-
336
- /**
337
- * @function 控制扬声器是否静音
338
- * @param mute:Boolean 必选
339
- * @return Promise | void
340
- */
341
- export const setPlaybackDeviceMute = (mute) => {
342
- return callMethod('IADM.SetPlaybackDeviceMute', {
343
- mute
344
- });
345
- };
346
-
347
- /**
348
- * @function 启动扬声器测试
349
- * @param testAudioFilePath
350
- * @return Promise | void
351
- */
352
- export const startPlaybackDeviceTest = (testAudioFilePath) => {
353
- return callMethod('IADM.StartPlaybackDeviceTest', {
354
- testAudioFilePath
355
- });
356
- };
357
-
358
- /**
359
- * @function 停止扬声器测试
360
- * @return Promise | void
361
- */
362
- export const stopPlaybackDeviceTest = () => {
363
- return callMethod('IADM.StopPlaybackDeviceTest', {});
364
- };
365
-
366
- /**
367
- * @function 获取 App 音量
368
- * @return Promise | void
369
- */
370
- export const getApplicationVolume = () => {
371
- return callMethod('IADC.GetApplicationVolume', {});
372
- };
373
-
374
- /**
375
- * @function 设置 App 音量
376
- * @param volume 音量值,范围 [0, 255]
377
- * @return Promise | void
378
- */
379
- export const setApplicationVolume = (volume) => {
380
- return callMethod('IADC.SetApplicationVolume', {
381
- volume
382
- });
383
- };
384
-
385
- /**
386
- * @function 设置 App 静音
387
- * @param mute:Boolean
388
- * @return Promise | void
389
- */
390
- export const setApplicationMute = (mute) => {
391
- return callMethod('IADC.SetApplicationMute', {
392
- mute
393
- });
394
- };
395
-
396
- /**
397
- * @function 获取系统中所有的麦克风列表
398
- * @return Promise | void
399
- */
400
- export const enumerateRecordingDevices = () => {
401
- return callMethod('IADM.EnumerateRecordingDevices', {});
402
- };
403
-
404
- /**
405
- * @function 指定麦克风
406
- * @param deviceId:String 麦克风的 Device ID,必选
407
- * 可通过 enumerateRecordingDevices() 获取
408
- * 插拔设备不会影响 deviceId
409
- * @return Promise | void
410
- */
411
- export const setRecordingDevice = (deviceId) => {
412
- return callMethod('IADM.SetRecordingDevice', {
413
- deviceId
414
- });
415
- };
416
-
417
- /**
418
- * @function 获取麦克风音量
419
- * @return Promise | void
420
- */
421
- export const getRecordingDeviceVolume = () => {
422
- return callMethod('IADM.GetRecordingDeviceVolume', {});
423
- };
424
-
425
- /**
426
- * @function 设置麦克风音量
427
- * @param volume:Number 麦克风音量,取值 [0, 255],必选
428
- * @return Promise | void
429
- */
430
- export const setRecordingDeviceVolume = (volume) => {
431
- return callMethod('IADM.SetRecordingDeviceVolume', {
432
- volume
433
- });
434
- };
435
-
436
- /**
437
- * @function 静音麦克风
438
- * @param mute:Boolean
439
- * @return Promise | void
440
- */
441
- export const setRecordingDeviceMute = (mute) => {
442
- return callMethod('IADM.SetRecordingDeviceMute', {
443
- mute
444
- });
445
- };
446
-
447
- /**
448
- * @function 启动麦克风测试
449
- * @param indicationInterval 向应用程序上报音量信息的时间间隔,推荐 500
450
- * @return Promise | void
451
- */
452
- export const startRecordingDeviceTest = (indicationInterval) => {
453
- return callMethod('IADM.StartRecordingDeviceTest', {
454
- indicationInterval
455
- });
456
- };
457
-
458
- /**
459
- * @function 停止麦克风测试
460
- * @return Promise | void
461
- */
462
- export const stopRecordingDeviceTest = () => {
463
- return callMethod('IADM.StopRecordingDeviceTest', {});
464
- };
465
-
466
- /**
467
- * @function 启用说话者音量提示
468
- * 该方法允许 SDK 定期向应用程序反馈当前谁在说话以及说话者的音量。
469
- * @param interval 指定音量提示的时间间隔
470
- * <= 0: 禁用音量提示功能
471
- * > 0: 提示间隔,单位为毫秒
472
- * 建议设置到大于 200 毫秒
473
- * @param smooth 平滑系数。默认可以设置为 3
474
- * @return Promise | void
475
- */
476
- export const enableAudioVolumeIndication = (interval, smooth) => {
477
- return callMethod('REPS.EnableAudioVolumeIndication', {
478
- interval,
479
- smooth
480
- });
481
- };
482
-
483
- /**
484
- * @function 开启本地或者远程的视频视图
485
- * @param isLocal:Boolean 是否是本地的视频预览,必选
486
- * @param streamId:String 要拉取的视频流的 id,可选,只有拉取远程的视频流的时候才是必选的
487
- * @param domId:String <video> 标签的 id,可选
488
- * 如果传了 domId,就把视频绑定到对应的 <video> 标签上
489
- * @return Promise,可从 Promise 中获取 src,Promise.then((src) => {})
490
- */
491
- export const startLocalOrRemotePreview = (isLocal, streamId, domId) => {
492
- let playChannel = null;
493
- if (isLocal) {
494
- playChannel = window.zbyAVSDK_init_params.agora.userId;
495
- } else {
496
- playChannel = +(streamId.split('_')[2]);
497
- }
498
- const externalConstraints = {
499
- audio: false,
500
- video: {
501
- mandatory: {
502
- chromeMediaSource: 'external',
503
- chromeMediaSourceId: `ems://agora/${playChannel}`
504
- }
505
- }
506
- };
507
-
508
- return new Promise((resolve, reject) => {
509
- const handleExternalSuccess = (stream) => {
510
- stream.oninactive = () => {
511
- console.log('Stream inactive');
512
- };
513
- const src = window.URL.createObjectURL(stream);
514
- if (domId) {
515
- document.querySelector(domId).src = src;
516
- }
517
- resolve(src);
518
- };
519
-
520
- const handleExternalError = (error) => {
521
- if (error.name === 'ConstraintNotSatisfiedError') {
522
- console.error('ConstraintNotSatisfiedError');
523
- // console.error(`The resolution ${cameraConstraints.video.width.exact}x${
524
- // cameraConstraints.video.width.exact} px is not supported by your device.`);
525
- } else if (error.name === 'PermissionDeniedError') {
526
- console.error(
527
- 'Permissions have not been granted to use your camera and ' +
528
- 'microphone, you need to allow the page access to your devices in ' +
529
- 'order for the demo to work.'
530
- );
531
- }
532
- console.error(`getUserMedia error: ${error.name}`, error);
533
- if (domId) {
534
- document.querySelector(domId).src = '';
535
- }
536
- reject('');
537
- };
538
-
539
- if (navigator.webkitGetUserMedia) {
540
- navigator.webkitGetUserMedia(
541
- externalConstraints,
542
- handleExternalSuccess,
543
- handleExternalError
544
- );
545
- }
546
- });
547
- };
548
-
549
- /**
550
- * @function 初始化
551
- * @param args:Object
552
- * {
553
- * extensionVersion, // String,扩展版本号,必选
554
- * appId, // String,Agora 秘钥,必选
555
- * userId, // Number,用户 id,必选
556
- * roomId, // String,频道号(房间号),必选
557
- * token, // String,Agora 提供的 token,可选,默认与 appId 相同
558
- * swapWidthAndHeight, // Boolean,是否交换宽和高,可选,默认 false
559
- * videoProfile, // Number,视频分辨率、帧率和码率,可选,默认 30
560
- * channelProfile // Number,频道模式,可选,默认 0
561
- * }
562
- * @return Promise
563
- */
564
- export const init = async (args) => {
565
- await loadAgora(args.extensionVersion);
566
- addListener();
567
- await startEngine(args.appId);
568
- await setChannelProfile(args.channelProfile);
569
- await enableVideo();
570
- await setVideoProfile(args.videoProfile, args.swapWidthAndHeight);
571
- if (typeof args.token === 'undefined') {
572
- await joinChannel(args.userId, args.roomId, args.appId);
573
- } else {
574
- await joinChannel(args.userId, args.roomId, args.token);
575
- }
576
- await setupLocalVideo(args.userId);
577
- // 初始化的时候不推流
578
- await muteLocalVideoStream(true);
579
- // 初始化的时候不打开麦克风
580
- await muteLocalAudioStream(true);
581
- // 初始化的时候不打开摄像头
582
- await enableLocalVideo(false);
583
- };
584
-
585
- /**
586
- * @function 开始推流
587
- * @return Promise
588
- */
589
- export const startPushFlow = async () => {
590
- await muteLocalVideoStream(false);
591
- await muteLocalAudioStream(false);
592
- };
593
-
594
- /**
595
- * @function 停止推流
596
- * @return Promise
597
- */
598
- export const stopPushFlow = async () => {
599
- await muteLocalVideoStream(true);
600
- await muteLocalAudioStream(true);
601
- };
602
-
603
- /**
604
- * @function 初始化拉流
605
- * @param streamId:String 被拉取的流的 id,必选
606
- * @param domId:String <video> 标签的 id,可选
607
- * 如果传了就把视频绑定到对应的 <video> 标签上
608
- * @return src:String 视频预览地址
609
- */
610
- export const initPullFlow = async (streamId, domId) => {
611
- await setupRemoteVideo(+(streamId.split('_')[2]));
612
- return await startLocalOrRemotePreview(false, streamId, domId);
613
- };
614
-
615
- /**
616
- * @function 恢复拉指定用户的流
617
- * @param streamId:String 被拉取的流的 id,必选
618
- * @return Promise
619
- */
620
- export const startPullFlow = async (streamId) => {
621
- const userId = +(streamId.split('_')[2]);
622
- await muteRemoteVideoStream(userId, false);
623
- await muteRemoteAudioStream(userId, false);
624
- };
625
-
626
- /**
627
- * @function 暂停拉指定用户的流
628
- * @param streamId:String 被拉取的流的 id,必选
629
- * @return Promise
630
- */
631
- export const stopPullFlow = async (streamId) => {
632
- const userId = +(streamId.split('_')[2]);
633
- await muteRemoteVideoStream(userId, true);
634
- await muteRemoteAudioStream(userId, true);
635
- };
636
-
637
- /**
638
- * @function 暂停指定远端视频流
639
- * @param userId:Number 被拉取视频流的用户的 id,必选
640
- * @param mute:Boolean 必选
641
- * @return Promise | void
642
- */
643
- export const muteRemoteVideoStream = (userId, mute) => {
644
- return callMethod('MuteRemoteVideoStream', {
645
- uid: userId,
646
- mute
647
- });
648
- };
649
-
650
- /**
651
- * @function 暂停指定远端音频流
652
- * @param userId:Number 被拉取音频流的用户的 id,必选
653
- * @param mute:Boolean 必选
654
- * @return Promise | void
655
- */
656
- export const muteRemoteAudioStream = (userId, mute) => {
657
- return callMethod('MuteRemoteAudioStream', {
658
- uid: userId,
659
- mute
660
- });
661
- };
662
-
663
- export default {
664
- loadAgora,
665
- unloadAgora,
666
- startEngine,
667
- setVideoProfile,
668
- setChannelProfile,
669
- joinChannel,
670
- leaveChannel,
671
- enumerateVideoDevices,
672
- setCameraDevice,
673
- enableAudio,
674
- disableAudio,
675
- enableVideo,
676
- disableVideo,
677
- muteLocalAudioStream,
678
- muteLocalVideoStream,
679
- startPreview,
680
- stopPreview,
681
- enableLocalVideo,
682
- setupLocalVideo,
683
- setupRemoteVideo,
684
- startLocalOrRemotePreview,
685
- enumeratePlaybackDevices,
686
- setPlaybackDevice,
687
- startPlaybackDeviceTest,
688
- stopPlaybackDeviceTest,
689
- getPlaybackDeviceVolume,
690
- setPlaybackDeviceVolume,
691
- setPlaybackDeviceMute,
692
- getApplicationVolume,
693
- setApplicationVolume,
694
- setApplicationMute,
695
- enumerateRecordingDevices,
696
- setRecordingDevice,
697
- getRecordingDeviceVolume,
698
- setRecordingDeviceVolume,
699
- setRecordingDeviceMute,
700
- startRecordingDeviceTest,
701
- stopRecordingDeviceTest,
702
- enableAudioVolumeIndication,
703
- init,
704
- startPushFlow,
705
- stopPushFlow,
706
- initPullFlow,
707
- startPullFlow,
708
- stopPullFlow,
709
- muteRemoteVideoStream,
710
- muteRemoteAudioStream
711
- };
1
+ /**
2
+ * @File: Agora 音视频 SDK
3
+ * @Author: xuyuanrui
4
+ * @Email: raywhbxyr@163.com
5
+ * @Date: 2018-08-06 11:00:29
6
+ **/
7
+
8
+ // 扩展标识
9
+ const extensionId = 'agora_ext';
10
+ // 端提供的 API 入口
11
+ const EM = window.EM;
12
+
13
+ /**
14
+ * @function 调用端提供的回调方法
15
+ * @param name:String 回调方法名,必选
16
+ * @param args:Object 回调参数,必选
17
+ * @return Promise | void
18
+ */
19
+ const callMethod = (name, args) => {
20
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
21
+ if (EM) {
22
+ return new Promise((resolve, reject) => {
23
+ EM.CallMethod(
24
+ extensionId,
25
+ name,
26
+ JSON.stringify(args),
27
+ (code, msg) => {
28
+ console.log(`${name} Code: ${code}\nMessage: ${msg}`);
29
+ resolve({
30
+ code,
31
+ msg
32
+ });
33
+ }
34
+ );
35
+ });
36
+ }
37
+ };
38
+
39
+ /**
40
+ * @function 加载声网扩展
41
+ * @param extensionVersion:String 扩展版本号,必选
42
+ * @return Promise | void
43
+ */
44
+ export const loadAgora = (extensionVersion) => {
45
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
46
+ if (EM) {
47
+ return new Promise((resolve, reject) => {
48
+ EM.Load(
49
+ extensionId,
50
+ extensionVersion,
51
+ false,
52
+ (code, msg) => {
53
+ console.log(`loadAgora Code: ${code}\nMessage: ${msg}`);
54
+ resolve();
55
+ }
56
+ );
57
+ });
58
+ }
59
+ };
60
+
61
+ /**
62
+ * @function 卸载声网扩展
63
+ * @return Promise | void
64
+ */
65
+ export const unloadAgora = () => {
66
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
67
+ if (EM) {
68
+ return new Promise((resolve, reject) => {
69
+ EM.UnLoad(
70
+ extensionId,
71
+ (code, msg) => {
72
+ console.log(`unloadAgora Code: ${code}\nMessage: ${msg}`);
73
+ resolve();
74
+ }
75
+ );
76
+ });
77
+ }
78
+ };
79
+
80
+ /**
81
+ * @function 添加扩展监听机制
82
+ * @return void
83
+ */
84
+ const addListener = () => {
85
+ // EM 是寄宿于端的,浏览器中并不存在,为防止报错需要先进行能力检测
86
+ if (EM) {
87
+ EM.AddListener(extensionId, (event, data) => {
88
+ console.log(`AddListener Event: ${event}\nData: ${data}`);
89
+ });
90
+ }
91
+ };
92
+
93
+ /**
94
+ * @function 创建 IRtcEngine 对象
95
+ * @param appId:String Agora 秘钥,必选
96
+ * @return Promise | void
97
+ */
98
+ export const startEngine = (appId) => {
99
+ return callMethod('StartEngine', {
100
+ appId
101
+ });
102
+ };
103
+
104
+ /**
105
+ * @function 设置频道属性
106
+ * 该方法用于设置频道模式(profile),
107
+ * Agora RtcEngine 需知道应用程序的使用场景(例如通信模式或直播模式),
108
+ * 从而使用不同的优化手段。
109
+ * @param profile 频道模式,可选,默认 0,即使用通信模式,
110
+ * 用于常见的一对一或群聊,频道中的任何用户可以自由说话
111
+ * @return Promise | void
112
+ */
113
+ export const setChannelProfile = (profile) => {
114
+ if (typeof profile === 'undefined') {
115
+ profile = 0;
116
+ }
117
+ return callMethod('SetChannelProfile', {
118
+ profile
119
+ });
120
+ };
121
+
122
+ /**
123
+ * @function 打开视频模式
124
+ * 可以在加入频道前或者通话中调用,在加入频道前调用,
125
+ * 则自动开启视频模式,在通话中调用则由音频模式切换为视频模式。
126
+ * 调用 disableVideo() 方法可关闭视频模式。
127
+ * @return Promise | void
128
+ */
129
+ export const enableVideo = () => {
130
+ return callMethod('EnableVideo', {});
131
+ };
132
+
133
+ /**
134
+ * @function 关闭视频模式
135
+ * 可以在加入频道前或者通话中调用,在加入频道前调用,
136
+ * 则自动开启纯音频模式,在通话中调用则由视频模式切换为纯音频频模式。
137
+ * 调用 enableVideo() 方法可开启视频模式。
138
+ * @return Promise | void
139
+ */
140
+ export const disableVideo = () => {
141
+ return callMethod('DisableVideo', {});
142
+ };
143
+
144
+ /**
145
+ * @function 设置本地视频显示属性
146
+ * @param userId:Number 用户 id
147
+ * @return Promise | void
148
+ */
149
+ export const setupLocalVideo = (userId) => {
150
+ return callMethod('SetupLocalVideo', {
151
+ uid: userId
152
+ });
153
+ };
154
+
155
+ /**
156
+ * @function 设置远端视频显示属性
157
+ * @param userId:Number 用户 id
158
+ * @return Promise | void
159
+ */
160
+ export const setupRemoteVideo = (userId) => {
161
+ return callMethod('SetupRemoteVideo', {
162
+ uid: userId
163
+ });
164
+ };
165
+
166
+ /**
167
+ * @function 设置本地视频编码属性
168
+ * 应在调用 enableVideo 后设置视频属性
169
+ * 应在调用 joinChannel/startPreview 前设置视频属性
170
+ * @param profile:Number 视频分辨率、帧率和码率,可选,默认 30
171
+ * @param swapWidthAndHeight:Boolean 是否交换宽和高,可选,默认 false
172
+ * @return Promise | void
173
+ */
174
+ export const setVideoProfile = (profile, swapWidthAndHeight) => {
175
+ if (typeof profile === 'undefined') {
176
+ profile = 30;
177
+ }
178
+ if (typeof swapWidthAndHeight === 'undefined') {
179
+ swapWidthAndHeight = false;
180
+ }
181
+ return callMethod('SetVideoProfile', {
182
+ profile,
183
+ swapWidthAndHeight
184
+ });
185
+ };
186
+
187
+ /**
188
+ * @function 开启本地视频预览
189
+ * @return Promise | void
190
+ */
191
+ export const startPreview = () => {
192
+ return callMethod('StartPreview', {});
193
+ };
194
+
195
+ /**
196
+ * @function 停止本地视频预览
197
+ * @return Promise | void
198
+ */
199
+ export const stopPreview = () => {
200
+ return callMethod('StopPreview', {});
201
+ };
202
+
203
+ /**
204
+ * @function 加入频道
205
+ * @param userId:Number 用户 id,必选
206
+ * @param channelId:String 用课节 id 标识的频道号,必选
207
+ * @param token:String Agora 提供的 token,必选
208
+ * @return Promise | void
209
+ */
210
+ export const joinChannel = (userId, channelId, token) => {
211
+ return callMethod('JoinChannel', {
212
+ uid: userId,
213
+ channelId,
214
+ token
215
+ });
216
+ };
217
+
218
+ /**
219
+ * @function 离开频道
220
+ * @return Promise | void
221
+ */
222
+ export const leaveChannel = () => {
223
+ return callMethod('LeaveChannel', {});
224
+ };
225
+
226
+ /**
227
+ * @function 启用本地视频
228
+ * @param enabled:Boolean
229
+ * @return Promise | void
230
+ */
231
+ export const enableLocalVideo = (enabled) => {
232
+ return callMethod('REPS.EnableLocalVideo', {
233
+ enabled
234
+ });
235
+ };
236
+
237
+ /**
238
+ * @function 获取系统中所有的摄像头列表
239
+ * @return Promise | void
240
+ */
241
+ export const enumerateVideoDevices = () => {
242
+ return callMethod('IVDM.EnumerateVideoDevices', {});
243
+ };
244
+
245
+ /**
246
+ * @function 指定使用的摄像头
247
+ * @param deviceId:String 摄像头 id
248
+ * @return Promise | void
249
+ */
250
+ export const setCameraDevice = (deviceId) => {
251
+ return callMethod('IVDM.SetDevice', {
252
+ deviceId
253
+ });
254
+ };
255
+
256
+ /**
257
+ * @function 静音/取消静音。暂停/开始发送音频流
258
+ * 将自己静音/取消静音,该方法用于禁止/允许往网络发送本地音频流
259
+ * @param mute:Boolean
260
+ * @return Promise | void
261
+ */
262
+ export const muteLocalAudioStream = (mute) => {
263
+ return callMethod('REPS.MuteLocalAudioStream', {
264
+ mute
265
+ });
266
+ };
267
+
268
+ /**
269
+ * @function 暂停/开始发送视频流
270
+ * 该方法不影响本地视频流获取,没有禁用摄像头。
271
+ * @param mute:Boolean
272
+ * @return Promise | void
273
+ */
274
+ export const muteLocalVideoStream = (mute) => {
275
+ return callMethod('REPS.MuteLocalVideoStream', {
276
+ mute
277
+ });
278
+ };
279
+
280
+ /**
281
+ * @function 打开音频
282
+ * @return Promise | void
283
+ */
284
+ export const enableAudio = () => {
285
+ return callMethod('EnableAudio', {});
286
+ };
287
+
288
+ /**
289
+ * @function 关闭音频
290
+ * @return Promise | void
291
+ */
292
+ export const disableAudio = () => {
293
+ return callMethod('DisableAudio', {});
294
+ };
295
+
296
+ /**
297
+ * @function 获取系统中所有的扬声器列表
298
+ * @return Promise | void
299
+ */
300
+ export const enumeratePlaybackDevices = () => {
301
+ return callMethod('IADM.EnumeratePlaybackDevices', {});
302
+ };
303
+
304
+ /**
305
+ * @function 指定扬声器
306
+ * @param deviceId:String 扬声器的 Device ID,必选
307
+ * 可通过 enumeratePlaybackDevices() 获取
308
+ * 插拔设备不会影响 deviceId
309
+ * @return Promise | void
310
+ */
311
+ export const setPlaybackDevice = (deviceId) => {
312
+ return callMethod('IADM.SetPlaybackDevice', {
313
+ deviceId
314
+ });
315
+ };
316
+
317
+ /**
318
+ * @function 获取扬声器音量
319
+ * @return Promise | void
320
+ */
321
+ export const getPlaybackDeviceVolume = () => {
322
+ return callMethod('IADM.GetPlaybackDeviceVolume', {});
323
+ };
324
+
325
+ /**
326
+ * @function 设置扬声器音量
327
+ * @param volume:Number 扬声器音量,取值 [0, 255],必选
328
+ * @return Promise | void
329
+ */
330
+ export const setPlaybackDeviceVolume = (volume) => {
331
+ return callMethod('IADM.SetPlaybackDeviceVolume', {
332
+ volume
333
+ });
334
+ };
335
+
336
+ /**
337
+ * @function 控制扬声器是否静音
338
+ * @param mute:Boolean 必选
339
+ * @return Promise | void
340
+ */
341
+ export const setPlaybackDeviceMute = (mute) => {
342
+ return callMethod('IADM.SetPlaybackDeviceMute', {
343
+ mute
344
+ });
345
+ };
346
+
347
+ /**
348
+ * @function 启动扬声器测试
349
+ * @param testAudioFilePath
350
+ * @return Promise | void
351
+ */
352
+ export const startPlaybackDeviceTest = (testAudioFilePath) => {
353
+ return callMethod('IADM.StartPlaybackDeviceTest', {
354
+ testAudioFilePath
355
+ });
356
+ };
357
+
358
+ /**
359
+ * @function 停止扬声器测试
360
+ * @return Promise | void
361
+ */
362
+ export const stopPlaybackDeviceTest = () => {
363
+ return callMethod('IADM.StopPlaybackDeviceTest', {});
364
+ };
365
+
366
+ /**
367
+ * @function 获取 App 音量
368
+ * @return Promise | void
369
+ */
370
+ export const getApplicationVolume = () => {
371
+ return callMethod('IADC.GetApplicationVolume', {});
372
+ };
373
+
374
+ /**
375
+ * @function 设置 App 音量
376
+ * @param volume 音量值,范围 [0, 255]
377
+ * @return Promise | void
378
+ */
379
+ export const setApplicationVolume = (volume) => {
380
+ return callMethod('IADC.SetApplicationVolume', {
381
+ volume
382
+ });
383
+ };
384
+
385
+ /**
386
+ * @function 设置 App 静音
387
+ * @param mute:Boolean
388
+ * @return Promise | void
389
+ */
390
+ export const setApplicationMute = (mute) => {
391
+ return callMethod('IADC.SetApplicationMute', {
392
+ mute
393
+ });
394
+ };
395
+
396
+ /**
397
+ * @function 获取系统中所有的麦克风列表
398
+ * @return Promise | void
399
+ */
400
+ export const enumerateRecordingDevices = () => {
401
+ return callMethod('IADM.EnumerateRecordingDevices', {});
402
+ };
403
+
404
+ /**
405
+ * @function 指定麦克风
406
+ * @param deviceId:String 麦克风的 Device ID,必选
407
+ * 可通过 enumerateRecordingDevices() 获取
408
+ * 插拔设备不会影响 deviceId
409
+ * @return Promise | void
410
+ */
411
+ export const setRecordingDevice = (deviceId) => {
412
+ return callMethod('IADM.SetRecordingDevice', {
413
+ deviceId
414
+ });
415
+ };
416
+
417
+ /**
418
+ * @function 获取麦克风音量
419
+ * @return Promise | void
420
+ */
421
+ export const getRecordingDeviceVolume = () => {
422
+ return callMethod('IADM.GetRecordingDeviceVolume', {});
423
+ };
424
+
425
+ /**
426
+ * @function 设置麦克风音量
427
+ * @param volume:Number 麦克风音量,取值 [0, 255],必选
428
+ * @return Promise | void
429
+ */
430
+ export const setRecordingDeviceVolume = (volume) => {
431
+ return callMethod('IADM.SetRecordingDeviceVolume', {
432
+ volume
433
+ });
434
+ };
435
+
436
+ /**
437
+ * @function 静音麦克风
438
+ * @param mute:Boolean
439
+ * @return Promise | void
440
+ */
441
+ export const setRecordingDeviceMute = (mute) => {
442
+ return callMethod('IADM.SetRecordingDeviceMute', {
443
+ mute
444
+ });
445
+ };
446
+
447
+ /**
448
+ * @function 启动麦克风测试
449
+ * @param indicationInterval 向应用程序上报音量信息的时间间隔,推荐 500
450
+ * @return Promise | void
451
+ */
452
+ export const startRecordingDeviceTest = (indicationInterval) => {
453
+ return callMethod('IADM.StartRecordingDeviceTest', {
454
+ indicationInterval
455
+ });
456
+ };
457
+
458
+ /**
459
+ * @function 停止麦克风测试
460
+ * @return Promise | void
461
+ */
462
+ export const stopRecordingDeviceTest = () => {
463
+ return callMethod('IADM.StopRecordingDeviceTest', {});
464
+ };
465
+
466
+ /**
467
+ * @function 启用说话者音量提示
468
+ * 该方法允许 SDK 定期向应用程序反馈当前谁在说话以及说话者的音量。
469
+ * @param interval 指定音量提示的时间间隔
470
+ * <= 0: 禁用音量提示功能
471
+ * > 0: 提示间隔,单位为毫秒
472
+ * 建议设置到大于 200 毫秒
473
+ * @param smooth 平滑系数。默认可以设置为 3
474
+ * @return Promise | void
475
+ */
476
+ export const enableAudioVolumeIndication = (interval, smooth) => {
477
+ return callMethod('REPS.EnableAudioVolumeIndication', {
478
+ interval,
479
+ smooth
480
+ });
481
+ };
482
+
483
+ /**
484
+ * @function 开启本地或者远程的视频视图
485
+ * @param isLocal:Boolean 是否是本地的视频预览,必选
486
+ * @param streamId:String 要拉取的视频流的 id,可选,只有拉取远程的视频流的时候才是必选的
487
+ * @param domId:String <video> 标签的 id,可选
488
+ * 如果传了 domId,就把视频绑定到对应的 <video> 标签上
489
+ * @return Promise,可从 Promise 中获取 src,Promise.then((src) => {})
490
+ */
491
+ export const startLocalOrRemotePreview = (isLocal, streamId, domId) => {
492
+ let playChannel = null;
493
+ if (isLocal) {
494
+ playChannel = window.zbyAVSDK_init_params.agora.userId;
495
+ } else {
496
+ playChannel = +(streamId.split('_')[2]);
497
+ }
498
+ const externalConstraints = {
499
+ audio: false,
500
+ video: {
501
+ mandatory: {
502
+ chromeMediaSource: 'external',
503
+ chromeMediaSourceId: `ems://agora/${playChannel}`
504
+ }
505
+ }
506
+ };
507
+
508
+ return new Promise((resolve, reject) => {
509
+ const handleExternalSuccess = (stream) => {
510
+ stream.oninactive = () => {
511
+ console.log('Stream inactive');
512
+ };
513
+ const src = window.URL.createObjectURL(stream);
514
+ if (domId) {
515
+ document.querySelector(domId).src = src;
516
+ }
517
+ resolve(src);
518
+ };
519
+
520
+ const handleExternalError = (error) => {
521
+ if (error.name === 'ConstraintNotSatisfiedError') {
522
+ console.error('ConstraintNotSatisfiedError');
523
+ // console.error(`The resolution ${cameraConstraints.video.width.exact}x${
524
+ // cameraConstraints.video.width.exact} px is not supported by your device.`);
525
+ } else if (error.name === 'PermissionDeniedError') {
526
+ console.error(
527
+ 'Permissions have not been granted to use your camera and ' +
528
+ 'microphone, you need to allow the page access to your devices in ' +
529
+ 'order for the demo to work.'
530
+ );
531
+ }
532
+ console.error(`getUserMedia error: ${error.name}`, error);
533
+ if (domId) {
534
+ document.querySelector(domId).src = '';
535
+ }
536
+ reject('');
537
+ };
538
+
539
+ if (navigator.webkitGetUserMedia) {
540
+ navigator.webkitGetUserMedia(
541
+ externalConstraints,
542
+ handleExternalSuccess,
543
+ handleExternalError
544
+ );
545
+ }
546
+ });
547
+ };
548
+
549
+ /**
550
+ * @function 初始化
551
+ * @param args:Object
552
+ * {
553
+ * extensionVersion, // String,扩展版本号,必选
554
+ * appId, // String,Agora 秘钥,必选
555
+ * userId, // Number,用户 id,必选
556
+ * roomId, // String,频道号(房间号),必选
557
+ * token, // String,Agora 提供的 token,可选,默认与 appId 相同
558
+ * swapWidthAndHeight, // Boolean,是否交换宽和高,可选,默认 false
559
+ * videoProfile, // Number,视频分辨率、帧率和码率,可选,默认 30
560
+ * channelProfile // Number,频道模式,可选,默认 0
561
+ * }
562
+ * @return Promise
563
+ */
564
+ export const init = async (args) => {
565
+ await loadAgora(args.extensionVersion);
566
+ addListener();
567
+ await startEngine(args.appId);
568
+ await setChannelProfile(args.channelProfile);
569
+ await enableVideo();
570
+ await setVideoProfile(args.videoProfile, args.swapWidthAndHeight);
571
+ if (typeof args.token === 'undefined') {
572
+ await joinChannel(args.userId, args.roomId, args.appId);
573
+ } else {
574
+ await joinChannel(args.userId, args.roomId, args.token);
575
+ }
576
+ await setupLocalVideo(args.userId);
577
+ // 初始化的时候不推流
578
+ await muteLocalVideoStream(true);
579
+ // 初始化的时候不打开麦克风
580
+ await muteLocalAudioStream(true);
581
+ // 初始化的时候不打开摄像头
582
+ await enableLocalVideo(false);
583
+ };
584
+
585
+ /**
586
+ * @function 开始推流
587
+ * @return Promise
588
+ */
589
+ export const startPushFlow = async () => {
590
+ await muteLocalVideoStream(false);
591
+ await muteLocalAudioStream(false);
592
+ };
593
+
594
+ /**
595
+ * @function 停止推流
596
+ * @return Promise
597
+ */
598
+ export const stopPushFlow = async () => {
599
+ await muteLocalVideoStream(true);
600
+ await muteLocalAudioStream(true);
601
+ };
602
+
603
+ /**
604
+ * @function 初始化拉流
605
+ * @param streamId:String 被拉取的流的 id,必选
606
+ * @param domId:String <video> 标签的 id,可选
607
+ * 如果传了就把视频绑定到对应的 <video> 标签上
608
+ * @return src:String 视频预览地址
609
+ */
610
+ export const initPullFlow = async (streamId, domId) => {
611
+ await setupRemoteVideo(+(streamId.split('_')[2]));
612
+ return await startLocalOrRemotePreview(false, streamId, domId);
613
+ };
614
+
615
+ /**
616
+ * @function 恢复拉指定用户的流
617
+ * @param streamId:String 被拉取的流的 id,必选
618
+ * @return Promise
619
+ */
620
+ export const startPullFlow = async (streamId) => {
621
+ const userId = +(streamId.split('_')[2]);
622
+ await muteRemoteVideoStream(userId, false);
623
+ await muteRemoteAudioStream(userId, false);
624
+ };
625
+
626
+ /**
627
+ * @function 暂停拉指定用户的流
628
+ * @param streamId:String 被拉取的流的 id,必选
629
+ * @return Promise
630
+ */
631
+ export const stopPullFlow = async (streamId) => {
632
+ const userId = +(streamId.split('_')[2]);
633
+ await muteRemoteVideoStream(userId, true);
634
+ await muteRemoteAudioStream(userId, true);
635
+ };
636
+
637
+ /**
638
+ * @function 暂停指定远端视频流
639
+ * @param userId:Number 被拉取视频流的用户的 id,必选
640
+ * @param mute:Boolean 必选
641
+ * @return Promise | void
642
+ */
643
+ export const muteRemoteVideoStream = (userId, mute) => {
644
+ return callMethod('MuteRemoteVideoStream', {
645
+ uid: userId,
646
+ mute
647
+ });
648
+ };
649
+
650
+ /**
651
+ * @function 暂停指定远端音频流
652
+ * @param userId:Number 被拉取音频流的用户的 id,必选
653
+ * @param mute:Boolean 必选
654
+ * @return Promise | void
655
+ */
656
+ export const muteRemoteAudioStream = (userId, mute) => {
657
+ return callMethod('MuteRemoteAudioStream', {
658
+ uid: userId,
659
+ mute
660
+ });
661
+ };
662
+
663
+ export default {
664
+ loadAgora,
665
+ unloadAgora,
666
+ startEngine,
667
+ setVideoProfile,
668
+ setChannelProfile,
669
+ joinChannel,
670
+ leaveChannel,
671
+ enumerateVideoDevices,
672
+ setCameraDevice,
673
+ enableAudio,
674
+ disableAudio,
675
+ enableVideo,
676
+ disableVideo,
677
+ muteLocalAudioStream,
678
+ muteLocalVideoStream,
679
+ startPreview,
680
+ stopPreview,
681
+ enableLocalVideo,
682
+ setupLocalVideo,
683
+ setupRemoteVideo,
684
+ startLocalOrRemotePreview,
685
+ enumeratePlaybackDevices,
686
+ setPlaybackDevice,
687
+ startPlaybackDeviceTest,
688
+ stopPlaybackDeviceTest,
689
+ getPlaybackDeviceVolume,
690
+ setPlaybackDeviceVolume,
691
+ setPlaybackDeviceMute,
692
+ getApplicationVolume,
693
+ setApplicationVolume,
694
+ setApplicationMute,
695
+ enumerateRecordingDevices,
696
+ setRecordingDevice,
697
+ getRecordingDeviceVolume,
698
+ setRecordingDeviceVolume,
699
+ setRecordingDeviceMute,
700
+ startRecordingDeviceTest,
701
+ stopRecordingDeviceTest,
702
+ enableAudioVolumeIndication,
703
+ init,
704
+ startPushFlow,
705
+ stopPushFlow,
706
+ initPullFlow,
707
+ startPullFlow,
708
+ stopPullFlow,
709
+ muteRemoteVideoStream,
710
+ muteRemoteAudioStream
711
+ };