@realsee/live 0.4.0-beta.6 → 0.5.0-alpha.1

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.
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var JSBridge = require('@realsee/jsbridge-x');
6
- var amazonChimeSdkJs = require('amazon-chime-sdk-js');
7
6
  var TRTC = require('trtc-js-sdk');
7
+ var amazonChimeSdkJs = require('amazon-chime-sdk-js');
8
8
  var React = require('react');
9
9
 
10
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -131,6 +131,31 @@ class Subscribe {
131
131
  class CoreRTC extends Subscribe {
132
132
  }
133
133
 
134
+ /******************************************************************************
135
+ Copyright (c) Microsoft Corporation.
136
+
137
+ Permission to use, copy, modify, and/or distribute this software for any
138
+ purpose with or without fee is hereby granted.
139
+
140
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
141
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
142
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
143
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
144
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
145
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
146
+ PERFORMANCE OF THIS SOFTWARE.
147
+ ***************************************************************************** */
148
+
149
+ function __awaiter(thisArg, _arguments, P, generator) {
150
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
151
+ return new (P || (P = Promise))(function (resolve, reject) {
152
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
153
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
154
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
155
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
156
+ });
157
+ }
158
+
134
159
  /**
135
160
  * rtc 类型
136
161
  */
@@ -184,24 +209,21 @@ class BrowserRTC extends CoreRTC {
184
209
  client: null,
185
210
  stream: null,
186
211
  };
187
- this.join = async (options) => {
212
+ this.join = (options) => __awaiter(this, void 0, void 0, function* () {
188
213
  var _a;
189
214
  this.emit('joinWillStart');
190
- const createClientOptions = await this._getVoiceSign({
215
+ const createClientOptions = yield this._getVoiceSign({
191
216
  voiceId: options.voiceId,
192
217
  roomId: options.roomId,
193
218
  userId: options.userId,
194
219
  });
195
220
  // 1. 创建client
196
- this._trtc.client = TRTC__default["default"].createClient({
197
- mode: 'rtc',
198
- ...createClientOptions,
199
- });
221
+ this._trtc.client = TRTC__default["default"].createClient(Object.assign({ mode: 'rtc' }, createClientOptions));
200
222
  (_a = this._trtc.client) === null || _a === void 0 ? void 0 : _a.enableAudioVolumeEvaluation();
201
223
  // 2. 订阅事件
202
224
  this._registerRtcEvent();
203
225
  // 3. 加入语音房间
204
- let result = await new Promise((resolve) => {
226
+ let result = yield new Promise((resolve) => {
205
227
  var _a;
206
228
  (_a = this._trtc.client) === null || _a === void 0 ? void 0 : _a.join({ roomId: Number(options.voiceId) }).then(() => resolve(true)).catch(() => resolve(false));
207
229
  });
@@ -215,12 +237,12 @@ class BrowserRTC extends CoreRTC {
215
237
  video: false,
216
238
  });
217
239
  // 5. 初始化本地流
218
- result = await new Promise((resolve) => {
240
+ result = yield new Promise((resolve) => {
219
241
  var _a;
220
242
  (_a = this._trtc.stream) === null || _a === void 0 ? void 0 : _a.initialize().then(() => resolve(true)).catch(() => resolve(false));
221
243
  });
222
244
  // 6. 发布本地流
223
- result = await new Promise((resolve) => {
245
+ result = yield new Promise((resolve) => {
224
246
  var _a;
225
247
  (_a = this._trtc.client) === null || _a === void 0 ? void 0 : _a.publish(this._trtc.stream).then(() => resolve(true)).catch(() => resolve(false));
226
248
  });
@@ -228,7 +250,7 @@ class BrowserRTC extends CoreRTC {
228
250
  if (this.joined)
229
251
  this.emit('joined');
230
252
  return result;
231
- };
253
+ });
232
254
  this._handleStreamAdded = (event) => {
233
255
  var _a;
234
256
  const remoteStream = event.stream;
@@ -256,17 +278,17 @@ class BrowserRTC extends CoreRTC {
256
278
  document.body.appendChild(this.$dom);
257
279
  }
258
280
  quit() {
259
- return new Promise(async (resolve) => {
281
+ return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
260
282
  var _a, _b;
261
283
  this.joined = false;
262
284
  if (this._trtc.stream) {
263
- await ((_a = this._trtc.client) === null || _a === void 0 ? void 0 : _a.unpublish(this._trtc.stream));
285
+ yield ((_a = this._trtc.client) === null || _a === void 0 ? void 0 : _a.unpublish(this._trtc.stream));
264
286
  this._trtc.stream.stop();
265
287
  this._trtc.stream.close();
266
288
  this._trtc.stream = null;
267
289
  }
268
290
  (_b = this._trtc.client) === null || _b === void 0 ? void 0 : _b.leave().then(() => (this._trtc.client = null)).then(() => resolve(true)).catch(() => resolve(false));
269
- });
291
+ }));
270
292
  }
271
293
  detectMicro() {
272
294
  return new Promise((resolve) => {
@@ -438,65 +460,64 @@ class BrowserRTC4Chime extends CoreRTC {
438
460
  * @param options
439
461
  * @returns
440
462
  */
441
- async join(options) {
442
- return new Promise(async (success, fail) => {
443
- var _a;
444
- this.emit('joinWillStart');
445
- try {
446
- // 取签名
447
- const { sdkAppId, userId, roomId, userSig } = await this._getVoiceSign({
448
- ...options,
449
- roomId: options.roomId || 0,
450
- });
451
- this.userId = userId;
452
- const { attendence, vendor_wrapper, } = JSON.parse(decodeURIComponent(userSig));
453
- // 初始化配置
454
- const configuration = new amazonChimeSdkJs.MeetingSessionConfiguration({
455
- Meeting: vendor_wrapper,
456
- }, {
457
- Attendee: {
458
- ExternalUserId: attendence.external_user_id,
459
- AttendeeId: attendence.attendee_id,
460
- JoinToken: attendence.join_token,
461
- },
462
- });
463
- // 初始化会议会话
464
- this.meetingSession = new amazonChimeSdkJs.DefaultMeetingSession(configuration, this.logger, this.deviceController);
465
- // 注册事件
466
- this._registerRtcEvent();
467
- // 绑定监听器
468
- this.meetingSession.audioVideo.addDeviceChangeObserver(this.deviceChangeObserver);
469
- this.meetingSession.audioVideo.addObserver(this.audioVideoObserver);
470
- // 绑定播放器
471
- this.meetingSession.audioVideo.bindAudioElement(this.$audio);
472
- const observer = {
473
- audioVideoDidStart: () => {
474
- var _a;
475
- (_a = this.meetingSession) === null || _a === void 0 ? void 0 : _a.audioVideo.realtimeMuteLocalAudio();
476
- this.joined = true;
477
- this.emit('joined');
478
- success(true);
479
- },
480
- audioVideoDidStop: () => {
481
- this.joined = false;
482
- success(false);
483
- },
484
- };
485
- this.meetingSession.audioVideo.addObserver(observer);
486
- // 选择语音输入设备
487
- const audioInputDevices = await this.deviceController.listAudioInputDevices(true);
488
- const defaultAudioInput = audioInputDevices.find((device) => device.deviceId === 'default');
489
- const otherAudioInput = audioInputDevices.find((device) => device.deviceId !== '');
490
- this.audioInput = defaultAudioInput || otherAudioInput;
491
- await this.meetingSession.audioVideo.chooseVideoInputDevice(null);
492
- await this.meetingSession.audioVideo.chooseAudioInputDevice(((_a = this.audioInput) === null || _a === void 0 ? void 0 : _a.deviceId) || 'default');
493
- this.meetingSession.audioVideo.start();
494
- }
495
- catch (e) {
496
- this.emit('error', e);
497
- this.logger.error(e.message);
498
- success(false);
499
- }
463
+ join(options) {
464
+ return __awaiter(this, void 0, void 0, function* () {
465
+ return new Promise((success, fail) => __awaiter(this, void 0, void 0, function* () {
466
+ var _a;
467
+ this.emit('joinWillStart');
468
+ try {
469
+ // 取签名
470
+ const { sdkAppId, userId, roomId, userSig } = yield this._getVoiceSign(Object.assign(Object.assign({}, options), { roomId: options.roomId || 0 }));
471
+ this.userId = userId;
472
+ const { attendence, vendor_wrapper, } = JSON.parse(decodeURIComponent(userSig));
473
+ // 初始化配置
474
+ const configuration = new amazonChimeSdkJs.MeetingSessionConfiguration({
475
+ Meeting: vendor_wrapper,
476
+ }, {
477
+ Attendee: {
478
+ ExternalUserId: attendence.external_user_id,
479
+ AttendeeId: attendence.attendee_id,
480
+ JoinToken: attendence.join_token,
481
+ },
482
+ });
483
+ // 初始化会议会话
484
+ this.meetingSession = new amazonChimeSdkJs.DefaultMeetingSession(configuration, this.logger, this.deviceController);
485
+ // 注册事件
486
+ this._registerRtcEvent();
487
+ // 绑定监听器
488
+ this.meetingSession.audioVideo.addDeviceChangeObserver(this.deviceChangeObserver);
489
+ this.meetingSession.audioVideo.addObserver(this.audioVideoObserver);
490
+ // 绑定播放器
491
+ this.meetingSession.audioVideo.bindAudioElement(this.$audio);
492
+ const observer = {
493
+ audioVideoDidStart: () => {
494
+ var _a;
495
+ (_a = this.meetingSession) === null || _a === void 0 ? void 0 : _a.audioVideo.realtimeMuteLocalAudio();
496
+ this.joined = true;
497
+ this.emit('joined');
498
+ success(true);
499
+ },
500
+ audioVideoDidStop: () => {
501
+ this.joined = false;
502
+ success(false);
503
+ },
504
+ };
505
+ this.meetingSession.audioVideo.addObserver(observer);
506
+ // 选择语音输入设备
507
+ const audioInputDevices = yield this.deviceController.listAudioInputDevices(true);
508
+ const defaultAudioInput = audioInputDevices.find((device) => device.deviceId === 'default');
509
+ const otherAudioInput = audioInputDevices.find((device) => device.deviceId !== '');
510
+ this.audioInput = defaultAudioInput || otherAudioInput;
511
+ yield this.meetingSession.audioVideo.chooseVideoInputDevice(null);
512
+ yield this.meetingSession.audioVideo.chooseAudioInputDevice(((_a = this.audioInput) === null || _a === void 0 ? void 0 : _a.deviceId) || 'default');
513
+ this.meetingSession.audioVideo.start();
514
+ }
515
+ catch (e) {
516
+ this.emit('error', e);
517
+ this.logger.error(e.message);
518
+ success(false);
519
+ }
520
+ }));
500
521
  });
501
522
  }
502
523
  quit() {
@@ -526,36 +547,40 @@ class BrowserRTC4Chime extends CoreRTC {
526
547
  (_b = this.meetingSession) === null || _b === void 0 ? void 0 : _b.audioVideo.stop();
527
548
  });
528
549
  }
529
- async detectMicro() {
530
- return new Promise((resolve) => {
531
- const rule = { audio: true, video: false };
532
- try {
533
- navigator.mediaDevices
534
- .getUserMedia(rule)
535
- .then(() => resolve(true))
536
- .catch(() => resolve(false));
537
- }
538
- catch (e) {
539
- this.logger.error(e.message);
540
- resolve(false);
541
- }
550
+ detectMicro() {
551
+ return __awaiter(this, void 0, void 0, function* () {
552
+ return new Promise((resolve) => {
553
+ const rule = { audio: true, video: false };
554
+ try {
555
+ navigator.mediaDevices
556
+ .getUserMedia(rule)
557
+ .then(() => resolve(true))
558
+ .catch(() => resolve(false));
559
+ }
560
+ catch (e) {
561
+ this.logger.error(e.message);
562
+ resolve(false);
563
+ }
564
+ });
542
565
  });
543
566
  }
544
- async toggleMicro(flag) {
567
+ toggleMicro(flag) {
545
568
  var _a, _b, _c;
546
- if (flag) {
547
- (_a = this.meetingSession) === null || _a === void 0 ? void 0 : _a.audioVideo.realtimeUnmuteLocalAudio();
548
- }
549
- else {
550
- (_b = this.meetingSession) === null || _b === void 0 ? void 0 : _b.audioVideo.realtimeMuteLocalAudio();
551
- }
552
- const muted = (_c = this.meetingSession) === null || _c === void 0 ? void 0 : _c.audioVideo.realtimeIsLocalAudioMuted();
553
- if (muted !== undefined) {
554
- return flag !== muted;
555
- }
556
- else {
557
- return false;
558
- }
569
+ return __awaiter(this, void 0, void 0, function* () {
570
+ if (flag) {
571
+ (_a = this.meetingSession) === null || _a === void 0 ? void 0 : _a.audioVideo.realtimeUnmuteLocalAudio();
572
+ }
573
+ else {
574
+ (_b = this.meetingSession) === null || _b === void 0 ? void 0 : _b.audioVideo.realtimeMuteLocalAudio();
575
+ }
576
+ const muted = (_c = this.meetingSession) === null || _c === void 0 ? void 0 : _c.audioVideo.realtimeIsLocalAudioMuted();
577
+ if (muted !== undefined) {
578
+ return flag !== muted;
579
+ }
580
+ else {
581
+ return false;
582
+ }
583
+ });
559
584
  }
560
585
  shock() {
561
586
  throw new Error('Method not implemented.');
@@ -604,51 +629,59 @@ class VRWebViewRTC extends CoreRTC {
604
629
  get jsBridge() {
605
630
  return this.options.jsBridge;
606
631
  }
607
- async join(options) {
608
- this.emit('joinWillStart');
609
- const { sdkAppId, userId, userSig } = await this.options.getVoiceSign(options);
610
- this.type = options.type;
611
- const [res, error] = await this.jsBridge.callAndBackfeed(`live/join?sdkAppID=${sdkAppId}&userID=${userId}&roomID=${Number(options.voiceId)}&userSig=${userSig}`);
612
- if (!res) {
613
- this.emit('error', error ? error : new Error('加入房间失败:未知异常。'));
614
- this.joined = false;
615
- }
616
- else {
617
- if (res.code === exports.RTCJoinedInfoCodeEnum.Success) {
618
- this.emit('joined');
619
- this.joined = true;
632
+ join(options) {
633
+ return __awaiter(this, void 0, void 0, function* () {
634
+ this.emit('joinWillStart');
635
+ const { sdkAppId, userId, userSig } = yield this.options.getVoiceSign(options);
636
+ this.type = options.type;
637
+ const [res, error] = yield this.jsBridge.callAndBackfeed(`live/join?sdkAppID=${sdkAppId}&userID=${userId}&roomID=${Number(options.voiceId)}&userSig=${userSig}`);
638
+ if (!res) {
639
+ this.emit('error', error ? error : new Error('加入房间失败:未知异常。'));
640
+ this.joined = false;
620
641
  }
621
642
  else {
622
- this.emit('error', res);
623
- this.joined = false;
643
+ if (res.code === exports.RTCJoinedInfoCodeEnum.Success) {
644
+ this.emit('joined');
645
+ this.joined = true;
646
+ }
647
+ else {
648
+ this.emit('error', res);
649
+ this.joined = false;
650
+ }
624
651
  }
625
- }
626
- return this.joined;
652
+ return this.joined;
653
+ });
627
654
  }
628
- async quit() {
629
- const [res, error] = await this.jsBridge.callAndBackfeed('live/quit');
630
- if (res === null) {
631
- this.emit('error', error ? error : new Error('退出房间失败:未知异常。'));
632
- }
633
- this.joined = false;
634
- return !!res;
655
+ quit() {
656
+ return __awaiter(this, void 0, void 0, function* () {
657
+ const [res, error] = yield this.jsBridge.callAndBackfeed('live/quit');
658
+ if (res === null) {
659
+ this.emit('error', error ? error : new Error('退出房间失败:未知异常。'));
660
+ }
661
+ this.joined = false;
662
+ return !!res;
663
+ });
635
664
  }
636
- async detectMicro() {
637
- const [res, error] = await this.jsBridge.detectMicro();
638
- if (res === null) {
639
- this.emit('error', error ? error : new Error('麦克风监测异常!'));
640
- return false;
641
- }
642
- return res;
665
+ detectMicro() {
666
+ return __awaiter(this, void 0, void 0, function* () {
667
+ const [res, error] = yield this.jsBridge.detectMicro();
668
+ if (res === null) {
669
+ this.emit('error', error ? error : new Error('麦克风监测异常!'));
670
+ return false;
671
+ }
672
+ return res;
673
+ });
643
674
  }
644
- async toggleMicro(flag) {
645
- const [res, error] = await this.jsBridge.callAndBackfeed(`live/toggleMicro?flag=${!!flag ? 1 : 0}`);
646
- if (res === null) {
647
- this.emit('error', error ? error : new Error('麦克风监测异常!'));
648
- return false;
649
- }
650
- this.micro = res;
651
- return res;
675
+ toggleMicro(flag) {
676
+ return __awaiter(this, void 0, void 0, function* () {
677
+ const [res, error] = yield this.jsBridge.callAndBackfeed(`live/toggleMicro?flag=${!!flag ? 1 : 0}`);
678
+ if (res === null) {
679
+ this.emit('error', error ? error : new Error('麦克风监测异常!'));
680
+ return false;
681
+ }
682
+ this.micro = res;
683
+ return res;
684
+ });
652
685
  }
653
686
  shock() {
654
687
  this.jsBridge.shock(1);
@@ -891,6 +924,51 @@ function parseWSClsErr(code) {
891
924
  return exports.WebSocketCloseError.Err_unknown;
892
925
  }
893
926
 
927
+ function getDefaultExportFromCjs (x) {
928
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
929
+ }
930
+
931
+ function createCommonjsModule(fn) {
932
+ var module = { exports: {} };
933
+ return fn(module, module.exports), module.exports;
934
+ }
935
+
936
+ var LogLevel_1 = createCommonjsModule(function (module, exports) {
937
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
938
+ // SPDX-License-Identifier: Apache-2.0
939
+ Object.defineProperty(exports, "__esModule", { value: true });
940
+ exports.LogLevel = void 0;
941
+ var LogLevel;
942
+ (function (LogLevel) {
943
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
944
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
945
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
946
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
947
+ LogLevel[LogLevel["OFF"] = 4] = "OFF";
948
+ })(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
949
+ exports.default = LogLevel;
950
+
951
+ });
952
+
953
+ var LogLevel = /*@__PURE__*/getDefaultExportFromCjs(LogLevel_1);
954
+
955
+ var LiveState;
956
+ (function (LiveState) {
957
+ LiveState[LiveState["NOTINITIALIZED"] = -1] = "NOTINITIALIZED";
958
+ /**
959
+ * 正在链接中
960
+ */
961
+ LiveState[LiveState["CONNECTING"] = 0] = "CONNECTING";
962
+ /**
963
+ * 已经链接并且可以通讯
964
+ */
965
+ LiveState[LiveState["OPEN"] = 1] = "OPEN";
966
+ /**
967
+ * 连接已关闭或者链接失败
968
+ */
969
+ LiveState[LiveState["CLOSED"] = 3] = "CLOSED";
970
+ })(LiveState || (LiveState = {}));
971
+
894
972
  function appendUri(uri, query) {
895
973
  const hasQuery = uri.indexOf('?') !== -1;
896
974
  const newQuery = Object.keys(query).reduce((accu, curr, idx) => `${accu}${(idx === 0 && !hasQuery) ? '?' : '&'}${curr}=${query[curr]}`, '');
@@ -1035,692 +1113,1115 @@ function equal(value, other, opt) {
1035
1113
  return isDeepEqual(value, other);
1036
1114
  }
1037
1115
 
1038
- class LiveController {
1116
+ /**
1117
+ * 输出格式化日志
1118
+ */
1119
+ // 获取当前时间
1120
+ const getTime = () => {
1121
+ const date = new Date();
1122
+ const year = date.getFullYear();
1123
+ const month = (date.getMonth() + 1).toString().padStart(2, '0'); //月份是从0开始的
1124
+ const day = date.getDate().toString().padStart(2, '0');
1125
+ const hour = date.getHours().toString().padStart(2, '0');
1126
+ const min = date.getMinutes().toString().padStart(2, '0');
1127
+ const sec = date.getSeconds().toString().padStart(2, '0');
1128
+ const ms = date.getMilliseconds();
1129
+ return `[${year}-${month}-${day} ${hour}:${min}:${sec}.${ms}]`;
1130
+ };
1131
+ var LOG_LEVEL;
1132
+ (function (LOG_LEVEL) {
1133
+ LOG_LEVEL["info"] = "INFO";
1134
+ LOG_LEVEL["log"] = "LOG";
1135
+ LOG_LEVEL["error"] = "ERROR";
1136
+ LOG_LEVEL["warn"] = "WARN";
1137
+ })(LOG_LEVEL || (LOG_LEVEL = {}));
1138
+ // 输出日志
1139
+ const echo = (logLevel, args = []) => {
1140
+ args.unshift(`Realsee Live ${getTime()} <${logLevel}> `);
1141
+ switch (logLevel) {
1142
+ case LOG_LEVEL.info:
1143
+ return console.info(...args);
1144
+ case LOG_LEVEL.error:
1145
+ return console.error(...args);
1146
+ case LOG_LEVEL.warn:
1147
+ return console.warn(...args);
1148
+ default:
1149
+ return console.log(...args);
1150
+ }
1151
+ };
1152
+ const log = (...args) => echo(LOG_LEVEL.log, args);
1153
+ const info = (...args) => echo(LOG_LEVEL.info, args);
1154
+ const error = (...args) => echo(LOG_LEVEL.error, args);
1155
+ const warn = (...args) => echo(LOG_LEVEL.warn, args);
1156
+ const logger = {
1157
+ log,
1158
+ info,
1159
+ error,
1160
+ warn,
1161
+ };
1162
+ var logger$1 = logger;
1163
+
1164
+ /**
1165
+ * 具有鲁棒性的WebSocket封装
1166
+ * 1、自动重连
1167
+ * 2、可根据网络情况进行重连
1168
+ */
1169
+ class RobustWebSocket extends Subscribe {
1039
1170
  constructor(options) {
1040
- this.readyState = exports.WebSocketState.NOTINITIALIZED;
1041
- this.canSync = true;
1042
- this.connecting = false;
1043
- this.keyframes = {};
1171
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
1172
+ super();
1173
+ this._options = {
1174
+ timeout: 10000,
1175
+ shouldReconnect: (event, ws) => {
1176
+ if (event.code === 1008 || event.code === 1011)
1177
+ return;
1178
+ return [0, 3000, 10000][ws.attempts];
1179
+ },
1180
+ should1000Reconnect: false,
1181
+ ignoreConnectivityEvents: false,
1182
+ automaticOpen: false,
1183
+ };
1184
+ this._attempts = 0;
1185
+ this._reconnects = -1;
1186
+ this._reconnectWhenOnlineAgain = false;
1187
+ this._explicitlyClosed = false;
1188
+ this._connectivityEventsAttached = false;
1044
1189
  /**
1045
- * 检测 WebSocket.readyState 状态
1190
+ * 清理连接中的请求
1046
1191
  */
1047
- this.checkReadyState = (live) => {
1048
- do {
1049
- if (!this.webSocket) {
1050
- if (this.readyState !== exports.WebSocketState.NOTINITIALIZED) {
1051
- this.readyState = exports.WebSocketState.NOTINITIALIZED;
1052
- live.emit('ws.readyStateUpdate', this.readyState);
1053
- }
1054
- break;
1055
- }
1056
- const readyState = this.webSocket.readyState;
1057
- if (readyState !== this.readyState) {
1058
- this.readyState = readyState;
1059
- live.emit('ws.readyStateUpdate', this.readyState);
1060
- }
1061
- } while (false);
1062
- return this.readyState;
1192
+ this._clearPendingReconnectIfNeeded = () => {
1193
+ if (this._pendingReconnect) {
1194
+ clearTimeout(this._pendingReconnect);
1195
+ this._pendingReconnect = undefined;
1196
+ }
1063
1197
  };
1064
- this.dispose = () => {
1065
- this.disposeWebSocket();
1066
- this.connecting = false;
1067
- if (this.healthCheckId) {
1068
- clearInterval(this.healthCheckId);
1069
- this.healthCheckId = undefined;
1198
+ /**
1199
+ * 当网页连接上网络进行重连
1200
+ * @param event
1201
+ */
1202
+ this._online = (event) => {
1203
+ if (this._reconnectWhenOnlineAgain) {
1204
+ this._clearPendingReconnectIfNeeded();
1205
+ this._reconnect(event);
1070
1206
  }
1071
- return true;
1072
1207
  };
1073
1208
  /**
1074
- * 销毁WebSocket相关依赖。
1209
+ * 当网页断开网络进行关闭
1075
1210
  */
1076
- this.disposeWebSocket = () => {
1077
- if (!this.webSocket)
1078
- return;
1079
- if (this.onEvtOpnListener) {
1080
- this.webSocket.removeEventListener('open', this.onEvtOpnListener);
1081
- this.onEvtOpnListener = undefined;
1211
+ this._offline = () => {
1212
+ var _a;
1213
+ this._reconnectWhenOnlineAgain = true;
1214
+ (_a = this._realWebSocket) === null || _a === void 0 ? void 0 : _a.close(1000);
1215
+ };
1216
+ /**
1217
+ * 解除网络监听事件
1218
+ */
1219
+ this._detachConnectivityEvents = () => {
1220
+ if (this._connectivityEventsAttached) {
1221
+ globalThis === null || globalThis === void 0 ? void 0 : globalThis.removeEventListener('online', this._online);
1222
+ globalThis === null || globalThis === void 0 ? void 0 : globalThis.removeEventListener('offline', this._offline);
1223
+ this._connectivityEventsAttached = false;
1224
+ }
1225
+ };
1226
+ /**
1227
+ * 注册网络监听事件
1228
+ */
1229
+ this._attachConnectivityEvents = () => {
1230
+ if (!this._connectivityEventsAttached) {
1231
+ globalThis === null || globalThis === void 0 ? void 0 : globalThis.addEventListener('online', this._online);
1232
+ globalThis === null || globalThis === void 0 ? void 0 : globalThis.addEventListener('offline', this._offline);
1233
+ this._connectivityEventsAttached = true;
1082
1234
  }
1083
- if (this.onEvtMsgListener) {
1084
- this.webSocket.removeEventListener('message', this.onEvtMsgListener);
1085
- this.onEvtMsgListener = undefined;
1235
+ };
1236
+ /**
1237
+ * 发送消息
1238
+ * @param data
1239
+ * @returns
1240
+ */
1241
+ this.send = (data) => { var _a; return (_a = this._realWebSocket) === null || _a === void 0 ? void 0 : _a.send(data); };
1242
+ /**
1243
+ * 关闭连接
1244
+ * @param code 代码
1245
+ * @param reason 原因
1246
+ * @returns
1247
+ */
1248
+ this.close = (code, reason) => {
1249
+ var _a;
1250
+ if (typeof code !== 'number') {
1251
+ reason = code;
1252
+ code = 1000;
1086
1253
  }
1087
- if (this.onEvtErrListener) {
1088
- this.webSocket.removeEventListener('error', this.onEvtErrListener);
1089
- this.onEvtErrListener = undefined;
1254
+ this._clearPendingReconnectIfNeeded();
1255
+ this._reconnectWhenOnlineAgain = false;
1256
+ this._explicitlyClosed = true;
1257
+ this._detachConnectivityEvents();
1258
+ return (_a = this._realWebSocket) === null || _a === void 0 ? void 0 : _a.close(code, reason);
1259
+ };
1260
+ /**
1261
+ * 进行ws连接
1262
+ */
1263
+ this.open = (url) => {
1264
+ var _a, _b;
1265
+ if (url) {
1266
+ this._url = url;
1090
1267
  }
1091
- if (this.onEvtCLEListener) {
1092
- this.webSocket.removeEventListener('close', this.onEvtCLEListener);
1093
- this.onEvtCLEListener = undefined;
1268
+ if (((_a = this._realWebSocket) === null || _a === void 0 ? void 0 : _a.readyState) !== WebSocket.OPEN &&
1269
+ ((_b = this._realWebSocket) === null || _b === void 0 ? void 0 : _b.readyState) !== WebSocket.CONNECTING) {
1270
+ this._clearPendingReconnectIfNeeded();
1271
+ this._reconnectWhenOnlineAgain = false;
1272
+ this._explicitlyClosed = false;
1273
+ this._createWebSocket();
1094
1274
  }
1095
- this.webSocket.close();
1096
- this.webSocket = undefined;
1097
- return true;
1098
1275
  };
1099
- this.options = Object.assign({ autoConnect: true, healthCheck: 3000 }, options);
1276
+ /**
1277
+ * 创建ws连接
1278
+ */
1279
+ this._createWebSocket = () => {
1280
+ var _a, _b, _c;
1281
+ const newUrl = typeof this._url === 'string' ? this._url : (_a = this._url) === null || _a === void 0 ? void 0 : _a.call(this, this);
1282
+ if (!newUrl)
1283
+ return;
1284
+ this._pendingReconnect = undefined;
1285
+ this._realWebSocket = new WebSocket(newUrl, this._protocols || undefined);
1286
+ this._attempts = this._attempts + 1;
1287
+ this.emit('connecting', new CustomEvent('connecting', {
1288
+ detail: { attempts: this._attempts, reconnects: this._reconnects },
1289
+ }));
1290
+ const timeoutCallback = () => {
1291
+ this._connectTimeout = undefined;
1292
+ this._detachConnectivityEvents();
1293
+ this.emit('timeout', new CustomEvent('connecting', {
1294
+ detail: {
1295
+ attempts: this._attempts,
1296
+ reconnects: this._reconnects,
1297
+ },
1298
+ }));
1299
+ };
1300
+ this._connectTimeout = setTimeout(timeoutCallback, (_b = this._options) === null || _b === void 0 ? void 0 : _b.timeout);
1301
+ this._dispatchWebSocketEvent();
1302
+ if (!((_c = this._options) === null || _c === void 0 ? void 0 : _c.ignoreConnectivityEvents)) {
1303
+ this._attachConnectivityEvents();
1304
+ }
1305
+ };
1306
+ /**
1307
+ * 分发ws事件
1308
+ */
1309
+ this._dispatchWebSocketEvent = () => {
1310
+ var _a, _b, _c, _d;
1311
+ (_a = this._realWebSocket) === null || _a === void 0 ? void 0 : _a.addEventListener('open', this._webSocketOpenHandler);
1312
+ (_b = this._realWebSocket) === null || _b === void 0 ? void 0 : _b.addEventListener('close', this._webSocketCloseHandler);
1313
+ (_c = this._realWebSocket) === null || _c === void 0 ? void 0 : _c.addEventListener('error', this._webSocketErrorHandler);
1314
+ (_d = this._realWebSocket) === null || _d === void 0 ? void 0 : _d.addEventListener('message', this._webSocketMessageHandler);
1315
+ };
1316
+ /**
1317
+ * ws连接事件
1318
+ * @returns
1319
+ */
1320
+ this._webSocketOpenHandler = (event) => {
1321
+ if (this._connectTimeout) {
1322
+ clearTimeout(this._connectTimeout);
1323
+ this._connectTimeout = undefined;
1324
+ }
1325
+ const reconnects = ++this._reconnects;
1326
+ const attempts = this._attempts;
1327
+ this._attempts = 0;
1328
+ this._reconnectWhenOnlineAgain = false;
1329
+ return this.emit('open', Object.assign(event, { detail: { reconnects, attempts } }));
1330
+ };
1331
+ /**
1332
+ * ws 关闭事件
1333
+ * @param event
1334
+ * @returns
1335
+ */
1336
+ this._webSocketCloseHandler = (event) => {
1337
+ this._reconnect(event);
1338
+ return this.emit('close', event);
1339
+ };
1340
+ /**
1341
+ * ws 异常
1342
+ * @param event
1343
+ * @returns
1344
+ */
1345
+ this._webSocketErrorHandler = (event) => {
1346
+ return this.emit('error', new CustomEvent('error', { detail: { error: event } }));
1347
+ };
1348
+ /**
1349
+ * ws消息
1350
+ * @param event
1351
+ * @returns
1352
+ */
1353
+ this._webSocketMessageHandler = (event) => {
1354
+ return this.emit('message', event);
1355
+ };
1356
+ if (options) {
1357
+ this.setOptions(options);
1358
+ }
1359
+ }
1360
+ get attempts() {
1361
+ return this._attempts;
1362
+ }
1363
+ setOptions(options) {
1364
+ if (!options)
1365
+ return;
1366
+ this._url = options.url;
1367
+ this._protocols = options.protocols;
1368
+ const opts = Object.assign(this._options, options.robustOptions || {});
1369
+ if (typeof (opts === null || opts === void 0 ? void 0 : opts.timeout) !== 'number') {
1370
+ throw new Error('timeout must be the number of milliseconds to timeout a connection attempt');
1371
+ }
1372
+ if (typeof (opts === null || opts === void 0 ? void 0 : opts.shouldReconnect) !== 'function') {
1373
+ throw new Error('shouldReconnect must be a function that returns the number of milliseconds to wait for a reconnect attempt, or null or undefined to not reconnect.');
1374
+ }
1375
+ this._options = opts;
1376
+ if (this._options.automaticOpen) {
1377
+ this._createWebSocket();
1378
+ }
1100
1379
  }
1101
1380
  /**
1102
- * 解析数据
1103
- * @param liveMsg
1104
- * @param live
1381
+ * 进行重连
1382
+ * @param event
1383
+ * @returns
1105
1384
  */
1106
- handleMessage(liveMsg, live) {
1107
- var _a, _b, _c;
1108
- const { command, data, frontRequestId, code, message } = liveMsg;
1109
- if (code === 'SUCCESS') {
1110
- switch (command) {
1111
- /**
1112
- * 自己的状态变化
1113
- */
1114
- case exports.Command.SelfUserInfo: {
1115
- const selfInfo = data;
1116
- if (equal(this.selfUserInfo, selfInfo, { deep: true }))
1117
- return;
1118
- this.selfUserInfo = selfInfo;
1119
- live.emit('selfInfoUpdate', this.selfUserInfo, frontRequestId);
1120
- break;
1121
- }
1122
- /**
1123
- * 房间信息变化
1124
- */
1125
- case exports.Command.RoomInfo: {
1126
- const roomInfo = data;
1127
- this.roomInfo = Object.assign({}, roomInfo);
1128
- live.emit('readyKeyframeSync', (roomInfo.last_frame || {}));
1129
- break;
1130
- }
1131
- /**
1132
- * 语音信息变化
1133
- */
1134
- case exports.Command.RTCInfo: {
1135
- const { voice_id: voiceId, type } = data;
1136
- /* 如果已经进入语音房间,则不重复进入 --> "RTCInfo" 指令可能会下发多次 */
1137
- if (live.$RTC.joined) {
1138
- break;
1139
- }
1140
- live.$RTC.join({
1141
- voiceId,
1142
- userId: ((_a = this.selfUserInfo) === null || _a === void 0 ? void 0 : _a.id) || '',
1143
- roomId: (_b = this.roomInfo) === null || _b === void 0 ? void 0 : _b.info.room_code,
1144
- type,
1145
- });
1146
- // 加入房间后 麦克风默认就开启了:需要发个指令。
1147
- live.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserMicroStatus, {
1148
- status: exports.MicroStatus.OPEN,
1149
- });
1150
- break;
1151
- }
1152
- /**
1153
- * 房间用户列表变化
1154
- */
1155
- case exports.Command.UserList: {
1156
- const userList = data;
1157
- this.userList = userList;
1158
- live.emit('userListUpdate', this.userList, frontRequestId);
1159
- break;
1160
- }
1161
- /**
1162
- * 自定义事件广播
1163
- */
1164
- case exports.Command.CustomEvent: {
1165
- const evtMsg = data;
1166
- live.emit('broadcast', evtMsg, frontRequestId);
1167
- break;
1168
- }
1169
- /**
1170
- * 帧数据同步
1171
- */
1172
- case exports.Command.KeyframeSync: {
1173
- const remoteKeyframes = data;
1174
- // 此处做一层 diff,仅跟本地数据不一致的情况下才广播数据。
1175
- const keyframes = Object.keys(remoteKeyframes).reduce((accu, curr) => {
1176
- if (equal(remoteKeyframes[curr], this.keyframes[curr], { deep: true })) {
1177
- return accu;
1178
- }
1179
- const params = [
1180
- remoteKeyframes[curr],
1181
- this.keyframes[curr],
1182
- frontRequestId,
1183
- ];
1184
- const evtName = curr;
1185
- live.keyframes.emit(evtName, ...params);
1186
- this.keyframes[curr] = remoteKeyframes[curr];
1187
- accu[curr] = remoteKeyframes[curr];
1188
- return accu;
1189
- }, {});
1190
- live.emit('keyframes', keyframes, frontRequestId);
1191
- break;
1192
- }
1193
- /**
1194
- * 内置消息
1195
- */
1196
- case exports.Command.BuiltinMsg: {
1197
- const builtinMsg = data;
1198
- live.emit('builtinEvent', builtinMsg);
1199
- if (builtinMsg.event_type === exports.BuiltinEventType.UserChange) {
1200
- live.emit('userChange', builtinMsg);
1201
- }
1202
- if (builtinMsg.event_type === exports.BuiltinEventType.RoomChange) {
1203
- live.emit('roomChange', builtinMsg);
1204
- }
1205
- /**
1206
- * 下发指令自己操作麦克风
1207
- */
1208
- if (builtinMsg.event_type === exports.BuiltinEventType.UserChange &&
1209
- builtinMsg.action === exports.BuiltinActionType.UserMicroStatus) {
1210
- live.toggleMicro(builtinMsg.data.status === exports.MicroStatus.OPEN);
1211
- }
1212
- /**
1213
- * 如果下发指令退出房间,则 关闭麦克风 及 销毁 WebSocket
1214
- */
1215
- if (builtinMsg.event_type === exports.BuiltinEventType.RoomChange &&
1216
- builtinMsg.action === exports.BuiltinActionType.RoomClose) {
1217
- (_c = this.options.rtc) === null || _c === void 0 ? void 0 : _c.quit();
1218
- this.disposeWebSocket();
1219
- }
1220
- break;
1221
- }
1222
- /**
1223
- * 被踢出房间
1224
- */
1225
- case exports.Command.UserKickOut: {
1226
- live.emit('kickOut');
1227
- break;
1228
- }
1229
- /**
1230
- * 其它未知广播
1231
- */
1232
- default: {
1233
- console.warn('unknown command: ', command);
1234
- }
1235
- }
1385
+ _reconnect(event) {
1386
+ var _a, _b, _c, _d;
1387
+ if ((!((_a = this._options) === null || _a === void 0 ? void 0 : _a.should1000Reconnect) && event.code === 1000) ||
1388
+ this._explicitlyClosed) {
1389
+ this._attempts = 0;
1390
+ return;
1236
1391
  }
1237
- else {
1238
- live.emit('error', liveMsg);
1392
+ if (((_b = globalThis === null || globalThis === void 0 ? void 0 : globalThis.navigator) === null || _b === void 0 ? void 0 : _b.onLine) === false) {
1393
+ this._reconnectWhenOnlineAgain = true;
1394
+ return;
1239
1395
  }
1396
+ const delay = (_d = (_c = this._options) === null || _c === void 0 ? void 0 : _c.shouldReconnect) === null || _d === void 0 ? void 0 : _d.call(_c, event, this);
1397
+ if (typeof delay === 'number') {
1398
+ this._pendingReconnect = setTimeout(this._createWebSocket, delay);
1399
+ }
1400
+ }
1401
+ }
1402
+
1403
+ class LiveController extends Subscribe {
1404
+ constructor() {
1405
+ super();
1406
+ /**
1407
+ * ws代理器
1408
+ */
1409
+ this._ws = new RobustWebSocket();
1410
+ /**
1411
+ * 带看连接状态
1412
+ */
1413
+ this._state = LiveState.NOTINITIALIZED;
1414
+ /**
1415
+ * 添加事件监听
1416
+ */
1417
+ this._addWebSocketEventListeners = () => {
1418
+ this._ws.on('close', this._handleCloseEvent);
1419
+ this._ws.on('connecting', this._handleConnectingEvent);
1420
+ this._ws.on('error', this._handleErrorEvent);
1421
+ this._ws.on('message', this._handleMessageEvent);
1422
+ this._ws.on('open', this._handleOpenEvent);
1423
+ this._ws.on('timeout', this._handleTimeoutEvent);
1424
+ };
1425
+ /**
1426
+ * 移除事件监听
1427
+ */
1428
+ this._removeWebSocketEventListeners = () => {
1429
+ this._ws.off('close', this._handleCloseEvent);
1430
+ this._ws.off('connecting', this._handleConnectingEvent);
1431
+ this._ws.off('error', this._handleErrorEvent);
1432
+ this._ws.off('message', this._handleMessageEvent);
1433
+ this._ws.off('open', this._handleOpenEvent);
1434
+ this._ws.off('timeout', this._handleTimeoutEvent);
1435
+ };
1436
+ /**
1437
+ * 处理房间关闭事件
1438
+ * @param event
1439
+ */
1440
+ this._handleCloseEvent = (event) => {
1441
+ logger$1.info(`live room closed bacause of ${event.code}-${event.reason || parseWSClsErr(event.code)}`);
1442
+ this.state = LiveState.CLOSED;
1443
+ };
1444
+ /**
1445
+ * 连接中
1446
+ * @param event
1447
+ */
1448
+ this._handleConnectingEvent = (event) => {
1449
+ logger$1.info(`live room is connecting`, event.detail);
1450
+ this.state = LiveState.CONNECTING;
1451
+ };
1452
+ /**
1453
+ * 连接发送异常
1454
+ * @param event
1455
+ */
1456
+ this._handleErrorEvent = (event) => {
1457
+ logger$1.error(`live room error`, event);
1458
+ this.state = LiveState.CLOSED;
1459
+ };
1460
+ /**
1461
+ * 接收到消息
1462
+ * @param event
1463
+ */
1464
+ this._handleMessageEvent = (event) => {
1465
+ // logger.info('live room received message ', event.data);
1466
+ let message = (() => {
1467
+ try {
1468
+ return JSON.parse(event.data);
1469
+ }
1470
+ catch (e) {
1471
+ return event.data;
1472
+ }
1473
+ })();
1474
+ this.emit('message', message);
1475
+ };
1476
+ /**
1477
+ * 连接建立成功
1478
+ * @param event
1479
+ */
1480
+ this._handleOpenEvent = (event) => {
1481
+ logger$1.info('live room open', event.detail);
1482
+ this.state = LiveState.OPEN;
1483
+ };
1484
+ /**
1485
+ * 处理超时
1486
+ * @param event
1487
+ */
1488
+ this._handleTimeoutEvent = (event) => {
1489
+ logger$1.error('live room connect timeout!', event.detail);
1490
+ this.state = LiveState.CLOSED;
1491
+ };
1492
+ /**
1493
+ * 释放资源,释放之后需要重新实例化
1494
+ * @returns
1495
+ */
1496
+ this.dispose = () => __awaiter(this, void 0, void 0, function* () {
1497
+ this._removeWebSocketEventListeners();
1498
+ return yield this.close('live room close by controller disposed!');
1499
+ });
1500
+ /**
1501
+ * 开启房间链接
1502
+ * @param url 房间链接
1503
+ * @returns
1504
+ */
1505
+ this.open = (url) => this._ws.open(url);
1506
+ /**
1507
+ * 关闭房间
1508
+ * @param code
1509
+ * @param reason
1510
+ */
1511
+ this.close = (code, reason) => new Promise((resolve) => {
1512
+ this._ws.once('close', () => resolve(true));
1513
+ this._ws.close(code, reason);
1514
+ });
1515
+ this._addWebSocketEventListeners();
1516
+ }
1517
+ set state(state) {
1518
+ const prevState = JSON.parse(JSON.stringify(this._state));
1519
+ this._state = state;
1520
+ this.emit('stateChange', this.state, prevState);
1521
+ }
1522
+ get state() {
1523
+ return this._state;
1240
1524
  }
1241
1525
  /**
1242
1526
  * 发送数据
1243
1527
  * @param data
1244
1528
  */
1245
- sendMessage(data) {
1246
- if (!this.webSocket)
1247
- return console.warn('WebSocket has not yet been initialized!');
1248
- if (!data)
1249
- return console.warn('WebSocket messages is empty!');
1250
- this.webSocket.send(JSON.stringify(data));
1529
+ sendMessage(data = '') {
1530
+ if (data === undefined || data === null || data === '') {
1531
+ throw new Error('live message is empty!');
1532
+ }
1533
+ if (this.state === LiveState.OPEN) {
1534
+ return this._ws.send(JSON.stringify(data));
1535
+ }
1536
+ else {
1537
+ throw new Error('live has not yet been initialized!');
1538
+ }
1251
1539
  }
1252
1540
  }
1253
1541
 
1254
1542
  const unimplementedGetVoiceSign = (params) => Promise.reject('unimplemented method GetVoiceSign');
1255
- /**
1256
- * 创建 `live` 实例。
1257
- */
1258
- function createLive(options) {
1259
- const liveController = new LiveController(options);
1260
- const createLiveMsg = (command, data = {}, toUserIds) => {
1261
- toUserIds = toUserIds
1262
- ? Array.isArray(toUserIds)
1263
- ? toUserIds
1264
- : [toUserIds]
1265
- : [];
1266
- if (toUserIds)
1267
- data['to_user_ids'] = toUserIds;
1268
- return { command, front_request_id: uuid(), data };
1269
- };
1270
- class LiveTpl extends Subscribe {
1271
- constructor() {
1272
- var _a, _b;
1273
- super();
1274
- this.keyframes = new Subscribe();
1275
- const jsBridge = (() => {
1276
- if (options.jsBridge)
1277
- return options.jsBridge;
1278
- if (options.useBuiltInJsBridge)
1279
- return new JSBridge__default["default"]();
1280
- return undefined;
1281
- })();
1282
- liveController.options.jsBridge = jsBridge;
1283
- // 没有传rtc实例时
1284
- if (!options.rtc) {
1285
- // 取指定的内部rtc类型
1286
- if (options.rtcType) {
1287
- if (!options.getVoiceSign) {
1288
- throw new Error('GetVoiceSign method must be passed when using built-in RTC instances');
1289
- }
1290
- const getVoiceSign = (_a = options.getVoiceSign) !== null && _a !== void 0 ? _a : unimplementedGetVoiceSign;
1291
- switch (options.rtcType) {
1292
- case exports.RTCType.RealseeVRWebViewRTC: {
1293
- // 内置的 VRWebViewRTC
1294
- if (!jsBridge) {
1295
- throw new Error('JsBridge instance must be passed when using built-in VRWebViewRTC instances');
1296
- }
1297
- liveController.options.rtc = new VRWebViewRTC({
1298
- jsBridge,
1299
- getVoiceSign,
1300
- });
1301
- break;
1302
- }
1303
- case exports.RTCType.RealseeBrowserChimeRTC: {
1304
- // 内置的 RealseeBrowserChimeRTC
1305
- liveController.options.rtc = new BrowserRTC4Chime({
1306
- getVoiceSign,
1307
- logLevel: options.__debug__ ? amazonChimeSdkJs.LogLevel.DEBUG : amazonChimeSdkJs.LogLevel.ERROR,
1308
- });
1543
+ const createLiveMsg = (command, data = {}, toUserIds = []) => ({
1544
+ command,
1545
+ front_request_id: uuid(),
1546
+ data: Object.assign(Object.assign({}, data), { to_user_ids: Array.isArray(toUserIds) ? toUserIds : [toUserIds] }),
1547
+ });
1548
+ const _clearLiveInstanceIfNeed = () => {
1549
+ var _a, _b;
1550
+ if (window === null || window === void 0 ? void 0 : window.__Realsee_Live__) {
1551
+ (_b = (_a = window === null || window === void 0 ? void 0 : window.__Realsee_Live__) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
1552
+ window.__Realsee_Live__ = null;
1553
+ }
1554
+ };
1555
+ class Live extends Subscribe {
1556
+ constructor(opts) {
1557
+ var _a;
1558
+ super();
1559
+ /**
1560
+ * 带看的配置
1561
+ */
1562
+ this._options = {};
1563
+ /**
1564
+ * 帧数据监听
1565
+ */
1566
+ this.keyframes = new Subscribe();
1567
+ /**
1568
+ * 内置的一些数据
1569
+ */
1570
+ this._buildInData = {
1571
+ keyframes: {},
1572
+ };
1573
+ /**
1574
+ * 根据键值取帧数据
1575
+ * @param key 帧数据的键值
1576
+ * @returns
1577
+ */
1578
+ this.getFramesByKey = (key) => this.snapshot[key];
1579
+ /**
1580
+ * 发送帧数据(需要能够被序列化)
1581
+ * @param key 帧数据键值
1582
+ * @param frame 帧数据本体
1583
+ * @returns
1584
+ */
1585
+ this.sendKeyframe = (key, frame) => {
1586
+ if (this.state !== LiveState.OPEN)
1587
+ return false;
1588
+ this._buildInData.keyframes = Object.assign(Object.assign({}, this._buildInData.keyframes), { [key]: frame });
1589
+ const liveMsg = createLiveMsg(exports.Command.KeyframeSync, this.snapshot);
1590
+ try {
1591
+ this._controller.sendMessage(liveMsg);
1592
+ return true;
1593
+ }
1594
+ catch (e) {
1595
+ logger$1.error(e);
1596
+ return false;
1597
+ }
1598
+ };
1599
+ /**
1600
+ * 带看控制器
1601
+ */
1602
+ this._controller = new LiveController();
1603
+ /**
1604
+ * 添加带看控制的事件监听
1605
+ */
1606
+ this._addLiveControllerEventListeners = () => {
1607
+ this._controller.on('stateChange', this._handleStateChange);
1608
+ this._controller.on('message', this._handleMessage);
1609
+ };
1610
+ /**
1611
+ * 移除带看控制的事件监听
1612
+ */
1613
+ this._removeLiveControllerEventListeners = () => {
1614
+ this._controller.off('stateChange', this._handleStateChange);
1615
+ this._controller.off('message', this._handleMessage);
1616
+ };
1617
+ /**
1618
+ * 带看状态变化
1619
+ * @param state
1620
+ * @returns
1621
+ */
1622
+ this._handleStateChange = (state, prevState) => this.emit('stateChange', state, prevState);
1623
+ this._handleMessage = (liveMsg) => __awaiter(this, void 0, void 0, function* () {
1624
+ var _b, _c, _d, _e, _f, _g;
1625
+ if (typeof liveMsg === 'object') {
1626
+ const { command, data, frontRequestId, code, message } = liveMsg;
1627
+ if (code === 'SUCCESS') {
1628
+ switch (command) {
1629
+ /**
1630
+ * 自己的状态变化
1631
+ */
1632
+ case exports.Command.SelfUserInfo: {
1633
+ const selfInfo = data;
1634
+ if (!equal(this.selfInfo, selfInfo, { deep: true })) {
1635
+ this._buildInData.selfInfo = selfInfo;
1636
+ this.emit('selfInfoUpdate', this._buildInData.selfInfo, frontRequestId);
1637
+ }
1309
1638
  break;
1310
1639
  }
1311
- case exports.RTCType.RealseeBrowserRTC: {
1312
- // 内置的 RealseeBrowserRTC
1313
- liveController.options.rtc = new BrowserRTC({
1314
- getVoiceSign,
1315
- });
1640
+ /**
1641
+ * 房间信息变化
1642
+ */
1643
+ case exports.Command.RoomInfo: {
1644
+ const roomInfo = data;
1645
+ this._buildInData.roomInfo = Object.assign({}, roomInfo);
1646
+ this.emit('readyKeyframeSync', (roomInfo.last_frame || {}));
1316
1647
  break;
1317
1648
  }
1649
+ /**
1650
+ * 语音信息变化
1651
+ */
1652
+ case exports.Command.RTCInfo: {
1653
+ const { voice_id: voiceId, type } = data;
1654
+ if (!((_b = this.$RTC) === null || _b === void 0 ? void 0 : _b.joined)) {
1655
+ const result = yield ((_c = this.$RTC) === null || _c === void 0 ? void 0 : _c.join({
1656
+ voiceId,
1657
+ userId: ((_d = this.selfInfo) === null || _d === void 0 ? void 0 : _d.id) || '',
1658
+ roomId: (_e = this.roomInfo) === null || _e === void 0 ? void 0 : _e.info.room_code,
1659
+ type,
1660
+ }));
1661
+ if (result) {
1662
+ const status = (_f = this._options.initialMicroStatus) !== null && _f !== void 0 ? _f : exports.MicroStatus.OPEN;
1663
+ yield ((_g = this.$RTC) === null || _g === void 0 ? void 0 : _g.toggleMicro(status === exports.MicroStatus.OPEN));
1664
+ }
1665
+ else {
1666
+ logger$1.error('加入语音房间失败');
1667
+ }
1668
+ }
1669
+ else {
1670
+ logger$1.warn('已加入语音房间,无需重复加入!');
1671
+ }
1672
+ break;
1673
+ }
1674
+ /**
1675
+ * 房间用户列表变化
1676
+ */
1677
+ case exports.Command.UserList: {
1678
+ const userList = data;
1679
+ this._buildInData.userList = userList;
1680
+ this.emit('userListUpdate', this.userList, frontRequestId);
1681
+ break;
1682
+ }
1683
+ /**
1684
+ * 自定义事件广播
1685
+ */
1686
+ case exports.Command.CustomEvent: {
1687
+ const evtMsg = data;
1688
+ this.emit('broadcast', evtMsg, frontRequestId);
1689
+ break;
1690
+ }
1691
+ /**
1692
+ * 帧数据同步
1693
+ */
1694
+ case exports.Command.KeyframeSync: {
1695
+ const remoteKeyframes = data;
1696
+ // 此处做一层 diff,仅跟本地数据不一致的情况下才广播数据。
1697
+ const keyframes = Object.keys(remoteKeyframes).reduce((accu, curr) => {
1698
+ if (equal(remoteKeyframes[curr], this._buildInData.keyframes[curr], {
1699
+ deep: true,
1700
+ })) {
1701
+ return accu;
1702
+ }
1703
+ const params = [
1704
+ remoteKeyframes[curr],
1705
+ this._buildInData.keyframes[curr],
1706
+ frontRequestId,
1707
+ ];
1708
+ const evtName = curr;
1709
+ this.keyframes.emit(evtName, ...params);
1710
+ this._buildInData.keyframes[curr] = remoteKeyframes[curr];
1711
+ accu[curr] = remoteKeyframes[curr];
1712
+ return accu;
1713
+ }, {});
1714
+ this.emit('keyframes', keyframes, frontRequestId);
1715
+ break;
1716
+ }
1717
+ /**
1718
+ * 内置消息
1719
+ */
1720
+ case exports.Command.BuiltinMsg: {
1721
+ const builtinMsg = data;
1722
+ this.emit('builtinEvent', builtinMsg);
1723
+ if (builtinMsg.event_type === exports.BuiltinEventType.UserChange) {
1724
+ this.emit('userChange', builtinMsg);
1725
+ }
1726
+ if (builtinMsg.event_type === exports.BuiltinEventType.RoomChange) {
1727
+ this.emit('roomChange', builtinMsg);
1728
+ }
1729
+ /**
1730
+ * 下发指令自己操作麦克风
1731
+ */
1732
+ if (builtinMsg.event_type === exports.BuiltinEventType.UserChange &&
1733
+ builtinMsg.action === exports.BuiltinActionType.UserMicroStatus) {
1734
+ yield this.toggleMicro(builtinMsg.data.status === exports.MicroStatus.OPEN);
1735
+ }
1736
+ /**
1737
+ * 如果下发指令退出房间,则 关闭麦克风 及 销毁 WebSocket
1738
+ */
1739
+ if (builtinMsg.event_type === exports.BuiltinEventType.RoomChange &&
1740
+ builtinMsg.action === exports.BuiltinActionType.RoomClose) {
1741
+ yield this.exit();
1742
+ }
1743
+ break;
1744
+ }
1745
+ /**
1746
+ * 被踢出房间
1747
+ */
1748
+ case exports.Command.UserKickOut: {
1749
+ this.emit('kickOut');
1750
+ break;
1751
+ }
1752
+ /**
1753
+ * 其它未知广播
1754
+ */
1318
1755
  default: {
1319
- throw new Error('unknown built-in RTC type');
1756
+ console.warn('unknown command: ', command);
1320
1757
  }
1321
1758
  }
1322
1759
  }
1323
- // 都不满足时取内置
1324
- if (options.useBuiltInRTC) {
1325
- if (!options.getVoiceSign) {
1326
- throw new Error('GetVoiceSign method must be passed when using built-in RTC instances');
1327
- }
1328
- const getVoiceSign = (_b = options.getVoiceSign) !== null && _b !== void 0 ? _b : unimplementedGetVoiceSign;
1329
- if (!jsBridge) {
1330
- throw new Error('jsBridge instance must be passed when using built-in RTC instances');
1331
- }
1332
- // vrwebview 默认
1333
- if ((isRealseeVRWebview && (isAndroid || isIOS)) || isWxMiniProgram) {
1334
- liveController.options.rtc = new VRWebViewRTC({
1335
- jsBridge,
1336
- getVoiceSign,
1337
- });
1338
- }
1339
- else {
1340
- // 其它终端使用
1341
- liveController.options.rtc =
1342
- options.builtInRTCType === exports.BuiltInRTCType.RealseeXChimeRTC
1343
- ? new BrowserRTC4Chime({ getVoiceSign })
1344
- : new BrowserRTC({ getVoiceSign });
1345
- }
1760
+ else {
1761
+ this.emit('error', liveMsg);
1346
1762
  }
1347
1763
  }
1348
- if (!liveController.options.rtc) {
1349
- console.warn('unused rtc');
1350
- }
1351
- // 默认自动连接
1352
- if (liveController.options.url && liveController.options.getTicket) {
1353
- this.connect();
1354
- }
1355
- // 健康检查:WHY --> 在某些WebView特殊场景下 WebSocket.readyState 发生变化时不会出发error\close等事件;
1356
- // 因此,开启一个定时任务监测 WebSocket.readyState 状态的更新
1357
- const healthCheck = ((healthCheck) => {
1358
- if (!healthCheck)
1359
- return 0;
1360
- if (healthCheck === true)
1361
- return 3000;
1362
- const duration = Number(healthCheck);
1363
- if (duration > 0)
1364
- return duration;
1365
- return 3000;
1366
- })(liveController.options.healthCheck);
1367
- if (healthCheck) {
1368
- liveController.healthCheckId = setInterval(() => liveController.checkReadyState(this), healthCheck);
1369
- }
1370
- }
1371
- get options() {
1372
- return Object.freeze(Object.assign({}, liveController.options));
1373
- }
1374
- get readyState() {
1375
- liveController.checkReadyState(this);
1376
- return liveController.readyState;
1377
- }
1378
- get url() {
1379
- var _a;
1380
- return ((_a = liveController.webSocket) === null || _a === void 0 ? void 0 : _a.url) || '';
1381
- }
1382
- get selfInfo() {
1383
- return liveController.selfUserInfo;
1384
- }
1385
- get userList() {
1386
- return liveController.userList || [];
1387
- }
1388
- get snapshot() {
1389
- return liveController.keyframes || {};
1390
- }
1391
- get $RTC() {
1392
- return liveController.options.rtc;
1393
- }
1394
- get jsBridge() {
1395
- return liveController.options.jsBridge;
1396
- }
1397
- async setSelfInfo(userInfo) {
1398
- if (this.readyState !== exports.WebSocketState.OPEN) {
1399
- return new Error('The connection is not open and ready to communicate.');
1400
- }
1401
- try {
1402
- return await this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserInfo, userInfo);
1403
- }
1404
- catch (error) {
1405
- return error;
1764
+ });
1765
+ /**
1766
+ * 清理带看缓存的数据
1767
+ */
1768
+ this._clearLiveData = () => {
1769
+ this._buildInData = { keyframes: {} };
1770
+ };
1771
+ /**
1772
+ * 连接带看
1773
+ * @param options
1774
+ * @returns
1775
+ */
1776
+ this.connect = (options = {}) => __awaiter(this, void 0, void 0, function* () {
1777
+ var _h, _j, _k, _l;
1778
+ // 检查 url 和 票据获取接口实现
1779
+ this._options.url = (_j = (_h = options.url) !== null && _h !== void 0 ? _h : this._options.url) !== null && _j !== void 0 ? _j : '';
1780
+ this._options.getTicket = (_k = options.getTicket) !== null && _k !== void 0 ? _k : this._options.getTicket;
1781
+ this._options.initialMicroStatus =
1782
+ (_l = options.rtcMicStatus) !== null && _l !== void 0 ? _l : this._options.initialMicroStatus;
1783
+ if (!/^ws(s):\/\//.test(this._options.url) ||
1784
+ typeof this._options.getTicket !== 'function') {
1785
+ if (!/^ws(s):\/\//.test(this._options.url)) {
1786
+ return new Error('Illegal realsee live room link');
1787
+ }
1788
+ if (typeof this._options.getTicket !== 'function') {
1789
+ return new Error('getTicket muse be function');
1790
+ }
1791
+ return false;
1406
1792
  }
1407
- }
1408
- getFramesByKey(key) {
1409
- return liveController.keyframes[key];
1410
- }
1411
- sendKeyframe(key, frame) {
1412
- if (this.readyState !== exports.WebSocketState.OPEN) {
1413
- return new Error('The connection is not open and ready to communicate.');
1793
+ const { force = false } = options;
1794
+ // 检查是否已有实例在使用
1795
+ const currentState = this.state;
1796
+ if (currentState === LiveState.CONNECTING ||
1797
+ currentState === LiveState.OPEN) {
1798
+ if (force) {
1799
+ try {
1800
+ yield this._controller.close('force close by connect');
1801
+ }
1802
+ catch (e) {
1803
+ console.warn(e);
1804
+ }
1805
+ }
1806
+ else {
1807
+ return new Error('已有Live实例正在连接中,请勿重复连接!');
1808
+ }
1414
1809
  }
1415
- liveController.keyframes[key] = frame;
1416
- const liveMsg = createLiveMsg(exports.Command.KeyframeSync, this.snapshot);
1417
- liveController.sendMessage(liveMsg);
1810
+ // 建立连接
1811
+ this._clearLiveData();
1812
+ const url = appendUri(this._options.url, {
1813
+ ticket: yield this._options.getTicket(),
1814
+ force: Number(!!force),
1815
+ });
1816
+ this._controller.open(url);
1418
1817
  return true;
1419
- }
1420
- broadcast(data, toUserIds, timeout) {
1421
- if (this.readyState !== exports.WebSocketState.OPEN) {
1422
- return new Error('The connection is not open and ready to communicate.');
1818
+ });
1819
+ /**
1820
+ * 退出带看
1821
+ * @returns
1822
+ */
1823
+ this.exit = () => __awaiter(this, void 0, void 0, function* () {
1824
+ var _m;
1825
+ this._clearLiveData();
1826
+ try {
1827
+ /** 退出强制关闭语音 */
1828
+ (_m = this.$RTC) === null || _m === void 0 ? void 0 : _m.quit();
1829
+ yield this.updateStatus(exports.BuiltinEventType.RoomChange, exports.BuiltinActionType.RoomClose, {});
1423
1830
  }
1424
- return new Promise((resolve, reject) => {
1425
- const customEvent = createLiveMsg(exports.Command.CustomEvent, data, toUserIds);
1426
- const front_request_id = customEvent.front_request_id;
1427
- liveController.sendMessage(customEvent);
1428
- const timeoutId = timeout
1429
- ? setTimeout(() => {
1430
- reject(new Error('RESPONSE TIMEOUT'));
1431
- this.off('broadcast', broadcast);
1432
- }, timeout)
1433
- : undefined;
1434
- const broadcast = (data, frontRequestId) => {
1435
- if (frontRequestId !== front_request_id)
1436
- return;
1437
- this.off('broadcast', broadcast);
1438
- resolve(data);
1439
- if (timeoutId)
1440
- clearInterval(timeoutId);
1441
- };
1442
- this.on('broadcast', broadcast);
1443
- });
1444
- }
1445
- async updateStatus(evtType, atnType, status, toUserIds) {
1446
- // TODO 统一规则,不能联合类型
1447
- if (this.readyState !== exports.WebSocketState.OPEN) {
1448
- return false;
1831
+ catch (e) {
1832
+ logger$1.warn(e);
1449
1833
  }
1450
- const data = Object.assign({ event_type: evtType, action: atnType }, { data: status });
1451
- const liveMsg = createLiveMsg(exports.Command.BuiltinMsg, data, toUserIds);
1452
- liveController.sendMessage(liveMsg);
1453
- return true;
1454
- }
1834
+ return yield this._controller.close('user exit');
1835
+ });
1836
+ /**
1837
+ * 销毁带看
1838
+ * @returns
1839
+ */
1840
+ this.dispose = () => __awaiter(this, void 0, void 0, function* () {
1841
+ this._removeLiveControllerEventListeners();
1842
+ this._clearLiveData();
1843
+ return yield this._controller.dispose();
1844
+ });
1845
+ /**
1846
+ * 设置自己的用户信息
1847
+ * @param userInfo
1848
+ * @returns
1849
+ */
1850
+ this.setSelfInfo = (userInfo) => __awaiter(this, void 0, void 0, function* () {
1851
+ return yield this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserInfo, userInfo);
1852
+ });
1455
1853
  // 仅用于用户自己的麦克风控制
1456
- async toggleMicro(microStatus) {
1457
- var _a, _b;
1458
- if (!((_b = (_a = this.selfInfo) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.control_own_micro))
1854
+ this.toggleMicro = (microStatus) => __awaiter(this, void 0, void 0, function* () {
1855
+ var _o, _p, _q;
1856
+ if (!((_p = (_o = this.selfInfo) === null || _o === void 0 ? void 0 : _o.permission) === null || _p === void 0 ? void 0 : _p.control_own_micro))
1459
1857
  return false;
1460
- await this.$RTC.toggleMicro(microStatus);
1461
- return await this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserMicroStatus, {
1462
- status: microStatus ? exports.MicroStatus.OPEN : exports.MicroStatus.CLOSE,
1463
- }, []);
1464
- }
1465
- async forbidMicro(microStatus, toUserIds) {
1466
- var _a, _b;
1467
- if (liveController.options.canForbidUserMicro &&
1468
- !liveController.options.canForbidUserMicro(toUserIds)) {
1858
+ const result = yield ((_q = this.$RTC) === null || _q === void 0 ? void 0 : _q.toggleMicro(microStatus));
1859
+ if (result) {
1860
+ yield this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserMicroStatus, {
1861
+ status: microStatus ? exports.MicroStatus.OPEN : exports.MicroStatus.CLOSE,
1862
+ }, []);
1863
+ }
1864
+ return result;
1865
+ });
1866
+ /**
1867
+ * 控制别人的麦
1868
+ * @param microStatus
1869
+ * @param toUserIds
1870
+ * @returns
1871
+ */
1872
+ this.forbidMicro = (microStatus, toUserIds) => __awaiter(this, void 0, void 0, function* () {
1873
+ var _r, _s;
1874
+ if (typeof this._options.canForbidUserMicro === 'function' &&
1875
+ !this._options.canForbidUserMicro(toUserIds)) {
1469
1876
  return false;
1470
1877
  }
1471
- if (!((_b = (_a = this.selfInfo) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.control_other_micro)) {
1878
+ if (!((_s = (_r = this.selfInfo) === null || _r === void 0 ? void 0 : _r.permission) === null || _s === void 0 ? void 0 : _s.control_other_micro)) {
1472
1879
  return false;
1473
1880
  }
1474
- return await this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserMicroStatus, {
1881
+ return yield this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserMicroStatus, {
1475
1882
  status: microStatus,
1476
1883
  }, toUserIds);
1477
- }
1884
+ });
1478
1885
  /**
1479
- * @deprecated 暂不可用
1886
+ * 控制别人的同步全量帧数据权限
1887
+ * @param sync
1888
+ * @param toUserIds
1889
+ * @returns
1480
1890
  */
1481
- async forbidSync(sync, toUserIds) {
1482
- var _a, _b;
1483
- if (liveController.options.canForbidUserSync &&
1484
- !liveController.options.canForbidUserSync(toUserIds)) {
1891
+ this.forbidSync = (sync, toUserIds) => __awaiter(this, void 0, void 0, function* () {
1892
+ var _t, _u;
1893
+ if (typeof this._options.canForbidUserSync === 'function' &&
1894
+ !this._options.canForbidUserSync(toUserIds)) {
1485
1895
  return false;
1486
1896
  }
1487
- if (!((_b = (_a = this.selfInfo) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.control_other_sync)) {
1897
+ if (!((_u = (_t = this.selfInfo) === null || _t === void 0 ? void 0 : _t.permission) === null || _u === void 0 ? void 0 : _u.control_other_sync)) {
1488
1898
  return false;
1489
1899
  }
1490
- return await this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserPermission, { sync_frame: sync }, toUserIds);
1491
- }
1492
- async kick(toUserIds) {
1493
- var _a, _b;
1494
- if (liveController.options.canForbidUserKick &&
1495
- !liveController.options.canForbidUserKick(toUserIds)) {
1900
+ return yield this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserPermission, { sync_frame: sync }, toUserIds);
1901
+ });
1902
+ /**
1903
+ * 把用户踢出带看
1904
+ * @param toUserIds
1905
+ * @returns
1906
+ */
1907
+ this.kick = (toUserIds) => __awaiter(this, void 0, void 0, function* () {
1908
+ var _v, _w;
1909
+ if (typeof this._options.canForbidUserKick === 'function' &&
1910
+ !this._options.canForbidUserKick(toUserIds)) {
1496
1911
  return false;
1497
1912
  }
1498
- if (!((_b = (_a = this.selfInfo) === null || _a === void 0 ? void 0 : _a.permission) === null || _b === void 0 ? void 0 : _b.change_other_status)) {
1913
+ if (!((_w = (_v = this.selfInfo) === null || _v === void 0 ? void 0 : _v.permission) === null || _w === void 0 ? void 0 : _w.change_other_status)) {
1499
1914
  return false;
1500
1915
  }
1501
- return await this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserStatus, {
1916
+ return yield this.updateStatus(exports.BuiltinEventType.UserChange, exports.BuiltinActionType.UserStatus, {
1502
1917
  status: 'KICK_OUT',
1503
1918
  }, toUserIds);
1504
- }
1505
- async exit() {
1506
- /** 退出强制关闭语音(?) */
1507
- try {
1508
- this.$RTC.quit();
1509
- await this.updateStatus(exports.BuiltinEventType.RoomChange, exports.BuiltinActionType.RoomClose, {});
1510
- }
1511
- catch (e) {
1512
- console.log(e);
1513
- }
1514
- return liveController.dispose();
1515
- }
1516
- async connect(options = {}) {
1517
- // 连接 WebSocket 前验证麦克风权限
1518
- const microAuth = await this.$RTC.detectMicro();
1519
- if (!microAuth) {
1520
- const error = new Error('系统监测麦克风未授权~');
1521
- this.emit('ws.error', { type: exports.WebSocketErrorType.MicroAuth, error });
1522
- return error;
1523
- }
1524
- // WebSocket 正在连接中,规避重复连接
1525
- if (liveController.connecting) {
1526
- const error = new Error('WebSocket 正在连接中,请勿重复连接 ...');
1527
- this.emit('ws.error', {
1528
- type: exports.WebSocketErrorType.DuplicateConnect,
1529
- error,
1530
- });
1531
- return error;
1532
- }
1533
- // 非强制连接场景下,如果已经完成 WebSocket 连接则不执行后续逻辑
1534
- const { force } = options;
1535
- if (!force) {
1536
- if (this.readyState === exports.WebSocketState.CONNECTING ||
1537
- this.readyState === exports.WebSocketState.OPEN) {
1538
- return true;
1919
+ });
1920
+ this._addLiveControllerEventListeners();
1921
+ this._options = Object.assign({ initialMicroStatus: exports.MicroStatus.OPEN }, opts);
1922
+ // 第一步检查jsbridge
1923
+ this._options.jsBridge = (() => {
1924
+ if (opts.jsBridge)
1925
+ return opts.jsBridge;
1926
+ if (opts.useBuiltInJsBridge)
1927
+ return new JSBridge__default["default"]();
1928
+ return undefined;
1929
+ })();
1930
+ // 第二步检查getVoiceSign
1931
+ this._options.getVoiceSign = (_a = opts.getVoiceSign) !== null && _a !== void 0 ? _a : unimplementedGetVoiceSign;
1932
+ // 第二步检查rtc
1933
+ this._options.rtc = (() => {
1934
+ // 优先取rtc实例
1935
+ if (opts.rtc)
1936
+ return opts.rtc;
1937
+ // 取指定的内部rtc类型
1938
+ if (opts.rtcType) {
1939
+ if (!opts.getVoiceSign) {
1940
+ logger$1.error('GetVoiceSign method must be passed when using built-in RTC instances');
1941
+ }
1942
+ switch (opts.rtcType) {
1943
+ case exports.RTCType.RealseeVRWebViewRTC: {
1944
+ // 内置的 VRWebViewRTC
1945
+ if (this._options.jsBridge) {
1946
+ return new VRWebViewRTC({
1947
+ jsBridge: this._options.jsBridge,
1948
+ getVoiceSign: this._options.getVoiceSign,
1949
+ });
1950
+ }
1951
+ else {
1952
+ logger$1.error('JsBridge instance must be passed when using built-in VRWebViewRTC instances');
1953
+ return undefined;
1954
+ }
1955
+ }
1956
+ case exports.RTCType.RealseeBrowserChimeRTC: {
1957
+ // 内置的 RealseeBrowserChimeRTC
1958
+ return new BrowserRTC4Chime({
1959
+ getVoiceSign: this._options.getVoiceSign,
1960
+ logLevel: opts.__debug__ ? LogLevel.DEBUG : LogLevel.ERROR,
1961
+ });
1962
+ }
1963
+ case exports.RTCType.RealseeBrowserRTC: {
1964
+ // 内置的 RealseeBrowserRTC
1965
+ return new BrowserRTC({
1966
+ getVoiceSign: this._options.getVoiceSign,
1967
+ });
1968
+ }
1969
+ default: {
1970
+ logger$1.error('unknown built-in RTC type');
1971
+ return undefined;
1972
+ }
1539
1973
  }
1540
1974
  }
1541
- // WebSocket URL 逻辑
1542
- if (options.url) {
1543
- liveController.options.url = options.url;
1544
- }
1545
- if (options.getTicket) {
1546
- liveController.options.getTicket = options.getTicket;
1547
- }
1548
- if (!liveController.options.url ||
1549
- !liveController.options.url.startsWith('ws')) {
1550
- const error = new Error(`WebSocket URL 未配置或格式不合法:"${liveController.options.url}"`);
1551
- this.emit('ws.error', { type: exports.WebSocketErrorType.IllegalURL, error });
1552
- return error;
1553
- }
1554
- if (!liveController.options.getTicket) {
1555
- const error = new Error(`getTicket() 未配置!`);
1556
- this.emit('ws.error', { type: exports.WebSocketErrorType.IllegalArgs, error });
1557
- return error;
1558
- }
1559
- // 连接锁
1560
- liveController.connecting = true;
1561
- // 连接前销毁之前绑定的事件
1562
- liveController.disposeWebSocket();
1563
- this.emit('ws.beforeConnect');
1564
- const url = force || options.url || !this.url
1565
- ? appendUri(liveController.options.url, {
1566
- ticket: await liveController.options.getTicket(),
1567
- force: Number(!!force),
1568
- })
1569
- : this.url;
1570
- liveController.webSocket = new WebSocket(url);
1571
- liveController.onEvtOpnListener = () => {
1572
- liveController.checkReadyState(this);
1573
- this.emit('ws.afterConnect');
1574
- };
1575
- liveController.onEvtMsgListener = (evt) => {
1576
- liveController.checkReadyState(this);
1577
- try {
1578
- const liveMsg = parseLiveMsg(evt.data);
1579
- if (liveMsg === false)
1580
- return;
1581
- liveController.handleMessage(liveMsg, this);
1975
+ // 都不满足时取内置
1976
+ if (opts.useBuiltInRTC) {
1977
+ if (!opts.getVoiceSign) {
1978
+ logger$1.error('GetVoiceSign method must be passed when using built-in RTC instances');
1582
1979
  }
1583
- catch (error) {
1584
- // 未知错误
1585
- this.emit('ws.error', {
1586
- type: exports.WebSocketErrorType.Unknown,
1587
- error,
1588
- target: evt,
1589
- });
1980
+ if (this._options.jsBridge) {
1981
+ if ((isRealseeVRWebview && (isAndroid || isIOS)) || isWxMiniProgram) {
1982
+ return new VRWebViewRTC({
1983
+ jsBridge: this._options.jsBridge,
1984
+ getVoiceSign: this._options.getVoiceSign,
1985
+ });
1986
+ }
1987
+ else {
1988
+ // 其它终端使用
1989
+ return opts.builtInRTCType === exports.BuiltInRTCType.RealseeXChimeRTC
1990
+ ? new BrowserRTC4Chime({
1991
+ getVoiceSign: this._options.getVoiceSign,
1992
+ })
1993
+ : new BrowserRTC({ getVoiceSign: this._options.getVoiceSign });
1994
+ }
1590
1995
  }
1591
- };
1592
- liveController.onEvtErrListener = (evt) => {
1593
- live.emit('ws.error', { type: exports.WebSocketErrorType.Error, target: evt });
1594
- liveController.checkReadyState(this);
1595
- };
1596
- liveController.onEvtCLEListener = (evt) => {
1597
- liveController.checkReadyState(this);
1598
- const code = Number(evt.code);
1599
- if (code === 1000)
1600
- return;
1601
- // 异常退出不一定会触发'error'事件,根据 evt.code 一些类型的退出也算是 error 行为
1602
- const errMsg = parseWSClsErr(code);
1603
- live.emit('ws.error', {
1604
- target: evt,
1605
- type: exports.WebSocketErrorType.Close,
1606
- closeError: errMsg,
1607
- });
1608
- };
1609
- liveController.webSocket.addEventListener('open', liveController.onEvtOpnListener);
1610
- liveController.webSocket.addEventListener('message', liveController.onEvtMsgListener);
1611
- liveController.webSocket.addEventListener('error', liveController.onEvtErrListener);
1612
- liveController.webSocket.addEventListener('close', liveController.onEvtCLEListener);
1613
- return await new Promise((resolve, reject) => {
1614
- const success = () => {
1615
- resolve(true);
1616
- liveController.connecting = false;
1617
- this.off('ws.error', fail);
1618
- };
1619
- const fail = (error) => {
1620
- reject(error.error
1621
- ? error.error
1622
- : new Error('WebSocket connection failed!'));
1623
- liveController.connecting = false;
1624
- this.off('ws.afterConnect', success);
1625
- };
1626
- this.once('ws.afterConnect', success);
1627
- this.once('ws.error', fail);
1628
- });
1996
+ else {
1997
+ logger$1.error('jsBridge instance must be passed when using built-in RTC instances');
1998
+ return undefined;
1999
+ }
2000
+ }
2001
+ return undefined;
2002
+ })();
2003
+ if (!this._options.rtc) {
2004
+ logger$1.warn('unused rtc');
1629
2005
  }
1630
- async revoke() {
1631
- return true;
2006
+ // 第三步进行自动连接
2007
+ if (this._options.url && this._options.getTicket) {
2008
+ this.connect();
2009
+ }
2010
+ if (this._options.__debug__) {
2011
+ Object.assign(window, { $liveController: this._controller, $live: this });
1632
2012
  }
1633
2013
  }
1634
- const live = new LiveTpl();
1635
- // 如果是调试环境则将内部状态暴露出来
1636
- if (options.__debug__) {
1637
- Object.assign(live, { __controller__: liveController });
1638
- Object.assign(window, { $live: live });
2014
+ get options() {
2015
+ return Object.freeze(this._options || {});
2016
+ }
2017
+ /**
2018
+ * 带看状态
2019
+ */
2020
+ get state() {
2021
+ return this._controller.state;
2022
+ }
2023
+ /**
2024
+ * 兼容老逻辑
2025
+ * @deprecated 请直接读取 state 属性字段,未来将移除该属性
2026
+ */
2027
+ get readyState() {
2028
+ return this._controller.state;
2029
+ }
2030
+ /**
2031
+ * 获取当前WebSocket连接的URL。(注意:这个是WebSocket连接的完整连接,附带一些query参数)。
2032
+ * @deprecated 带看不需要关注底层ws的相关信息,未来将移除
2033
+ */
2034
+ get url() {
2035
+ return this.options.url;
2036
+ }
2037
+ /**
2038
+ * 获取当前live使用的RTC实例
2039
+ */
2040
+ get $RTC() {
2041
+ return this._options.rtc;
2042
+ }
2043
+ /**
2044
+ * 获取当前live使用的jsBridge实例
2045
+ */
2046
+ get jsBridge() {
2047
+ return this._options.jsBridge;
2048
+ }
2049
+ /**
2050
+ * 当前帧数据快照
2051
+ */
2052
+ get snapshot() {
2053
+ return this._buildInData.keyframes;
2054
+ }
2055
+ /**
2056
+ * 当前用户信息
2057
+ */
2058
+ get selfInfo() {
2059
+ return this._buildInData.selfInfo;
2060
+ }
2061
+ /**
2062
+ * 当前用户列表
2063
+ */
2064
+ get userList() {
2065
+ return this._buildInData.userList || [];
2066
+ }
2067
+ /**
2068
+ * 当前带看房间信息
2069
+ */
2070
+ get roomInfo() {
2071
+ return this._buildInData.roomInfo;
2072
+ }
2073
+ /**
2074
+ * 修改状态
2075
+ * @param evtType
2076
+ * @param atnType
2077
+ * @param status
2078
+ * @param toUserIds
2079
+ * @returns
2080
+ */
2081
+ updateStatus(evtType, atnType, status, toUserIds) {
2082
+ return __awaiter(this, void 0, void 0, function* () {
2083
+ if (this.state !== LiveState.OPEN)
2084
+ return false;
2085
+ const data = Object.assign({ event_type: evtType, action: atnType }, { data: status });
2086
+ const liveMsg = createLiveMsg(exports.Command.BuiltinMsg, data, toUserIds);
2087
+ try {
2088
+ this._controller.sendMessage(liveMsg);
2089
+ return true;
2090
+ }
2091
+ catch (e) {
2092
+ logger$1.error(e);
2093
+ return false;
2094
+ }
2095
+ });
2096
+ }
2097
+ /**
2098
+ * 自定义广播
2099
+ * @param request 广播请求的数据
2100
+ * @param toUserIds
2101
+ * @param timeout
2102
+ * @returns
2103
+ */
2104
+ broadcast(request, toUserIds, timeout) {
2105
+ if (this.state !== LiveState.OPEN)
2106
+ return false;
2107
+ return new Promise((resolve, reject) => {
2108
+ const customEvent = createLiveMsg(exports.Command.CustomEvent, request, toUserIds);
2109
+ const front_request_id = customEvent.front_request_id;
2110
+ const timeoutId = timeout
2111
+ ? setTimeout(() => {
2112
+ reject(new Error('RESPONSE TIMEOUT'));
2113
+ this.off('broadcast', broadcastRes);
2114
+ }, timeout)
2115
+ : undefined;
2116
+ const broadcastRes = (data, frontRequestId) => {
2117
+ if (frontRequestId !== front_request_id)
2118
+ return;
2119
+ if (timeoutId)
2120
+ clearTimeout(timeoutId);
2121
+ this.off('broadcast', broadcastRes);
2122
+ resolve(data);
2123
+ };
2124
+ this.on('broadcast', broadcastRes);
2125
+ try {
2126
+ this._controller.sendMessage(customEvent);
2127
+ }
2128
+ catch (e) {
2129
+ reject(e);
2130
+ }
2131
+ });
1639
2132
  }
1640
- return live;
1641
2133
  }
1642
2134
 
2135
+ /**
2136
+ * 创建`Live`实例
2137
+ * @param opts
2138
+ * @returns
2139
+ */
2140
+ const createLive = (opts) => {
2141
+ _clearLiveInstanceIfNeed();
2142
+ return new Live(opts);
2143
+ };
2144
+
1643
2145
  /**
1644
2146
  * 创建 {@link LiveReact} 实例,并提供 `React` 技术栈相关工具链。
1645
2147
  */
1646
2148
  function createLiveReact(options) {
1647
- const LiveContext = React__default["default"].createContext(null);
2149
+ const LiveContext = React.createContext(null);
1648
2150
  const live = createLive(options);
1649
2151
  const jsBridge = live.jsBridge;
1650
- function LiveProvider(props) {
1651
- return (React__default["default"].createElement(LiveContext.Provider, { value: props.live || live }, props.children));
1652
- }
1653
- function useLiveInstance() {
2152
+ const LiveProvider = (props) => (React__default["default"].createElement(LiveContext.Provider, { value: live }, props.children));
2153
+ /**
2154
+ * 使用live实例
2155
+ * @returns
2156
+ */
2157
+ const useLiveInstance = () => {
1654
2158
  const context = React__default["default"].useContext(LiveContext);
1655
2159
  if (!context)
1656
2160
  throw new Error('LiveProvider never found.');
1657
2161
  return context;
1658
- }
2162
+ };
1659
2163
  /**
2164
+ * 不建议这样使用
1660
2165
  * @deprecated
1661
2166
  * @returns
1662
2167
  */
1663
- function unsafe__useLiveInstance() {
1664
- return useLiveInstance();
1665
- }
1666
- function useRTCInstance() {
1667
- const live = useLiveInstance();
1668
- return live.$RTC;
1669
- }
2168
+ const unsafe__useLiveInstance = React.useCallback(() => useLiveInstance(), [useLiveInstance]);
2169
+ /**
2170
+ * 使用rtc实例
2171
+ */
2172
+ const useRTCInstance = React.useCallback(() => useLiveInstance().$RTC, [useLiveInstance]);
1670
2173
  /**
2174
+ * 不建议这样使用
1671
2175
  * @deprecated
1672
2176
  * @returns
1673
2177
  */
1674
- function unsafe__useRTCInstance() {
1675
- return useRTCInstance();
1676
- }
1677
- function useConnect() {
1678
- const live = useLiveInstance();
1679
- return async (options) => await live.connect(options);
1680
- }
1681
- function useCurrentWebSocketUrl() {
1682
- const live = useLiveInstance();
1683
- const [state, setState] = React__default["default"].useState(undefined);
1684
- React__default["default"].useEffect(() => {
1685
- const onWSBeforeConnect = () => setState(live.url);
1686
- live.on('ws.beforeConnect', onWSBeforeConnect);
1687
- return () => live.off('ws.beforeConnect', onWSBeforeConnect);
1688
- }, [live]);
1689
- return state;
1690
- }
1691
- function useKeyframeUpdateCallback(name, callback, deps = []) {
2178
+ const unsafe__useRTCInstance = React.useCallback(() => useRTCInstance(), [useRTCInstance]);
2179
+ /**
2180
+ * 带看连接操作
2181
+ */
2182
+ const useConnect = React.useCallback((options) => __awaiter(this, void 0, void 0, function* () { return yield useLiveInstance().connect(options); }), []);
2183
+ /**
2184
+ *
2185
+ * @param name
2186
+ * @param callback
2187
+ * @param deps
2188
+ * @returns
2189
+ */
2190
+ function useKeyframeUpdateCallback(key, callback, deps = []) {
1692
2191
  const live = useLiveInstance();
1693
2192
  const dependencyList = [live, name, ...deps];
1694
- const dispose = () => live.keyframes.off(name, callback);
2193
+ const dispose = () => live.keyframes.off(key, callback);
1695
2194
  React__default["default"].useEffect(() => {
1696
- live.keyframes.on(name, callback);
2195
+ live.keyframes.on(key, callback);
1697
2196
  return dispose;
1698
2197
  }, dependencyList);
1699
2198
  return dispose;
1700
2199
  }
2200
+ /**
2201
+ * 带看的一些操作
2202
+ * @returns
2203
+ */
1701
2204
  function useLiveAction() {
1702
2205
  const live = useLiveInstance();
2206
+ const connect = React__default["default"].useCallback((options) => __awaiter(this, void 0, void 0, function* () { return yield live.connect(options); }), [live]);
1703
2207
  const toggleMicro = React__default["default"].useCallback((microStatus) => live.toggleMicro(microStatus), [live]);
1704
- const broadcast = React__default["default"].useCallback((data, toUserIds, timeout = 0) => live.broadcast(data, toUserIds, timeout), [live]);
1705
- const exit = React__default["default"].useCallback(() => live.exit(), [live]);
1706
- const kick = React__default["default"].useCallback((toUserIds) => live.kick(toUserIds), [live]);
1707
- const forbidMicro = React__default["default"].useCallback((micro, toUserIds) => live.forbidMicro(micro, toUserIds), [live]);
1708
- // const forbidSync = React.useCallback(
1709
- // (sync: boolean, toUserIds?: string | string[] | undefined) =>
1710
- // live.forbidSync(sync, toUserIds),
1711
- // [live],
1712
- // );
2208
+ const broadcast = React__default["default"].useCallback((data, toUserIds, timeout = 0) => __awaiter(this, void 0, void 0, function* () { return yield live.broadcast(data, toUserIds, timeout); }), [live]);
2209
+ const exit = React__default["default"].useCallback(() => __awaiter(this, void 0, void 0, function* () { return yield live.exit(); }), [live]);
2210
+ const kick = React__default["default"].useCallback((toUserIds) => __awaiter(this, void 0, void 0, function* () { return yield live.kick(toUserIds); }), [live]);
2211
+ const forbidMicro = React__default["default"].useCallback((micro, toUserIds = []) => __awaiter(this, void 0, void 0, function* () { return yield live.forbidMicro(micro, toUserIds); }), [live]);
2212
+ const forbidSync = React__default["default"].useCallback((sync, toUserIds = []) => live.forbidSync(sync, toUserIds), [live]);
1713
2213
  const getFramesByKey = React__default["default"].useCallback((key) => live.getFramesByKey(key), [live]);
1714
2214
  const sendKeyframe = React__default["default"].useCallback((key, frame) => live.sendKeyframe(key, frame), [live]);
1715
2215
  const setSelfInfo = React__default["default"].useCallback((userInfo) => live.setSelfInfo(userInfo), [live]);
1716
2216
  const updateStatus = React__default["default"].useCallback((evtType, atnType, status, toUserIds) => live.updateStatus(evtType, atnType, status, toUserIds), [live]);
1717
2217
  return {
2218
+ connect,
1718
2219
  broadcast,
1719
2220
  exit,
1720
2221
  kick,
1721
2222
  toggleMicro,
1722
2223
  forbidMicro,
1723
- // forbidSync,
2224
+ forbidSync,
1724
2225
  sendKeyframe,
1725
2226
  getFramesByKey,
1726
2227
  setSelfInfo,
@@ -1751,16 +2252,16 @@ function createLiveReact(options) {
1751
2252
  return dispose;
1752
2253
  }
1753
2254
  /**
1754
- * @deprecated
2255
+ * 带看状态
1755
2256
  * @returns
1756
2257
  */
1757
- function useReadyState() {
2258
+ function useLiveState() {
1758
2259
  const live = useLiveInstance();
1759
- const [state, updateState] = React__default["default"].useState(live.readyState);
2260
+ const [state, updateState] = React__default["default"].useState(live.state);
1760
2261
  React__default["default"].useEffect(() => {
1761
- const readyStateUpdate = (readyState) => updateState(readyState);
1762
- live.on('ws.readyStateUpdate', readyStateUpdate);
1763
- return () => live.off('ws.readyStateUpdate', readyStateUpdate);
2262
+ const stateChange = (state) => updateState(state);
2263
+ live.on('stateChange', stateChange);
2264
+ return () => live.off('stateChange', stateChange);
1764
2265
  }, [live]);
1765
2266
  return state;
1766
2267
  }
@@ -1797,12 +2298,12 @@ function createLiveReact(options) {
1797
2298
  live.on('selfInfoUpdate', selfInfoUpdate);
1798
2299
  return () => live.off('selfInfoUpdate', selfInfoUpdate);
1799
2300
  }, [live]);
1800
- const setState = React__default["default"].useCallback(async (userInfo) => {
1801
- return await live.setSelfInfo(userInfo);
1802
- }, [live]);
2301
+ const setState = React__default["default"].useCallback((userInfo) => __awaiter(this, void 0, void 0, function* () {
2302
+ return yield live.setSelfInfo(userInfo);
2303
+ }), [live]);
1803
2304
  return [state, setState];
1804
2305
  }
1805
- function useSnapshot() {
2306
+ function useKeyframesSnapshot() {
1806
2307
  const live = useLiveInstance();
1807
2308
  const [state, setState] = React__default["default"].useState(live.snapshot);
1808
2309
  React__default["default"].useEffect(() => {
@@ -1822,43 +2323,23 @@ function createLiveReact(options) {
1822
2323
  }, [live]);
1823
2324
  return state;
1824
2325
  }
1825
- /**
1826
- *
1827
- * @param name
1828
- * @param callback
1829
- * @param deps
1830
- * @returns
1831
- * @deprecated
1832
- */
1833
- function useWebSocketEventCallback(name, callback, deps = []) {
1834
- const live = useLiveInstance();
1835
- const dispose = () => live.off(name, callback);
1836
- const dependencyList = [live, name, ...deps];
1837
- React__default["default"].useEffect(() => {
1838
- live.on(name, callback);
1839
- return dispose;
1840
- }, dependencyList);
1841
- return dispose;
1842
- }
1843
2326
  return {
1844
2327
  live,
1845
2328
  jsBridge,
1846
2329
  LiveProvider,
1847
2330
  unsafe__useLiveInstance,
1848
2331
  unsafe__useRTCInstance,
1849
- useCurrentWebSocketUrl,
1850
2332
  useConnect,
1851
2333
  useKeyframe,
1852
2334
  useKeyframeUpdateCallback,
1853
2335
  useLiveAction,
1854
2336
  useLiveEventCallback,
1855
- useReadyState,
2337
+ useLiveState,
1856
2338
  useRTCAction,
1857
2339
  useRTCEventCallback,
1858
2340
  useSelfInfo,
1859
- useSnapshot,
2341
+ useKeyframesSnapshot,
1860
2342
  useUserList,
1861
- useWebSocketEventCallback,
1862
2343
  };
1863
2344
  }
1864
2345