@xmaxai/web-sdk 1.0.5 → 1.0.6
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.
- package/README.md +77 -19
- package/dist/{VideoContentMode-BM97_H8V.d.cts → VideoRenderStatistics-C7zqzfuS.d.cts} +23 -1
- package/dist/{VideoContentMode-BM97_H8V.d.ts → VideoRenderStatistics-C7zqzfuS.d.ts} +23 -1
- package/dist/{chunk-JN6HURTT.cjs → chunk-NWNRFTLE.cjs} +990 -262
- package/dist/chunk-NWNRFTLE.cjs.map +1 -0
- package/dist/{chunk-VMJXIVUF.js → chunk-PLFWPS5A.js} +776 -48
- package/dist/chunk-PLFWPS5A.js.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -6
- package/dist/index.d.ts +39 -6
- package/dist/index.js +1 -1
- package/dist/react/index.cjs +6 -3
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +5 -1
- package/dist/react/index.d.ts +5 -1
- package/dist/react/index.js +4 -1
- package/dist/react/index.js.map +1 -1
- package/package.json +7 -9
- package/dist/chunk-JN6HURTT.cjs.map +0 -1
- package/dist/chunk-VMJXIVUF.js.map +0 -1
|
@@ -205,7 +205,7 @@ var XmaxError = class _XmaxError extends Error {
|
|
|
205
205
|
};
|
|
206
206
|
|
|
207
207
|
// src/Foundation/Runtime/RuntimeInfo.ts
|
|
208
|
-
var XMAX_SDK_VERSION = "1.0.
|
|
208
|
+
var XMAX_SDK_VERSION = "1.0.6";
|
|
209
209
|
var _RuntimeInfo = class _RuntimeInfo {
|
|
210
210
|
/**
|
|
211
211
|
* 序列化为接口传输使用的 snake_case 字段。
|
|
@@ -600,7 +600,6 @@ var RtcProvider = /* @__PURE__ */ ((RtcProvider2) => {
|
|
|
600
600
|
var RealtimeModel = /* @__PURE__ */ ((RealtimeModel2) => {
|
|
601
601
|
RealtimeModel2["x2_0"] = "x2.0";
|
|
602
602
|
RealtimeModel2["x2_0_trtc"] = "x2.0-trtc";
|
|
603
|
-
RealtimeModel2["x2_0_agora"] = "x2.0-agora";
|
|
604
603
|
RealtimeModel2["x2_1_preview"] = "x2.1-preview";
|
|
605
604
|
return RealtimeModel2;
|
|
606
605
|
})(RealtimeModel || {});
|
|
@@ -616,12 +615,10 @@ function modelDefaults(model) {
|
|
|
616
615
|
var MODEL_DISPLAY_NAMES = {
|
|
617
616
|
["x2.0" /* x2_0 */]: "X2.0",
|
|
618
617
|
["x2.0-trtc" /* x2_0_trtc */]: "X2.1-preview-trtc",
|
|
619
|
-
["x2.
|
|
620
|
-
["x2.1-preview" /* x2_1_preview */]: "X2.1-preview-vertc"
|
|
618
|
+
["x2.1-preview" /* x2_1_preview */]: "X2.1-preview-agora"
|
|
621
619
|
};
|
|
622
620
|
var MODEL_BASE_URLS = {
|
|
623
|
-
["x2.
|
|
624
|
-
["x2.1-preview" /* x2_1_preview */]: "https://dev.xmaxai.com/open/api/v1"
|
|
621
|
+
["x2.1-preview" /* x2_1_preview */]: "https://cloud.xmax.22duck.cn/open/api/v1"
|
|
625
622
|
};
|
|
626
623
|
var RESOLUTION_BUCKETS = {
|
|
627
624
|
["x2.0" /* x2_0 */]: [],
|
|
@@ -629,10 +626,6 @@ var RESOLUTION_BUCKETS = {
|
|
|
629
626
|
{ width: 1024, height: 1920 },
|
|
630
627
|
{ width: 1920, height: 1024 }
|
|
631
628
|
],
|
|
632
|
-
["x2.0-agora" /* x2_0_agora */]: [
|
|
633
|
-
{ width: 1024, height: 1920 },
|
|
634
|
-
{ width: 1920, height: 1024 }
|
|
635
|
-
],
|
|
636
629
|
["x2.1-preview" /* x2_1_preview */]: [
|
|
637
630
|
{ width: 1024, height: 1920 },
|
|
638
631
|
{ width: 1920, height: 1024 }
|
|
@@ -641,7 +634,6 @@ var RESOLUTION_BUCKETS = {
|
|
|
641
634
|
var MAXIMUM_INPUT_PIXELS = {
|
|
642
635
|
["x2.0" /* x2_0 */]: 128e4,
|
|
643
636
|
["x2.0-trtc" /* x2_0_trtc */]: 21e5,
|
|
644
|
-
["x2.0-agora" /* x2_0_agora */]: 21e5,
|
|
645
637
|
["x2.1-preview" /* x2_1_preview */]: 21e5
|
|
646
638
|
};
|
|
647
639
|
function modelDisplayName(model) {
|
|
@@ -674,8 +666,7 @@ function defaultCameraVideoFormat(model) {
|
|
|
674
666
|
var MODEL_RTC_PROVIDERS = {
|
|
675
667
|
["x2.0" /* x2_0 */]: Object.freeze(["vertc" /* vertc */]),
|
|
676
668
|
["x2.0-trtc" /* x2_0_trtc */]: Object.freeze(["trtc" /* trtc */]),
|
|
677
|
-
["x2.
|
|
678
|
-
["x2.1-preview" /* x2_1_preview */]: Object.freeze(["vertc" /* vertc */])
|
|
669
|
+
["x2.1-preview" /* x2_1_preview */]: Object.freeze(["agora" /* agora */])
|
|
679
670
|
};
|
|
680
671
|
function supportedRtcProviders(model) {
|
|
681
672
|
return isKnownModel(model) ? MODEL_RTC_PROVIDERS[model] : CUSTOM_MODEL_RTC_PROVIDERS;
|
|
@@ -1269,6 +1260,11 @@ ${JSON.stringify({
|
|
|
1269
1260
|
receivedBytes: valid(rtc.RecvBytes),
|
|
1270
1261
|
localVideo,
|
|
1271
1262
|
remoteVideo: remote,
|
|
1263
|
+
capture: {
|
|
1264
|
+
width: valid(local.captureResolutionWidth, 1),
|
|
1265
|
+
height: valid(local.captureResolutionHeight, 1),
|
|
1266
|
+
frameRate: valid(local.captureFrameRate)
|
|
1267
|
+
},
|
|
1272
1268
|
localAudio: client.getLocalAudioStats(),
|
|
1273
1269
|
remoteAudio: client.getRemoteAudioStats()
|
|
1274
1270
|
}, null, 2)}`, 2 /* performance */);
|
|
@@ -1316,6 +1312,59 @@ function rtcOrientedVideoSize(size, environment) {
|
|
|
1316
1312
|
return shouldTransposeRtcVideoSize(environment) ? { width: size.height, height: size.width } : size;
|
|
1317
1313
|
}
|
|
1318
1314
|
|
|
1315
|
+
// src/Foundation/RTC/Agora/AgoraVideoSender.ts
|
|
1316
|
+
var AgoraVideoSender = class {
|
|
1317
|
+
static async apply(track, config, ensureActive2) {
|
|
1318
|
+
ensureActive2();
|
|
1319
|
+
const sender = _optionalChain([track, 'access', _72 => _72.getRTCRtpTransceiver, 'call', _73 => _73(), 'optionalAccess', _74 => _74.sender]);
|
|
1320
|
+
if (!sender) throw new XmaxError("RTC_ERROR" /* rtcError */, "WebRTC video sender is unavailable");
|
|
1321
|
+
const capture = _optionalChain([sender, 'access', _75 => _75.track, 'optionalAccess', _76 => _76.getSettings, 'call', _77 => _77()]);
|
|
1322
|
+
if (!_optionalChain([capture, 'optionalAccess', _78 => _78.width]) || !capture.height) {
|
|
1323
|
+
throw new XmaxError("RTC_ERROR" /* rtcError */, "WebRTC capture dimensions are unavailable");
|
|
1324
|
+
}
|
|
1325
|
+
const scale = Math.max(1, capture.width / config.width, capture.height / config.height);
|
|
1326
|
+
const parameters = sender.getParameters();
|
|
1327
|
+
if (_optionalChain([parameters, 'access', _79 => _79.encodings, 'optionalAccess', _80 => _80.length]) !== 1) {
|
|
1328
|
+
throw new XmaxError("RTC_ERROR" /* rtcError */, "Sender-only configuration requires one video encoding");
|
|
1329
|
+
}
|
|
1330
|
+
const encoding = parameters.encodings[0];
|
|
1331
|
+
const previous = { ...encoding };
|
|
1332
|
+
const previousPreference = parameters.degradationPreference;
|
|
1333
|
+
encoding.scaleResolutionDownBy = scale;
|
|
1334
|
+
encoding.maxFramerate = config.frameRate;
|
|
1335
|
+
encoding.maxBitrate = Math.round(config.maximumBitrate * 1e3);
|
|
1336
|
+
parameters.degradationPreference = config.encoderPreference === "maintainFramerate" /* maintainFramerate */ ? "maintain-framerate" : "maintain-resolution";
|
|
1337
|
+
await sender.setParameters(parameters);
|
|
1338
|
+
ensureActive2();
|
|
1339
|
+
if (_optionalChain([track, 'access', _81 => _81.getRTCRtpTransceiver, 'call', _82 => _82(), 'optionalAccess', _83 => _83.sender]) !== sender) {
|
|
1340
|
+
throw new XmaxError("CANCELLED" /* cancelled */, "WebRTC video sender changed during configuration");
|
|
1341
|
+
}
|
|
1342
|
+
const applied = sender.getParameters();
|
|
1343
|
+
const actual = _optionalChain([applied, 'access', _84 => _84.encodings, 'optionalAccess', _85 => _85[0]]);
|
|
1344
|
+
if (!actual || Math.abs((_nullishCoalesce(actual.scaleResolutionDownBy, () => ( 1))) - scale) > 1e-4 || actual.maxFramerate !== encoding.maxFramerate || actual.maxBitrate !== encoding.maxBitrate) {
|
|
1345
|
+
if (actual && applied.encodings.length === 1) {
|
|
1346
|
+
for (const key of ["scaleResolutionDownBy", "maxFramerate", "maxBitrate"]) {
|
|
1347
|
+
if (previous[key] === void 0) delete actual[key];
|
|
1348
|
+
else actual[key] = previous[key];
|
|
1349
|
+
}
|
|
1350
|
+
if (previousPreference === void 0) delete applied.degradationPreference;
|
|
1351
|
+
else applied.degradationPreference = previousPreference;
|
|
1352
|
+
await sender.setParameters(applied);
|
|
1353
|
+
}
|
|
1354
|
+
throw new XmaxError("RTC_ERROR" /* rtcError */, "Browser did not retain WebRTC video sender parameters");
|
|
1355
|
+
}
|
|
1356
|
+
XmaxLogger.rtc.info(() => `Agora \u53D1\u9001\u53C2\u6570\u5B9E\u9A8C (Agora Sender Parameters)
|
|
1357
|
+
${JSON.stringify({
|
|
1358
|
+
capture: { width: capture.width, height: capture.height, frameRate: capture.frameRate },
|
|
1359
|
+
target: { width: config.width, height: config.height, frameRate: config.frameRate },
|
|
1360
|
+
scaleResolutionDownBy: actual.scaleResolutionDownBy,
|
|
1361
|
+
maxFramerate: actual.maxFramerate,
|
|
1362
|
+
maxBitrateKbps: actual.maxBitrate / 1e3,
|
|
1363
|
+
minimumBitrateApplied: false
|
|
1364
|
+
}, null, 2)}`, 2 /* performance */);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1319
1368
|
// src/Foundation/RTC/Agora/AgoraRtcManager.ts
|
|
1320
1369
|
var _AgoraRtcManager = class _AgoraRtcManager {
|
|
1321
1370
|
/**
|
|
@@ -1335,6 +1384,10 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1335
1384
|
__publicField(this, "microphone");
|
|
1336
1385
|
__publicField(this, "externalVideo");
|
|
1337
1386
|
__publicField(this, "externalAudio");
|
|
1387
|
+
__publicField(this, "appliedOptimizationModes", /* @__PURE__ */ new WeakMap());
|
|
1388
|
+
__publicField(this, "cameraSenderConfiguration");
|
|
1389
|
+
__publicField(this, "senderUpdateTail", Promise.resolve());
|
|
1390
|
+
__publicField(this, "cameraTransceiverListener");
|
|
1338
1391
|
__publicField(this, "connection");
|
|
1339
1392
|
__publicField(this, "roomVersion", 0);
|
|
1340
1393
|
/**
|
|
@@ -1351,6 +1404,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1351
1404
|
*/
|
|
1352
1405
|
__publicField(this, "listener");
|
|
1353
1406
|
__publicField(this, "statisticsTimer");
|
|
1407
|
+
__publicField(this, "networkQualitySuspended", false);
|
|
1354
1408
|
__publicField(this, "audioVolumes", /* @__PURE__ */ new Map());
|
|
1355
1409
|
__publicField(this, "requestedAudio", /* @__PURE__ */ new Set());
|
|
1356
1410
|
/**
|
|
@@ -1406,7 +1460,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1406
1460
|
if (typeof client.sendStreamMessage !== "function") {
|
|
1407
1461
|
throw new XmaxError("RTC_ERROR" /* rtcError */, "Agora DataStream is unavailable in this SDK version");
|
|
1408
1462
|
}
|
|
1409
|
-
_AgoraRtcManager.regions.set(sdk, { environment: this.environment, count: (_nullishCoalesce(_optionalChain([region, 'optionalAccess',
|
|
1463
|
+
_AgoraRtcManager.regions.set(sdk, { environment: this.environment, count: (_nullishCoalesce(_optionalChain([region, 'optionalAccess', _86 => _86.count]), () => ( 0))) + 1 });
|
|
1410
1464
|
this.sdk = sdk;
|
|
1411
1465
|
this.client = client;
|
|
1412
1466
|
this.registerEvents(client);
|
|
@@ -1419,11 +1473,12 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1419
1473
|
const client = this.client;
|
|
1420
1474
|
this.clearRoom();
|
|
1421
1475
|
this.client = void 0;
|
|
1422
|
-
_optionalChain([client, 'optionalAccess',
|
|
1423
|
-
|
|
1424
|
-
_optionalChain([this, 'access',
|
|
1425
|
-
_optionalChain([this, 'access',
|
|
1426
|
-
_optionalChain([this, 'access',
|
|
1476
|
+
_optionalChain([client, 'optionalAccess', _87 => _87.removeAllListeners, 'call', _88 => _88()]);
|
|
1477
|
+
this.releaseCameraSender();
|
|
1478
|
+
_optionalChain([this, 'access', _89 => _89.camera, 'optionalAccess', _90 => _90.close, 'call', _91 => _91()]);
|
|
1479
|
+
_optionalChain([this, 'access', _92 => _92.microphone, 'optionalAccess', _93 => _93.close, 'call', _94 => _94()]);
|
|
1480
|
+
_optionalChain([this, 'access', _95 => _95.externalVideo, 'optionalAccess', _96 => _96.close, 'call', _97 => _97()]);
|
|
1481
|
+
_optionalChain([this, 'access', _98 => _98.externalAudio, 'optionalAccess', _99 => _99.close, 'call', _100 => _100()]);
|
|
1427
1482
|
this.externalVideo = void 0;
|
|
1428
1483
|
this.externalAudio = void 0;
|
|
1429
1484
|
this.camera = void 0;
|
|
@@ -1431,7 +1486,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1431
1486
|
const sdk = this.sdk;
|
|
1432
1487
|
this.sdk = void 0;
|
|
1433
1488
|
try {
|
|
1434
|
-
await _optionalChain([client, 'optionalAccess',
|
|
1489
|
+
await _optionalChain([client, 'optionalAccess', _101 => _101.leave, 'call', _102 => _102()]);
|
|
1435
1490
|
} catch (e9) {
|
|
1436
1491
|
XmaxLogger.rtc.warning(() => "Agora \u9000\u623F\u5931\u8D25\uFF0C\u5DF2\u91CA\u653E\u672C\u5730\u8D44\u6E90 (Agora Leave Failed)");
|
|
1437
1492
|
} finally {
|
|
@@ -1458,6 +1513,16 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1458
1513
|
throw this.cancelled();
|
|
1459
1514
|
}
|
|
1460
1515
|
this.camera = camera;
|
|
1516
|
+
this.cameraTransceiverListener = () => {
|
|
1517
|
+
if (this.client === client && client.localTracks.includes(camera) && this.videoPublishRequested && !this.rejoinTask) {
|
|
1518
|
+
void this.restoreCameraSender(camera).catch(() => {
|
|
1519
|
+
if (this.camera === camera && this.videoPublishRequested) {
|
|
1520
|
+
XmaxLogger.rtc.warning(() => "Agora \u53D1\u9001\u53C2\u6570\u6062\u590D\u5931\u8D25 (Agora Sender Parameters Restore Failed)");
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
camera.on("transceiver-updated", this.cameraTransceiverListener);
|
|
1461
1526
|
return camera.getMediaStreamTrack();
|
|
1462
1527
|
} catch (error) {
|
|
1463
1528
|
throw this.mapError(error, "CAMERA_PERMISSION_DENIED" /* cameraPermissionDenied */);
|
|
@@ -1470,6 +1535,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1470
1535
|
const camera = this.requireCamera();
|
|
1471
1536
|
await this.run(() => camera.setDevice({ facingMode: to === "front" /* front */ ? "user" : "environment" }));
|
|
1472
1537
|
if (this.camera !== camera) throw this.cancelled();
|
|
1538
|
+
if (this.videoPublishRequested) await this.restoreCameraSender(camera);
|
|
1473
1539
|
return camera.getMediaStreamTrack();
|
|
1474
1540
|
}
|
|
1475
1541
|
/**
|
|
@@ -1477,8 +1543,9 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1477
1543
|
*/
|
|
1478
1544
|
async stopCameraCapture() {
|
|
1479
1545
|
const camera = this.camera;
|
|
1546
|
+
this.releaseCameraSender();
|
|
1480
1547
|
this.camera = void 0;
|
|
1481
|
-
_optionalChain([camera, 'optionalAccess',
|
|
1548
|
+
_optionalChain([camera, 'optionalAccess', _103 => _103.close, 'call', _104 => _104()]);
|
|
1482
1549
|
}
|
|
1483
1550
|
/**
|
|
1484
1551
|
* 将外部原生轨包装为 Agora 本地轨,不申请设备权限;失败时释放本次克隆。
|
|
@@ -1496,7 +1563,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1496
1563
|
let wrappedVideo;
|
|
1497
1564
|
let wrappedAudio;
|
|
1498
1565
|
try {
|
|
1499
|
-
audio = _optionalChain([tracks, 'access',
|
|
1566
|
+
audio = _optionalChain([tracks, 'access', _105 => _105.audioTrack, 'optionalAccess', _106 => _106.clone, 'call', _107 => _107()]);
|
|
1500
1567
|
wrappedVideo = this.sdk.createCustomVideoTrack({ mediaStreamTrack: video });
|
|
1501
1568
|
if (audio) {
|
|
1502
1569
|
wrappedAudio = this.sdk.createCustomAudioTrack({ mediaStreamTrack: audio, encoderConfig: "music_standard" });
|
|
@@ -1504,19 +1571,34 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1504
1571
|
this.externalVideo = wrappedVideo;
|
|
1505
1572
|
this.externalAudio = wrappedAudio;
|
|
1506
1573
|
} catch (error) {
|
|
1507
|
-
_optionalChain([wrappedVideo, 'optionalAccess',
|
|
1508
|
-
_optionalChain([wrappedAudio, 'optionalAccess',
|
|
1574
|
+
_optionalChain([wrappedVideo, 'optionalAccess', _108 => _108.close, 'call', _109 => _109()]);
|
|
1575
|
+
_optionalChain([wrappedAudio, 'optionalAccess', _110 => _110.close, 'call', _111 => _111()]);
|
|
1509
1576
|
video.stop();
|
|
1510
|
-
_optionalChain([audio, 'optionalAccess',
|
|
1577
|
+
_optionalChain([audio, 'optionalAccess', _112 => _112.stop, 'call', _113 => _113()]);
|
|
1511
1578
|
throw this.mapError(error);
|
|
1512
1579
|
}
|
|
1513
1580
|
}
|
|
1514
1581
|
/**
|
|
1515
|
-
*
|
|
1582
|
+
* 摄像头实验走原生 sender(发布前暂存);外部视频仍走 Agora 编码配置。
|
|
1516
1583
|
*/
|
|
1517
1584
|
async configureVideoEncoding(config) {
|
|
1518
1585
|
const camera = this.requireLocalVideo();
|
|
1519
|
-
|
|
1586
|
+
if (camera === this.camera) {
|
|
1587
|
+
const client = this.requireClient(), version = this.roomVersion;
|
|
1588
|
+
const published = this.videoPublishRequested;
|
|
1589
|
+
await this.run(() => this.queueSenderUpdate(async () => {
|
|
1590
|
+
const ensureActive2 = () => {
|
|
1591
|
+
if (this.camera !== camera || this.client !== client || this.roomVersion !== version || published && !this.videoPublishRequested) throw this.cancelled();
|
|
1592
|
+
};
|
|
1593
|
+
ensureActive2();
|
|
1594
|
+
if (this.videoPublishRequested) {
|
|
1595
|
+
await AgoraVideoSender.apply(camera, { ...config, ...rtcOrientedVideoSize(config) }, ensureActive2);
|
|
1596
|
+
}
|
|
1597
|
+
this.cameraSenderConfiguration = { ...config };
|
|
1598
|
+
}));
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
const encodingSize = config;
|
|
1520
1602
|
await this.run(async () => {
|
|
1521
1603
|
await camera.setEncoderConfiguration({
|
|
1522
1604
|
width: encodingSize.width,
|
|
@@ -1525,14 +1607,42 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1525
1607
|
bitrateMin: config.minimumBitrate,
|
|
1526
1608
|
bitrateMax: config.maximumBitrate
|
|
1527
1609
|
});
|
|
1528
|
-
|
|
1610
|
+
if (this.appliedOptimizationModes.get(camera) !== config.encoderPreference) {
|
|
1611
|
+
await camera.setOptimizationMode(config.encoderPreference === "maintainFramerate" /* maintainFramerate */ ? "motion" : "detail");
|
|
1612
|
+
this.appliedOptimizationModes.set(camera, config.encoderPreference);
|
|
1613
|
+
}
|
|
1529
1614
|
});
|
|
1530
1615
|
}
|
|
1616
|
+
queueSenderUpdate(operation) {
|
|
1617
|
+
const next = this.senderUpdateTail.then(operation);
|
|
1618
|
+
this.senderUpdateTail = next.catch(() => {
|
|
1619
|
+
});
|
|
1620
|
+
return next;
|
|
1621
|
+
}
|
|
1622
|
+
/** 发布/重建 sender 后恢复最近成功的目标配置;排队时不捕获过期的参数对象。 */
|
|
1623
|
+
restoreCameraSender(camera) {
|
|
1624
|
+
const client = this.client, version = this.roomVersion;
|
|
1625
|
+
return this.queueSenderUpdate(async () => {
|
|
1626
|
+
const ensureActive2 = () => {
|
|
1627
|
+
if (this.camera !== camera || this.client !== client || this.roomVersion !== version || !this.videoPublishRequested) {
|
|
1628
|
+
throw this.cancelled();
|
|
1629
|
+
}
|
|
1630
|
+
};
|
|
1631
|
+
ensureActive2();
|
|
1632
|
+
const config = this.cameraSenderConfiguration;
|
|
1633
|
+
if (config) await AgoraVideoSender.apply(camera, { ...config, ...rtcOrientedVideoSize(config) }, ensureActive2);
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
releaseCameraSender() {
|
|
1637
|
+
if (this.cameraTransceiverListener) _optionalChain([this, 'access', _114 => _114.camera, 'optionalAccess', _115 => _115.off, 'call', _116 => _116("transceiver-updated", this.cameraTransceiverListener)]);
|
|
1638
|
+
this.cameraTransceiverListener = void 0;
|
|
1639
|
+
this.cameraSenderConfiguration = void 0;
|
|
1640
|
+
}
|
|
1531
1641
|
/**
|
|
1532
1642
|
* 使用会话下发的字符串频道与 UID 入房;不采信后端区域覆盖。
|
|
1533
1643
|
*/
|
|
1534
1644
|
async joinRoom(configuration) {
|
|
1535
|
-
await _optionalChain([this, 'access',
|
|
1645
|
+
await _optionalChain([this, 'access', _117 => _117.rejoinTask, 'optionalAccess', _118 => _118.catch, 'call', _119 => _119(() => {
|
|
1536
1646
|
})]);
|
|
1537
1647
|
const client = this.requireClient();
|
|
1538
1648
|
if (configuration.provider !== "agora" /* agora */ || this.connection) {
|
|
@@ -1546,7 +1656,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1546
1656
|
}
|
|
1547
1657
|
this.connection = configuration;
|
|
1548
1658
|
for (const user of client.remoteUsers) {
|
|
1549
|
-
if (user.hasVideo) _optionalChain([this, 'access',
|
|
1659
|
+
if (user.hasVideo) _optionalChain([this, 'access', _120 => _120.listener, 'optionalAccess', _121 => _121.onRemoteVideoPublished, 'call', _122 => _122(String(user.uid), true)]);
|
|
1550
1660
|
}
|
|
1551
1661
|
this.statisticsTimer = setInterval(() => {
|
|
1552
1662
|
if (this.client !== client || !this.connection || this.tokenExpired || this.rejoinOperation) return;
|
|
@@ -1568,7 +1678,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1568
1678
|
* 应用同一频道的新 Token;即将过期时续签,已经过期时重新进房并恢复媒体。
|
|
1569
1679
|
*/
|
|
1570
1680
|
async updateCredentials(config, signal) {
|
|
1571
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
1681
|
+
if (_optionalChain([signal, 'optionalAccess', _123 => _123.aborted])) throw this.cancelled();
|
|
1572
1682
|
const current = this.connection;
|
|
1573
1683
|
const client = this.requireClient();
|
|
1574
1684
|
if (!current || config.provider !== "agora" /* agora */ || config.appID !== current.appID || config.roomID !== current.roomID || config.userID !== current.userID) {
|
|
@@ -1584,7 +1694,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1584
1694
|
}
|
|
1585
1695
|
}
|
|
1586
1696
|
this.ensureRoomCurrent(client, version);
|
|
1587
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
1697
|
+
if (_optionalChain([signal, 'optionalAccess', _124 => _124.aborted])) throw this.cancelled();
|
|
1588
1698
|
if (this.tokenExpired) await this.rejoinRoom(client, config, signal);
|
|
1589
1699
|
else this.connection = config;
|
|
1590
1700
|
}
|
|
@@ -1607,21 +1717,21 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1607
1717
|
reject(this.cancelled());
|
|
1608
1718
|
};
|
|
1609
1719
|
this.cancelRejoin = cancel;
|
|
1610
|
-
_optionalChain([signal, 'optionalAccess',
|
|
1720
|
+
_optionalChain([signal, 'optionalAccess', _125 => _125.addEventListener, 'call', _126 => _126("abort", cancel, { once: true })]);
|
|
1611
1721
|
task.then(resolve, reject);
|
|
1612
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
1722
|
+
if (_optionalChain([signal, 'optionalAccess', _127 => _127.aborted])) cancel();
|
|
1613
1723
|
});
|
|
1614
1724
|
this.rejoinOperation = operation;
|
|
1615
1725
|
try {
|
|
1616
1726
|
await operation;
|
|
1617
1727
|
} finally {
|
|
1618
|
-
_optionalChain([signal, 'optionalAccess',
|
|
1728
|
+
_optionalChain([signal, 'optionalAccess', _128 => _128.removeEventListener, 'call', _129 => _129("abort", cancel)]);
|
|
1619
1729
|
if (this.cancelRejoin === cancel) this.cancelRejoin = void 0;
|
|
1620
1730
|
if (this.rejoinOperation === operation) this.rejoinOperation = void 0;
|
|
1621
1731
|
}
|
|
1622
1732
|
this.ensureRoomCurrent(client, version);
|
|
1623
1733
|
for (const user of client.remoteUsers) {
|
|
1624
|
-
if (user.hasVideo) _optionalChain([this, 'access',
|
|
1734
|
+
if (user.hasVideo) _optionalChain([this, 'access', _130 => _130.listener, 'optionalAccess', _131 => _131.onRemoteVideoPublished, 'call', _132 => _132(String(user.uid), true)]);
|
|
1625
1735
|
}
|
|
1626
1736
|
}
|
|
1627
1737
|
/**
|
|
@@ -1629,10 +1739,10 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1629
1739
|
*/
|
|
1630
1740
|
async performRejoin(client, config, version) {
|
|
1631
1741
|
this.ensureRoomCurrent(client, version);
|
|
1632
|
-
_optionalChain([this, 'access',
|
|
1633
|
-
_optionalChain([this, 'access',
|
|
1634
|
-
_optionalChain([this, 'access',
|
|
1635
|
-
for (const user of client.remoteUsers) _optionalChain([user, 'access',
|
|
1742
|
+
_optionalChain([this, 'access', _133 => _133.cancelSendDelay, 'optionalCall', _134 => _134()]);
|
|
1743
|
+
_optionalChain([this, 'access', _135 => _135.cancelActiveSend, 'optionalCall', _136 => _136()]);
|
|
1744
|
+
_optionalChain([this, 'access', _137 => _137.listener, 'optionalAccess', _138 => _138.onRoomRejoining, 'optionalCall', _139 => _139()]);
|
|
1745
|
+
for (const user of client.remoteUsers) _optionalChain([user, 'access', _140 => _140.audioTrack, 'optionalAccess', _141 => _141.stop, 'call', _142 => _142()]);
|
|
1636
1746
|
await this.run(() => client.leave());
|
|
1637
1747
|
this.ensureRoomCurrent(client, version);
|
|
1638
1748
|
await this.run(() => client.join(config.appID, config.roomID, config.roomToken, config.userID));
|
|
@@ -1645,6 +1755,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1645
1755
|
if (this.videoPublishRequested && video) {
|
|
1646
1756
|
await this.run(() => client.publish(video));
|
|
1647
1757
|
this.ensureRoomCurrent(client, version);
|
|
1758
|
+
if (video === this.camera) await this.restoreCameraSender(this.camera);
|
|
1648
1759
|
}
|
|
1649
1760
|
if (this.audioPublishRequested && audio) {
|
|
1650
1761
|
await this.run(() => client.publish(audio));
|
|
@@ -1674,6 +1785,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1674
1785
|
if (client !== this.client || !this.videoPublishRequested) throw this.cancelled();
|
|
1675
1786
|
if (client.localTracks.includes(camera)) return;
|
|
1676
1787
|
await this.run(() => client.publish(camera));
|
|
1788
|
+
if (camera === this.camera) await this.run(() => this.restoreCameraSender(this.camera));
|
|
1677
1789
|
}
|
|
1678
1790
|
/**
|
|
1679
1791
|
* 停止视频发布但保留采集与预览。
|
|
@@ -1754,8 +1866,8 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1754
1866
|
const user = client.remoteUsers.find((user2) => String(user2.uid) === userID);
|
|
1755
1867
|
if (!subscribe) {
|
|
1756
1868
|
this.requestedAudio.delete(userID);
|
|
1757
|
-
_optionalChain([user, 'optionalAccess',
|
|
1758
|
-
if (_optionalChain([user, 'optionalAccess',
|
|
1869
|
+
_optionalChain([user, 'optionalAccess', _143 => _143.audioTrack, 'optionalAccess', _144 => _144.stop, 'call', _145 => _145()]);
|
|
1870
|
+
if (_optionalChain([user, 'optionalAccess', _146 => _146.audioTrack]) && !this.rejoinTask) await this.run(() => client.unsubscribe(user, "audio"));
|
|
1759
1871
|
return;
|
|
1760
1872
|
}
|
|
1761
1873
|
this.requestedAudio.add(userID);
|
|
@@ -1766,7 +1878,7 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1766
1878
|
if (this.requestedAudio.has(userID)) await this.subscribeRemoteAudio(userID, true);
|
|
1767
1879
|
return;
|
|
1768
1880
|
}
|
|
1769
|
-
if (!_optionalChain([user, 'optionalAccess',
|
|
1881
|
+
if (!_optionalChain([user, 'optionalAccess', _147 => _147.hasAudio])) return;
|
|
1770
1882
|
const version = this.roomVersion;
|
|
1771
1883
|
const track = await this.run(() => client.subscribe(user, "audio"));
|
|
1772
1884
|
if (client !== this.client || version !== this.roomVersion || !this.requestedAudio.has(userID)) {
|
|
@@ -1780,9 +1892,9 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1780
1892
|
*/
|
|
1781
1893
|
setRemoteAudioVolume(volume, userID) {
|
|
1782
1894
|
this.audioVolumes.set(userID, Math.max(0, Math.min(100, Number.isFinite(volume) ? Math.round(volume) : 0)));
|
|
1783
|
-
const user = _optionalChain([this, 'access',
|
|
1895
|
+
const user = _optionalChain([this, 'access', _148 => _148.client, 'optionalAccess', _149 => _149.remoteUsers, 'access', _150 => _150.find, 'call', _151 => _151((user2) => String(user2.uid) === userID)]);
|
|
1784
1896
|
if (this.rejoinTask || this.tokenExpired) {
|
|
1785
|
-
_optionalChain([user, 'optionalAccess',
|
|
1897
|
+
_optionalChain([user, 'optionalAccess', _152 => _152.audioTrack, 'optionalAccess', _153 => _153.stop, 'call', _154 => _154()]);
|
|
1786
1898
|
return;
|
|
1787
1899
|
}
|
|
1788
1900
|
if (user) this.applyAudioVolume(user);
|
|
@@ -1871,42 +1983,45 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1871
1983
|
const handleExpired = () => {
|
|
1872
1984
|
if (!active() || this.tokenExpired) return;
|
|
1873
1985
|
this.tokenExpired = true;
|
|
1874
|
-
_optionalChain([this, 'access',
|
|
1986
|
+
_optionalChain([this, 'access', _155 => _155.listener, 'optionalAccess', _156 => _156.onNetworkStatistics, 'optionalCall', _157 => _157(void 0)]);
|
|
1987
|
+
_optionalChain([this, 'access', _158 => _158.listener, 'optionalAccess', _159 => _159.onTokenExpired, 'optionalCall', _160 => _160()]);
|
|
1875
1988
|
};
|
|
1876
1989
|
client.on("user-published", (user, kind) => {
|
|
1877
1990
|
if (!mediaActive()) return;
|
|
1878
|
-
if (kind === "video") _optionalChain([this, 'access',
|
|
1991
|
+
if (kind === "video") _optionalChain([this, 'access', _161 => _161.listener, 'optionalAccess', _162 => _162.onRemoteVideoPublished, 'call', _163 => _163(String(user.uid), true)]);
|
|
1879
1992
|
if (kind === "audio" && this.requestedAudio.has(String(user.uid))) {
|
|
1880
1993
|
void this.subscribeRemoteAudio(String(user.uid), true).catch((error) => {
|
|
1881
|
-
if (active()) _optionalChain([this, 'access',
|
|
1994
|
+
if (active()) _optionalChain([this, 'access', _164 => _164.listener, 'optionalAccess', _165 => _165.onError, 'optionalCall', _166 => _166(this.mapError(error))]);
|
|
1882
1995
|
});
|
|
1883
1996
|
}
|
|
1884
1997
|
});
|
|
1885
1998
|
client.on("user-unpublished", (user, kind) => {
|
|
1886
1999
|
if (!mediaActive()) return;
|
|
1887
|
-
if (kind === "video") _optionalChain([this, 'access',
|
|
1888
|
-
if (kind === "audio") _optionalChain([user, 'access',
|
|
2000
|
+
if (kind === "video") _optionalChain([this, 'access', _167 => _167.listener, 'optionalAccess', _168 => _168.onRemoteVideoPublished, 'call', _169 => _169(String(user.uid), false)]);
|
|
2001
|
+
if (kind === "audio") _optionalChain([user, 'access', _170 => _170.audioTrack, 'optionalAccess', _171 => _171.stop, 'call', _172 => _172()]);
|
|
1889
2002
|
});
|
|
1890
2003
|
client.on("user-left", (user) => {
|
|
1891
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
2004
|
+
if (mediaActive()) _optionalChain([this, 'access', _173 => _173.listener, 'optionalAccess', _174 => _174.onRemoteVideoPublished, 'call', _175 => _175(String(user.uid), false)]);
|
|
1892
2005
|
});
|
|
1893
2006
|
client.on("stream-message", (uid, data) => {
|
|
1894
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
2007
|
+
if (mediaActive()) _optionalChain([this, 'access', _176 => _176.listener, 'optionalAccess', _177 => _177.onCustomMessageReceived, 'call', _178 => _178(String(uid), typeof data === "string" ? data : new TextDecoder().decode(data))]);
|
|
1895
2008
|
});
|
|
1896
2009
|
client.on("network-quality", (quality) => {
|
|
1897
|
-
if (mediaActive()) AgoraRtcStatistics.network(quality, this.listener);
|
|
2010
|
+
if (mediaActive() && !this.networkQualitySuspended) AgoraRtcStatistics.network(quality, this.listener);
|
|
1898
2011
|
});
|
|
1899
2012
|
client.on("token-privilege-will-expire", () => {
|
|
1900
|
-
if (active() && !this.tokenExpired) _optionalChain([this, 'access',
|
|
2013
|
+
if (active() && !this.tokenExpired) _optionalChain([this, 'access', _179 => _179.listener, 'optionalAccess', _180 => _180.onTokenWillExpire, 'optionalCall', _181 => _181()]);
|
|
1901
2014
|
});
|
|
1902
2015
|
client.on("token-privilege-did-expire", handleExpired);
|
|
1903
2016
|
client.on("connection-state-change", (state2, previous, reason) => {
|
|
2017
|
+
if (this.client === client) this.networkQualitySuspended = state2 !== "CONNECTED";
|
|
2018
|
+
if (active() && state2 !== "CONNECTED") _optionalChain([this, 'access', _182 => _182.listener, 'optionalAccess', _183 => _183.onNetworkStatistics, 'optionalCall', _184 => _184(void 0)]);
|
|
1904
2019
|
if (state2 === "DISCONNECTED" && reason === "TOKEN_EXPIRE") {
|
|
1905
2020
|
handleExpired();
|
|
1906
2021
|
return;
|
|
1907
2022
|
}
|
|
1908
2023
|
if (active() && !this.tokenExpired && state2 === "DISCONNECTED" && previous !== "DISCONNECTED") {
|
|
1909
|
-
_optionalChain([this, 'access',
|
|
2024
|
+
_optionalChain([this, 'access', _185 => _185.listener, 'optionalAccess', _186 => _186.onError, 'optionalCall', _187 => _187(new XmaxError("RTC_ERROR" /* rtcError */, `Agora connection disconnected: ${_nullishCoalesce(reason, () => ( "unknown"))}`))]);
|
|
1910
2025
|
}
|
|
1911
2026
|
});
|
|
1912
2027
|
}
|
|
@@ -1915,20 +2030,21 @@ var _AgoraRtcManager = class _AgoraRtcManager {
|
|
|
1915
2030
|
*/
|
|
1916
2031
|
clearRoom() {
|
|
1917
2032
|
this.roomVersion++;
|
|
1918
|
-
_optionalChain([this, 'access',
|
|
2033
|
+
_optionalChain([this, 'access', _188 => _188.cancelRejoin, 'optionalCall', _189 => _189()]);
|
|
1919
2034
|
this.connection = void 0;
|
|
1920
2035
|
this.tokenExpired = false;
|
|
2036
|
+
this.networkQualitySuspended = false;
|
|
1921
2037
|
this.videoPublishRequested = false;
|
|
1922
2038
|
this.audioPublishRequested = false;
|
|
1923
2039
|
clearInterval(this.statisticsTimer);
|
|
1924
2040
|
this.statisticsTimer = void 0;
|
|
1925
|
-
_optionalChain([this, 'access',
|
|
1926
|
-
_optionalChain([this, 'access',
|
|
2041
|
+
_optionalChain([this, 'access', _190 => _190.cancelSendDelay, 'optionalCall', _191 => _191()]);
|
|
2042
|
+
_optionalChain([this, 'access', _192 => _192.cancelActiveSend, 'optionalCall', _193 => _193()]);
|
|
1927
2043
|
this.sentPackets = [];
|
|
1928
2044
|
this.sendTail = Promise.resolve();
|
|
1929
2045
|
this.requestedAudio.clear();
|
|
1930
2046
|
this.audioVolumes.clear();
|
|
1931
|
-
for (const user of _nullishCoalesce(_optionalChain([this, 'access',
|
|
2047
|
+
for (const user of _nullishCoalesce(_optionalChain([this, 'access', _194 => _194.client, 'optionalAccess', _195 => _195.remoteUsers]), () => ( []))) _optionalChain([user, 'access', _196 => _196.audioTrack, 'optionalAccess', _197 => _197.stop, 'call', _198 => _198()]);
|
|
1932
2048
|
}
|
|
1933
2049
|
/**
|
|
1934
2050
|
* 判断异步恢复工作是否仍属于当前房间生命周期。
|
|
@@ -2066,7 +2182,7 @@ var _RtcEngineManager = class _RtcEngineManager {
|
|
|
2066
2182
|
* 释放有效租约、销毁 Engine,并把独占权交给下一个等待者。
|
|
2067
2183
|
*/
|
|
2068
2184
|
release(lease) {
|
|
2069
|
-
if (_optionalChain([this, 'access',
|
|
2185
|
+
if (_optionalChain([this, 'access', _199 => _199.activeLease, 'optionalAccess', _200 => _200.id]) !== lease.id) {
|
|
2070
2186
|
return;
|
|
2071
2187
|
}
|
|
2072
2188
|
this.activeLease = void 0;
|
|
@@ -2140,10 +2256,10 @@ var RtcStatsLogger = class {
|
|
|
2140
2256
|
`${XmaxLogger.localized("\u7D2F\u8BA1\u63A5\u6536\uFF1A", "Bytes Received: ")}${this.value(stats.bytesReceived, "bytes")}`
|
|
2141
2257
|
])];
|
|
2142
2258
|
const local = stats.localStatistics;
|
|
2143
|
-
if (_optionalChain([local, 'optionalAccess',
|
|
2259
|
+
if (_optionalChain([local, 'optionalAccess', _201 => _201.audio])) {
|
|
2144
2260
|
blocks.push(this.audioBlock("\u672C\u5730\u97F3\u9891\u53D1\u9001 (Local Audio Uplink)", local.audio, false));
|
|
2145
2261
|
}
|
|
2146
|
-
for (const video of _nullishCoalesce(_optionalChain([local, 'optionalAccess',
|
|
2262
|
+
for (const video of _nullishCoalesce(_optionalChain([local, 'optionalAccess', _202 => _202.video]), () => ( []))) {
|
|
2147
2263
|
blocks.push(this.videoBlock("\u672C\u5730\u89C6\u9891\u53D1\u9001 (Local Video Uplink)", video, false));
|
|
2148
2264
|
}
|
|
2149
2265
|
for (const remote of _nullishCoalesce(stats.remoteStatistics, () => ( []))) {
|
|
@@ -2233,8 +2349,8 @@ var RtcStatsLogger = class {
|
|
|
2233
2349
|
|
|
2234
2350
|
// src/Foundation/RTC/TRTC/TrtcAudioVolumeSupport.ts
|
|
2235
2351
|
function canControlTrtcRemoteAudioVolume(environment) {
|
|
2236
|
-
const userAgent = _nullishCoalesce(_optionalChain([environment, 'optionalAccess',
|
|
2237
|
-
const maxTouchPoints = _nullishCoalesce(_optionalChain([environment, 'optionalAccess',
|
|
2352
|
+
const userAgent = _nullishCoalesce(_optionalChain([environment, 'optionalAccess', _203 => _203.userAgent]), () => ( (typeof navigator === "undefined" ? "" : navigator.userAgent)));
|
|
2353
|
+
const maxTouchPoints = _nullishCoalesce(_optionalChain([environment, 'optionalAccess', _204 => _204.maxTouchPoints]), () => ( (typeof navigator === "undefined" ? 0 : _nullishCoalesce(navigator.maxTouchPoints, () => ( 0)))));
|
|
2238
2354
|
const ios = /iPhone|iPad|iPod/i.test(userAgent) || /Macintosh/i.test(userAgent) && maxTouchPoints > 1;
|
|
2239
2355
|
return !ios;
|
|
2240
2356
|
}
|
|
@@ -2321,11 +2437,11 @@ var TrtcRtcManager = class {
|
|
|
2321
2437
|
this.isCapturing = false;
|
|
2322
2438
|
this.isAudioCapturing = false;
|
|
2323
2439
|
this.isInRoom = false;
|
|
2324
|
-
_optionalChain([this, 'access',
|
|
2440
|
+
_optionalChain([this, 'access', _205 => _205.removeStatsListeners, 'optionalCall', _206 => _206()]);
|
|
2325
2441
|
this.removeStatsListeners = void 0;
|
|
2326
2442
|
if (!lease) {
|
|
2327
|
-
_optionalChain([externalVideo, 'optionalAccess',
|
|
2328
|
-
_optionalChain([externalAudio, 'optionalAccess',
|
|
2443
|
+
_optionalChain([externalVideo, 'optionalAccess', _207 => _207.stop, 'call', _208 => _208()]);
|
|
2444
|
+
_optionalChain([externalAudio, 'optionalAccess', _209 => _209.stop, 'call', _210 => _210()]);
|
|
2329
2445
|
return;
|
|
2330
2446
|
}
|
|
2331
2447
|
try {
|
|
@@ -2336,8 +2452,8 @@ var TrtcRtcManager = class {
|
|
|
2336
2452
|
await lease.engine.stopLocalVideo();
|
|
2337
2453
|
} catch (e13) {
|
|
2338
2454
|
}
|
|
2339
|
-
_optionalChain([externalVideo, 'optionalAccess',
|
|
2340
|
-
_optionalChain([externalAudio, 'optionalAccess',
|
|
2455
|
+
_optionalChain([externalVideo, 'optionalAccess', _211 => _211.stop, 'call', _212 => _212()]);
|
|
2456
|
+
_optionalChain([externalAudio, 'optionalAccess', _213 => _213.stop, 'call', _214 => _214()]);
|
|
2341
2457
|
this.engineManager.release(lease);
|
|
2342
2458
|
}
|
|
2343
2459
|
/**
|
|
@@ -2355,10 +2471,10 @@ var TrtcRtcManager = class {
|
|
|
2355
2471
|
this.externalVideo = video;
|
|
2356
2472
|
let audio;
|
|
2357
2473
|
try {
|
|
2358
|
-
audio = _optionalChain([tracks, 'access',
|
|
2474
|
+
audio = _optionalChain([tracks, 'access', _215 => _215.audioTrack, 'optionalAccess', _216 => _216.clone, 'call', _217 => _217()]);
|
|
2359
2475
|
this.externalAudio = audio;
|
|
2360
2476
|
await engine.startLocalVideo({ publish: false, option: { videoTrack: video } });
|
|
2361
|
-
if (_optionalChain([this, 'access',
|
|
2477
|
+
if (_optionalChain([this, 'access', _218 => _218.lease, 'optionalAccess', _219 => _219.engine]) !== engine) {
|
|
2362
2478
|
throw new XmaxError("CANCELLED" /* cancelled */, "External media preparation was cancelled");
|
|
2363
2479
|
}
|
|
2364
2480
|
if (audio) {
|
|
@@ -2366,12 +2482,12 @@ var TrtcRtcManager = class {
|
|
|
2366
2482
|
publish: false,
|
|
2367
2483
|
option: { audioTrack: audio, echoCancellation: false, autoGainControl: false, noiseSuppression: false }
|
|
2368
2484
|
});
|
|
2369
|
-
if (_optionalChain([this, 'access',
|
|
2485
|
+
if (_optionalChain([this, 'access', _220 => _220.lease, 'optionalAccess', _221 => _221.engine]) !== engine) {
|
|
2370
2486
|
throw new XmaxError("CANCELLED" /* cancelled */, "External media preparation was cancelled");
|
|
2371
2487
|
}
|
|
2372
2488
|
}
|
|
2373
2489
|
} catch (error) {
|
|
2374
|
-
if (_optionalChain([this, 'access',
|
|
2490
|
+
if (_optionalChain([this, 'access', _222 => _222.lease, 'optionalAccess', _223 => _223.engine]) === engine) {
|
|
2375
2491
|
await engine.stopLocalAudio().catch(() => {
|
|
2376
2492
|
});
|
|
2377
2493
|
await engine.stopLocalVideo().catch(() => {
|
|
@@ -2382,7 +2498,7 @@ var TrtcRtcManager = class {
|
|
|
2382
2498
|
this.externalAudio = void 0;
|
|
2383
2499
|
}
|
|
2384
2500
|
video.stop();
|
|
2385
|
-
_optionalChain([audio, 'optionalAccess',
|
|
2501
|
+
_optionalChain([audio, 'optionalAccess', _224 => _224.stop, 'call', _225 => _225()]);
|
|
2386
2502
|
throw this.mapError(error);
|
|
2387
2503
|
}
|
|
2388
2504
|
}
|
|
@@ -2467,7 +2583,7 @@ var TrtcRtcManager = class {
|
|
|
2467
2583
|
if (this.externalVideo) {
|
|
2468
2584
|
return;
|
|
2469
2585
|
}
|
|
2470
|
-
const engine = _optionalChain([this, 'access',
|
|
2586
|
+
const engine = _optionalChain([this, 'access', _226 => _226.lease, 'optionalAccess', _227 => _227.engine]);
|
|
2471
2587
|
this.isCapturing = false;
|
|
2472
2588
|
if (!engine) {
|
|
2473
2589
|
return;
|
|
@@ -2520,7 +2636,7 @@ var TrtcRtcManager = class {
|
|
|
2520
2636
|
* 离开当前 RTC 房间;未在房间中或引擎未初始化时不产生效果,退房失败仅记录日志。
|
|
2521
2637
|
*/
|
|
2522
2638
|
async leaveRoom() {
|
|
2523
|
-
const engine = _optionalChain([this, 'access',
|
|
2639
|
+
const engine = _optionalChain([this, 'access', _228 => _228.lease, 'optionalAccess', _229 => _229.engine]);
|
|
2524
2640
|
if (!engine || !this.isInRoom) {
|
|
2525
2641
|
return;
|
|
2526
2642
|
}
|
|
@@ -2593,7 +2709,7 @@ var TrtcRtcManager = class {
|
|
|
2593
2709
|
* 停止发布本地视频流;采集保持运行,本地预览不受影响。
|
|
2594
2710
|
*/
|
|
2595
2711
|
async unpublishLocalVideo() {
|
|
2596
|
-
const engine = _optionalChain([this, 'access',
|
|
2712
|
+
const engine = _optionalChain([this, 'access', _230 => _230.lease, 'optionalAccess', _231 => _231.engine]);
|
|
2597
2713
|
if (!engine || !this.isCapturing && !this.externalVideo) {
|
|
2598
2714
|
return;
|
|
2599
2715
|
}
|
|
@@ -2629,7 +2745,7 @@ var TrtcRtcManager = class {
|
|
|
2629
2745
|
* 停止发布本地音频流;麦克风采集保持运行。
|
|
2630
2746
|
*/
|
|
2631
2747
|
async unpublishLocalAudio() {
|
|
2632
|
-
const engine = _optionalChain([this, 'access',
|
|
2748
|
+
const engine = _optionalChain([this, 'access', _232 => _232.lease, 'optionalAccess', _233 => _233.engine]);
|
|
2633
2749
|
if (!engine || !this.isAudioCapturing && !this.externalAudio) {
|
|
2634
2750
|
return;
|
|
2635
2751
|
}
|
|
@@ -2755,19 +2871,19 @@ var TrtcRtcManager = class {
|
|
|
2755
2871
|
registerEventBridge(engine) {
|
|
2756
2872
|
const source = engine;
|
|
2757
2873
|
const onStatistics = (stats) => {
|
|
2758
|
-
if (this.isInRoom && _optionalChain([this, 'access',
|
|
2874
|
+
if (this.isInRoom && _optionalChain([this, 'access', _234 => _234.lease, 'optionalAccess', _235 => _235.engine]) === engine) {
|
|
2759
2875
|
RtcStatsLogger.logStatistics(stats);
|
|
2760
|
-
const video = _optionalChain([stats, 'access',
|
|
2876
|
+
const video = _optionalChain([stats, 'access', _236 => _236.localStatistics, 'optionalAccess', _237 => _237.video, 'optionalAccess', _238 => _238.find, 'call', _239 => _239((item) => item.videoType === "big")]);
|
|
2761
2877
|
const valid = (value, minimum) => typeof value === "number" && Number.isFinite(value) && value >= minimum ? value : void 0;
|
|
2762
|
-
_optionalChain([this, 'access',
|
|
2878
|
+
_optionalChain([this, 'access', _240 => _240.eventListener, 'optionalAccess', _241 => _241.onLocalVideoStatistics, 'optionalCall', _242 => _242(video ? Object.freeze({
|
|
2763
2879
|
width: valid(video.width, 1),
|
|
2764
2880
|
height: valid(video.height, 1),
|
|
2765
2881
|
frameRate: valid(video.frameRate, 0),
|
|
2766
2882
|
bitrateKbps: valid(video.bitrate, 0)
|
|
2767
2883
|
}) : void 0)]);
|
|
2768
|
-
_optionalChain([this, 'access',
|
|
2884
|
+
_optionalChain([this, 'access', _243 => _243.eventListener, 'optionalAccess', _244 => _244.onRemoteVideoStatistics, 'optionalCall', _245 => _245(Object.freeze(
|
|
2769
2885
|
(_nullishCoalesce(stats.remoteStatistics, () => ( []))).flatMap((remote) => {
|
|
2770
|
-
const video2 = _optionalChain([remote, 'access',
|
|
2886
|
+
const video2 = _optionalChain([remote, 'access', _246 => _246.video, 'optionalAccess', _247 => _247.find, 'call', _248 => _248((item) => item.videoType === "big")]);
|
|
2771
2887
|
if (!video2) {
|
|
2772
2888
|
return [];
|
|
2773
2889
|
}
|
|
@@ -2789,11 +2905,11 @@ var TrtcRtcManager = class {
|
|
|
2789
2905
|
}
|
|
2790
2906
|
};
|
|
2791
2907
|
const onNetworkQuality = (stats) => {
|
|
2792
|
-
if (this.isInRoom && _optionalChain([this, 'access',
|
|
2908
|
+
if (this.isInRoom && _optionalChain([this, 'access', _249 => _249.lease, 'optionalAccess', _250 => _250.engine]) === engine) {
|
|
2793
2909
|
RtcStatsLogger.logNetworkQuality(stats);
|
|
2794
2910
|
const quality = (value) => Number.isInteger(value) && value >= 0 && value <= 6 ? value : void 0;
|
|
2795
2911
|
const rtt = (value) => Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
2796
|
-
_optionalChain([this, 'access',
|
|
2912
|
+
_optionalChain([this, 'access', _251 => _251.eventListener, 'optionalAccess', _252 => _252.onNetworkStatistics, 'optionalCall', _253 => _253(Object.freeze({
|
|
2797
2913
|
uplinkQuality: quality(stats.uplinkNetworkQuality),
|
|
2798
2914
|
downlinkQuality: quality(stats.downlinkNetworkQuality),
|
|
2799
2915
|
uplinkRttMs: rtt(stats.uplinkRTT),
|
|
@@ -2808,19 +2924,19 @@ var TrtcRtcManager = class {
|
|
|
2808
2924
|
source.off(RTC_EVENT.networkQuality, onNetworkQuality);
|
|
2809
2925
|
};
|
|
2810
2926
|
source.on(RTC_EVENT.remoteVideoAvailable, (event) => {
|
|
2811
|
-
if (_optionalChain([this, 'access',
|
|
2927
|
+
if (_optionalChain([this, 'access', _254 => _254.lease, 'optionalAccess', _255 => _255.engine]) !== engine || event.streamType !== STREAM_TYPE_MAIN) {
|
|
2812
2928
|
return;
|
|
2813
2929
|
}
|
|
2814
|
-
_optionalChain([this, 'access',
|
|
2930
|
+
_optionalChain([this, 'access', _256 => _256.eventListener, 'optionalAccess', _257 => _257.onRemoteVideoPublished, 'call', _258 => _258(event.userId, true)]);
|
|
2815
2931
|
});
|
|
2816
2932
|
source.on(RTC_EVENT.remoteVideoUnavailable, (event) => {
|
|
2817
|
-
if (_optionalChain([this, 'access',
|
|
2933
|
+
if (_optionalChain([this, 'access', _259 => _259.lease, 'optionalAccess', _260 => _260.engine]) !== engine || event.streamType !== STREAM_TYPE_MAIN) {
|
|
2818
2934
|
return;
|
|
2819
2935
|
}
|
|
2820
|
-
_optionalChain([this, 'access',
|
|
2936
|
+
_optionalChain([this, 'access', _261 => _261.eventListener, 'optionalAccess', _262 => _262.onRemoteVideoPublished, 'call', _263 => _263(event.userId, false)]);
|
|
2821
2937
|
});
|
|
2822
2938
|
source.on(RTC_EVENT.customMessage, (event) => {
|
|
2823
|
-
if (_optionalChain([this, 'access',
|
|
2939
|
+
if (_optionalChain([this, 'access', _264 => _264.lease, 'optionalAccess', _265 => _265.engine]) !== engine || event.cmdId !== CUSTOM_MESSAGE_CMD_ID) {
|
|
2824
2940
|
return;
|
|
2825
2941
|
}
|
|
2826
2942
|
let message;
|
|
@@ -2830,14 +2946,14 @@ var TrtcRtcManager = class {
|
|
|
2830
2946
|
XmaxLogger.rtc.warning(() => "\u81EA\u5B9A\u4E49\u6D88\u606F\u89E3\u7801\u5931\u8D25 (Failed to Decode Custom Message)");
|
|
2831
2947
|
return;
|
|
2832
2948
|
}
|
|
2833
|
-
_optionalChain([this, 'access',
|
|
2949
|
+
_optionalChain([this, 'access', _266 => _266.eventListener, 'optionalAccess', _267 => _267.onCustomMessageReceived, 'call', _268 => _268(event.userId, message)]);
|
|
2834
2950
|
});
|
|
2835
2951
|
}
|
|
2836
2952
|
/**
|
|
2837
2953
|
* 返回当前引擎实例;未初始化时抛出错误。
|
|
2838
2954
|
*/
|
|
2839
2955
|
requireEngine() {
|
|
2840
|
-
const engine = _optionalChain([this, 'access',
|
|
2956
|
+
const engine = _optionalChain([this, 'access', _269 => _269.lease, 'optionalAccess', _270 => _270.engine]);
|
|
2841
2957
|
if (!engine) {
|
|
2842
2958
|
throw new XmaxError(
|
|
2843
2959
|
"RTC_ERROR" /* rtcError */,
|
|
@@ -2854,8 +2970,8 @@ var TrtcRtcManager = class {
|
|
|
2854
2970
|
return error;
|
|
2855
2971
|
}
|
|
2856
2972
|
const rtcError = error;
|
|
2857
|
-
const originName = _nullishCoalesce(_optionalChain([rtcError, 'optionalAccess',
|
|
2858
|
-
const message = typeof _optionalChain([rtcError, 'optionalAccess',
|
|
2973
|
+
const originName = _nullishCoalesce(_optionalChain([rtcError, 'optionalAccess', _271 => _271.originError, 'optionalAccess', _272 => _272.name]), () => ( ""));
|
|
2974
|
+
const message = typeof _optionalChain([rtcError, 'optionalAccess', _273 => _273.message]) === "string" && rtcError.message.trim().length > 0 ? rtcError.message.trim() : String(error);
|
|
2859
2975
|
if (originName === "NotAllowedError" || originName === "SecurityError" || /NotAllowed/i.test(message)) {
|
|
2860
2976
|
return new XmaxError("CAMERA_PERMISSION_DENIED" /* cameraPermissionDenied */, message);
|
|
2861
2977
|
}
|
|
@@ -2978,12 +3094,12 @@ var VeRtcManager = class {
|
|
|
2978
3094
|
this.sdk = void 0;
|
|
2979
3095
|
this.camera = void 0;
|
|
2980
3096
|
this.microphone = false;
|
|
2981
|
-
_optionalChain([engine, 'optionalAccess',
|
|
3097
|
+
_optionalChain([engine, 'optionalAccess', _274 => _274.removeAllListeners, 'call', _275 => _275()]);
|
|
2982
3098
|
try {
|
|
2983
3099
|
if (engine && sdk) sdk.default.destroyEngine(engine);
|
|
2984
3100
|
} finally {
|
|
2985
|
-
_optionalChain([this, 'access',
|
|
2986
|
-
_optionalChain([this, 'access',
|
|
3101
|
+
_optionalChain([this, 'access', _276 => _276.externalVideo, 'optionalAccess', _277 => _277.stop, 'call', _278 => _278()]);
|
|
3102
|
+
_optionalChain([this, 'access', _279 => _279.externalAudio, 'optionalAccess', _280 => _280.stop, 'call', _281 => _281()]);
|
|
2987
3103
|
this.externalVideo = void 0;
|
|
2988
3104
|
this.externalAudio = void 0;
|
|
2989
3105
|
}
|
|
@@ -3010,7 +3126,7 @@ var VeRtcManager = class {
|
|
|
3010
3126
|
}
|
|
3011
3127
|
};
|
|
3012
3128
|
try {
|
|
3013
|
-
audio = _optionalChain([tracks, 'access',
|
|
3129
|
+
audio = _optionalChain([tracks, 'access', _282 => _282.audioTrack, 'optionalAccess', _283 => _283.clone, 'call', _284 => _284()]);
|
|
3014
3130
|
this.externalAudio = audio;
|
|
3015
3131
|
await engine.setVideoSourceType(index, sdk.VideoSourceType.VIDEO_SOURCE_TYPE_EXTERNAL);
|
|
3016
3132
|
ensureCurrent();
|
|
@@ -3034,7 +3150,7 @@ var VeRtcManager = class {
|
|
|
3034
3150
|
this.externalAudio = void 0;
|
|
3035
3151
|
}
|
|
3036
3152
|
video.stop();
|
|
3037
|
-
_optionalChain([audio, 'optionalAccess',
|
|
3153
|
+
_optionalChain([audio, 'optionalAccess', _285 => _285.stop, 'call', _286 => _286()]);
|
|
3038
3154
|
throw this.mapError(error);
|
|
3039
3155
|
}
|
|
3040
3156
|
}
|
|
@@ -3103,9 +3219,9 @@ var VeRtcManager = class {
|
|
|
3103
3219
|
}));
|
|
3104
3220
|
}
|
|
3105
3221
|
async joinRoom(config) {
|
|
3106
|
-
await _optionalChain([this, 'access',
|
|
3222
|
+
await _optionalChain([this, 'access', _287 => _287.joining, 'optionalAccess', _288 => _288.catch, 'call', _289 => _289(() => {
|
|
3107
3223
|
})]);
|
|
3108
|
-
await _optionalChain([this, 'access',
|
|
3224
|
+
await _optionalChain([this, 'access', _290 => _290.recovery, 'optionalAccess', _291 => _291.catch, 'call', _292 => _292(() => {
|
|
3109
3225
|
})]);
|
|
3110
3226
|
const engine = this.requireEngine();
|
|
3111
3227
|
if (config.provider !== "vertc" /* vertc */ || config.appID !== VERTC_APP_ID || this.connection) {
|
|
@@ -3154,7 +3270,7 @@ var VeRtcManager = class {
|
|
|
3154
3270
|
async updateCredentials(config, signal) {
|
|
3155
3271
|
const engine = this.requireEngine();
|
|
3156
3272
|
const current = this.connection;
|
|
3157
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
3273
|
+
if (_optionalChain([signal, 'optionalAccess', _293 => _293.aborted])) throw this.cancelled();
|
|
3158
3274
|
if (!current || config.provider !== "vertc" /* vertc */ || config.appID !== current.appID || config.roomID !== current.roomID || config.userID !== current.userID) {
|
|
3159
3275
|
throw new XmaxError("SESSION_ERROR" /* sessionError */, "VeRTC session binding changed");
|
|
3160
3276
|
}
|
|
@@ -3182,7 +3298,7 @@ var VeRtcManager = class {
|
|
|
3182
3298
|
const restore = this.tokenExpired || this.publishPrivilegeExpired || this.subscribePrivilegeExpired;
|
|
3183
3299
|
if (restore) {
|
|
3184
3300
|
this.joined = false;
|
|
3185
|
-
_optionalChain([this, 'access',
|
|
3301
|
+
_optionalChain([this, 'access', _294 => _294.listener, 'optionalAccess', _295 => _295.onRoomRejoining, 'optionalCall', _296 => _296()]);
|
|
3186
3302
|
this.clearPlayers();
|
|
3187
3303
|
this.clearStatistics();
|
|
3188
3304
|
if (this.tokenExpired) {
|
|
@@ -3353,13 +3469,13 @@ var VeRtcManager = class {
|
|
|
3353
3469
|
if (!active()) return;
|
|
3354
3470
|
if (video(mediaType)) {
|
|
3355
3471
|
this.publishedVideo.add(userId);
|
|
3356
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
3472
|
+
if (mediaActive()) _optionalChain([this, 'access', _297 => _297.listener, 'optionalAccess', _298 => _298.onRemoteVideoPublished, 'call', _299 => _299(userId, true)]);
|
|
3357
3473
|
}
|
|
3358
3474
|
if (audio(mediaType)) {
|
|
3359
3475
|
this.publishedAudio.add(userId);
|
|
3360
3476
|
if (mediaActive() && this.requestedAudio.has(userId)) {
|
|
3361
3477
|
void this.subscribeRemoteAudio(userId, true).catch((error) => {
|
|
3362
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
3478
|
+
if (mediaActive()) _optionalChain([this, 'access', _300 => _300.listener, 'optionalAccess', _301 => _301.onError, 'optionalCall', _302 => _302(this.mapError(error))]);
|
|
3363
3479
|
});
|
|
3364
3480
|
}
|
|
3365
3481
|
}
|
|
@@ -3379,10 +3495,10 @@ var VeRtcManager = class {
|
|
|
3379
3495
|
this.clearPlayer(userInfo.userId);
|
|
3380
3496
|
});
|
|
3381
3497
|
engine.on(events.onRoomMessageReceived, ({ userId, message }) => {
|
|
3382
|
-
if (mediaActive() && typeof message === "string") _optionalChain([this, 'access',
|
|
3498
|
+
if (mediaActive() && typeof message === "string") _optionalChain([this, 'access', _303 => _303.listener, 'optionalAccess', _304 => _304.onCustomMessageReceived, 'call', _305 => _305(userId, message)]);
|
|
3383
3499
|
});
|
|
3384
3500
|
const willExpire = () => {
|
|
3385
|
-
if (active()) _optionalChain([this, 'access',
|
|
3501
|
+
if (active()) _optionalChain([this, 'access', _306 => _306.listener, 'optionalAccess', _307 => _307.onTokenWillExpire, 'optionalCall', _308 => _308()]);
|
|
3386
3502
|
};
|
|
3387
3503
|
engine.on(events.onTokenWillExpire, willExpire);
|
|
3388
3504
|
engine.on(events.onTokenPublishPrivilegeWillExpire, willExpire);
|
|
@@ -3390,13 +3506,13 @@ var VeRtcManager = class {
|
|
|
3390
3506
|
engine.on(events.onTokenPublishPrivilegeDidExpired, () => {
|
|
3391
3507
|
if (!active() || this.publishPrivilegeExpired) return;
|
|
3392
3508
|
this.publishPrivilegeExpired = true;
|
|
3393
|
-
_optionalChain([this, 'access',
|
|
3509
|
+
_optionalChain([this, 'access', _309 => _309.listener, 'optionalAccess', _310 => _310.onTokenExpired, 'optionalCall', _311 => _311()]);
|
|
3394
3510
|
});
|
|
3395
3511
|
engine.on(events.onTokenSubscribePrivilegeDidExpired, () => {
|
|
3396
3512
|
if (!active() || this.subscribePrivilegeExpired) return;
|
|
3397
3513
|
this.subscribePrivilegeExpired = true;
|
|
3398
3514
|
this.clearPlayers();
|
|
3399
|
-
_optionalChain([this, 'access',
|
|
3515
|
+
_optionalChain([this, 'access', _312 => _312.listener, 'optionalAccess', _313 => _313.onTokenExpired, 'optionalCall', _314 => _314()]);
|
|
3400
3516
|
});
|
|
3401
3517
|
engine.on(events.onError, ({ errorCode }) => {
|
|
3402
3518
|
if (!active()) return;
|
|
@@ -3404,23 +3520,23 @@ var VeRtcManager = class {
|
|
|
3404
3520
|
if (this.tokenExpired) return;
|
|
3405
3521
|
this.tokenExpired = true;
|
|
3406
3522
|
this.clearPlayers();
|
|
3407
|
-
_optionalChain([this, 'access',
|
|
3408
|
-
} else _optionalChain([this, 'access',
|
|
3523
|
+
_optionalChain([this, 'access', _315 => _315.listener, 'optionalAccess', _316 => _316.onTokenExpired, 'optionalCall', _317 => _317()]);
|
|
3524
|
+
} else _optionalChain([this, 'access', _318 => _318.listener, 'optionalAccess', _319 => _319.onError, 'optionalCall', _320 => _320(this.mapError({ code: errorCode }))]);
|
|
3409
3525
|
});
|
|
3410
3526
|
engine.on(events.onConnectionStateChanged, ({ state: state2 }) => {
|
|
3411
3527
|
if (!mediaActive() || state2 !== this.sdk.ConnectionState.CONNECTION_STATE_RECONNECTED) return;
|
|
3412
|
-
_optionalChain([this, 'access',
|
|
3528
|
+
_optionalChain([this, 'access', _321 => _321.listener, 'optionalAccess', _322 => _322.onRoomRejoining, 'optionalCall', _323 => _323()]);
|
|
3413
3529
|
this.clearPlayers();
|
|
3414
3530
|
this.clearStatistics();
|
|
3415
3531
|
this.replayVideo();
|
|
3416
3532
|
for (const userID of this.requestedAudio) {
|
|
3417
3533
|
void this.subscribeRemoteAudio(userID, true).catch((error) => {
|
|
3418
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
3534
|
+
if (mediaActive()) _optionalChain([this, 'access', _324 => _324.listener, 'optionalAccess', _325 => _325.onError, 'optionalCall', _326 => _326(this.mapError(error))]);
|
|
3419
3535
|
});
|
|
3420
3536
|
}
|
|
3421
3537
|
});
|
|
3422
3538
|
engine.on(events.onNetworkQuality, (up, down) => {
|
|
3423
|
-
if (mediaActive()) _optionalChain([this, 'access',
|
|
3539
|
+
if (mediaActive()) _optionalChain([this, 'access', _327 => _327.listener, 'optionalAccess', _328 => _328.onNetworkStatistics, 'optionalCall', _329 => _329(Object.freeze({
|
|
3424
3540
|
uplinkQuality: VeRtcStatistics.quality(up),
|
|
3425
3541
|
downlinkQuality: VeRtcStatistics.quality(down)
|
|
3426
3542
|
}))]);
|
|
@@ -3429,7 +3545,7 @@ var VeRtcManager = class {
|
|
|
3429
3545
|
if (!mediaActive() || stats.isScreen || !this.videoRequested) return;
|
|
3430
3546
|
const result = VeRtcStatistics.local(stats.videoStats);
|
|
3431
3547
|
this.uplinkLossPercent = result.uplinkLossPercent;
|
|
3432
|
-
_optionalChain([this, 'access',
|
|
3548
|
+
_optionalChain([this, 'access', _330 => _330.listener, 'optionalAccess', _331 => _331.onLocalVideoStatistics, 'optionalCall', _332 => _332(result)]);
|
|
3433
3549
|
XmaxLogger.rtc.info(() => `VeRTC local video statistics: ${JSON.stringify(result)}`, 2 /* performance */);
|
|
3434
3550
|
});
|
|
3435
3551
|
engine.on(events.onRemoteStreamStats, (stats) => {
|
|
@@ -3439,21 +3555,21 @@ var VeRtcManager = class {
|
|
|
3439
3555
|
});
|
|
3440
3556
|
}
|
|
3441
3557
|
replayVideo() {
|
|
3442
|
-
for (const userID of this.publishedVideo) _optionalChain([this, 'access',
|
|
3558
|
+
for (const userID of this.publishedVideo) _optionalChain([this, 'access', _333 => _333.listener, 'optionalAccess', _334 => _334.onRemoteVideoPublished, 'call', _335 => _335(userID, true)]);
|
|
3443
3559
|
}
|
|
3444
3560
|
removeVideo(userID) {
|
|
3445
3561
|
this.publishedVideo.delete(userID);
|
|
3446
3562
|
this.remoteStatistics.delete(userID);
|
|
3447
3563
|
this.emitRemoteStatistics();
|
|
3448
|
-
if (this.joined && !this.tokenExpired) _optionalChain([this, 'access',
|
|
3564
|
+
if (this.joined && !this.tokenExpired) _optionalChain([this, 'access', _336 => _336.listener, 'optionalAccess', _337 => _337.onRemoteVideoPublished, 'call', _338 => _338(userID, false)]);
|
|
3449
3565
|
}
|
|
3450
3566
|
emitRemoteStatistics() {
|
|
3451
|
-
_optionalChain([this, 'access',
|
|
3567
|
+
_optionalChain([this, 'access', _339 => _339.listener, 'optionalAccess', _340 => _340.onRemoteVideoStatistics, 'optionalCall', _341 => _341(Object.freeze([...this.remoteStatistics.values()]))]);
|
|
3452
3568
|
}
|
|
3453
3569
|
clearStatistics() {
|
|
3454
3570
|
this.remoteStatistics.clear();
|
|
3455
3571
|
this.uplinkLossPercent = void 0;
|
|
3456
|
-
_optionalChain([this, 'access',
|
|
3572
|
+
_optionalChain([this, 'access', _342 => _342.listener, 'optionalAccess', _343 => _343.onLocalVideoStatistics, 'optionalCall', _344 => _344(void 0)]);
|
|
3457
3573
|
this.emitRemoteStatistics();
|
|
3458
3574
|
}
|
|
3459
3575
|
clearPlayer(userID) {
|
|
@@ -3499,15 +3615,15 @@ var VeRtcManager = class {
|
|
|
3499
3615
|
const cleanup = () => {
|
|
3500
3616
|
clearTimeout(timer);
|
|
3501
3617
|
roomSignal.removeEventListener("abort", cancel);
|
|
3502
|
-
_optionalChain([signal, 'optionalAccess',
|
|
3618
|
+
_optionalChain([signal, 'optionalAccess', _345 => _345.removeEventListener, 'call', _346 => _346("abort", cancel)]);
|
|
3503
3619
|
};
|
|
3504
3620
|
const cancel = () => {
|
|
3505
|
-
if (_optionalChain([signal, 'optionalAccess',
|
|
3621
|
+
if (_optionalChain([signal, 'optionalAccess', _347 => _347.aborted]) && !roomSignal.aborted) this.roomVersion++;
|
|
3506
3622
|
cleanup();
|
|
3507
3623
|
reject(this.cancelled());
|
|
3508
3624
|
};
|
|
3509
3625
|
roomSignal.addEventListener("abort", cancel, { once: true });
|
|
3510
|
-
_optionalChain([signal, 'optionalAccess',
|
|
3626
|
+
_optionalChain([signal, 'optionalAccess', _348 => _348.addEventListener, 'call', _349 => _349("abort", cancel, { once: true })]);
|
|
3511
3627
|
task.then((value) => {
|
|
3512
3628
|
cleanup();
|
|
3513
3629
|
resolve(value);
|
|
@@ -3515,7 +3631,7 @@ var VeRtcManager = class {
|
|
|
3515
3631
|
cleanup();
|
|
3516
3632
|
reject(error);
|
|
3517
3633
|
});
|
|
3518
|
-
if (roomSignal.aborted || _optionalChain([signal, 'optionalAccess',
|
|
3634
|
+
if (roomSignal.aborted || _optionalChain([signal, 'optionalAccess', _350 => _350.aborted])) cancel();
|
|
3519
3635
|
});
|
|
3520
3636
|
}
|
|
3521
3637
|
isCurrent(engine, version) {
|
|
@@ -3551,8 +3667,8 @@ var VeRtcManager = class {
|
|
|
3551
3667
|
mapError(error, permissionCode) {
|
|
3552
3668
|
if (error instanceof XmaxError) return error;
|
|
3553
3669
|
const value = error;
|
|
3554
|
-
const code = typeof _optionalChain([value, 'optionalAccess',
|
|
3555
|
-
const denied = _optionalChain([value, 'optionalAccess',
|
|
3670
|
+
const code = typeof _optionalChain([value, 'optionalAccess', _351 => _351.code]) === "string" && /^[A-Z_0-9-]{1,64}$/.test(value.code) ? value.code : "UNKNOWN";
|
|
3671
|
+
const denied = _optionalChain([value, 'optionalAccess', _352 => _352.name]) === "NotAllowedError" || code === "PERMISSION_DENIED" || code === "DEVICE_PERMISSION_DENIED";
|
|
3556
3672
|
return new XmaxError(permissionCode && denied ? permissionCode : "RTC_ERROR" /* rtcError */, `VeRTC operation failed (${code})`);
|
|
3557
3673
|
}
|
|
3558
3674
|
cancelled() {
|
|
@@ -3634,7 +3750,7 @@ var PermissionManager = class {
|
|
|
3634
3750
|
* @param deniedCode 权限被拒绝时抛出的错误码。
|
|
3635
3751
|
*/
|
|
3636
3752
|
async ensurePermission(name, deniedCode) {
|
|
3637
|
-
if (typeof navigator === "undefined" || !_optionalChain([navigator, 'access',
|
|
3753
|
+
if (typeof navigator === "undefined" || !_optionalChain([navigator, 'access', _353 => _353.mediaDevices, 'optionalAccess', _354 => _354.getUserMedia])) {
|
|
3638
3754
|
throw new XmaxError(
|
|
3639
3755
|
deniedCode,
|
|
3640
3756
|
"This browser does not support media capture (getUserMedia)"
|
|
@@ -3642,7 +3758,7 @@ var PermissionManager = class {
|
|
|
3642
3758
|
}
|
|
3643
3759
|
try {
|
|
3644
3760
|
const permissions = navigator.permissions;
|
|
3645
|
-
if (!_optionalChain([permissions, 'optionalAccess',
|
|
3761
|
+
if (!_optionalChain([permissions, 'optionalAccess', _355 => _355.query])) {
|
|
3646
3762
|
return;
|
|
3647
3763
|
}
|
|
3648
3764
|
const status = await permissions.query({
|
|
@@ -3822,10 +3938,10 @@ var _CameraController = class _CameraController {
|
|
|
3822
3938
|
*/
|
|
3823
3939
|
__publicField(this, "storedUseMicrophone", false);
|
|
3824
3940
|
__publicField(this, "storedFrameValidationEnabled", true);
|
|
3825
|
-
this.permissionManager = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
3826
|
-
this.rtcManager = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
3827
|
-
this.mediaService = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
3828
|
-
this.errorListener = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
3941
|
+
this.permissionManager = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _356 => _356.permissionManager]), () => ( new PermissionManager()));
|
|
3942
|
+
this.rtcManager = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _357 => _357.rtcManager]), () => ( new TrtcRtcManager()));
|
|
3943
|
+
this.mediaService = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _358 => _358.mediaService]), () => ( new MediaService()));
|
|
3944
|
+
this.errorListener = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _359 => _359.errorListener]), () => ( (() => {
|
|
3829
3945
|
})));
|
|
3830
3946
|
}
|
|
3831
3947
|
/**
|
|
@@ -3851,7 +3967,7 @@ var _CameraController = class _CameraController {
|
|
|
3851
3967
|
*/
|
|
3852
3968
|
async waitForValidCameraFrame(signal) {
|
|
3853
3969
|
const track = this.activeTrack;
|
|
3854
|
-
const mediaTrack = _optionalChain([track, 'optionalAccess',
|
|
3970
|
+
const mediaTrack = _optionalChain([track, 'optionalAccess', _360 => _360.mediaStreamTrack]);
|
|
3855
3971
|
if (!mediaTrack) throw new XmaxError("MEDIA_ERROR" /* mediaError */, "Camera capture is not running");
|
|
3856
3972
|
if (signal.aborted) throw new XmaxError("CANCELLED" /* cancelled */, "Camera frame validation cancelled");
|
|
3857
3973
|
if (!this.isFrameValidationEnabled) return;
|
|
@@ -3951,7 +4067,7 @@ var _CameraController = class _CameraController {
|
|
|
3951
4067
|
*/
|
|
3952
4068
|
async switchCamera() {
|
|
3953
4069
|
const track = this.activeTrack;
|
|
3954
|
-
const position = _optionalChain([track, 'optionalAccess',
|
|
4070
|
+
const position = _optionalChain([track, 'optionalAccess', _361 => _361.position]);
|
|
3955
4071
|
if (!track || !position) {
|
|
3956
4072
|
throw new XmaxError(
|
|
3957
4073
|
"RTC_ERROR" /* rtcError */,
|
|
@@ -3969,7 +4085,7 @@ var _CameraController = class _CameraController {
|
|
|
3969
4085
|
}
|
|
3970
4086
|
this.previewStream.addTrack(mediaTrack);
|
|
3971
4087
|
}
|
|
3972
|
-
_optionalChain([this, 'access',
|
|
4088
|
+
_optionalChain([this, 'access', _362 => _362.previewMirrorApplier, 'optionalCall', _363 => _363(nextPosition === "front" /* front */)]);
|
|
3973
4089
|
this.observeMediaTrack(track, mediaTrack);
|
|
3974
4090
|
return new RealtimeMediaStream({ id: "stream0" /* local */, videoTrack: track });
|
|
3975
4091
|
}
|
|
@@ -4167,7 +4283,7 @@ var NetworkVideoController = class {
|
|
|
4167
4283
|
this.ended = video.ended || this.ended;
|
|
4168
4284
|
video.removeEventListener("loadedmetadata", restore);
|
|
4169
4285
|
video.removeEventListener("error", fail);
|
|
4170
|
-
_optionalChain([view, 'access',
|
|
4286
|
+
_optionalChain([view, 'access', _364 => _364.setVideoURL, 'optionalCall', _365 => _365(null)]);
|
|
4171
4287
|
});
|
|
4172
4288
|
view.isMirrored = false;
|
|
4173
4289
|
view.setVideoURL(this.reference.path);
|
|
@@ -4176,7 +4292,7 @@ var NetworkVideoController = class {
|
|
|
4176
4292
|
* 保存预览进度并释放该视图的地址和事件监听。
|
|
4177
4293
|
*/
|
|
4178
4294
|
detach(view) {
|
|
4179
|
-
_optionalChain([this, 'access',
|
|
4295
|
+
_optionalChain([this, 'access', _366 => _366.bindings, 'access', _367 => _367.get, 'call', _368 => _368(view), 'optionalCall', _369 => _369()]);
|
|
4180
4296
|
this.bindings.delete(view);
|
|
4181
4297
|
}
|
|
4182
4298
|
};
|
|
@@ -4205,13 +4321,13 @@ var LocalVideoController = class {
|
|
|
4205
4321
|
* 准备完成的本地视频轨。
|
|
4206
4322
|
*/
|
|
4207
4323
|
get currentTrack() {
|
|
4208
|
-
return _optionalChain([this, 'access',
|
|
4324
|
+
return _optionalChain([this, 'access', _370 => _370.source, 'optionalAccess', _371 => _371.track]);
|
|
4209
4325
|
}
|
|
4210
4326
|
/**
|
|
4211
4327
|
* 文件音频输出;禁用音频时为空,无音轨文件的 Web Audio 输出为静音。
|
|
4212
4328
|
*/
|
|
4213
4329
|
get audioTrack() {
|
|
4214
|
-
return _optionalChain([this, 'access',
|
|
4330
|
+
return _optionalChain([this, 'access', _372 => _372.source, 'optionalAccess', _373 => _373.audioDestination, 'optionalAccess', _374 => _374.stream, 'access', _375 => _375.getAudioTracks, 'call', _376 => _376(), 'access', _377 => _377[0]]);
|
|
4215
4331
|
}
|
|
4216
4332
|
/**
|
|
4217
4333
|
* 校验文件和格式,准备首帧与音频输出;应从用户点击事件直接调用以解锁播放。
|
|
@@ -4264,7 +4380,7 @@ var LocalVideoController = class {
|
|
|
4264
4380
|
source.audioSource.connect(source.audioDestination);
|
|
4265
4381
|
}
|
|
4266
4382
|
video.src = source.url;
|
|
4267
|
-
const resume = _optionalChain([source, 'access',
|
|
4383
|
+
const resume = _optionalChain([source, 'access', _378 => _378.audioContext, 'optionalAccess', _379 => _379.resume, 'call', _380 => _380()]);
|
|
4268
4384
|
const playing = this.play(source, signal);
|
|
4269
4385
|
await this.wait(source, Promise.all([resume, playing]), signal);
|
|
4270
4386
|
video.pause();
|
|
@@ -4316,7 +4432,7 @@ var LocalVideoController = class {
|
|
|
4316
4432
|
*/
|
|
4317
4433
|
async start(signal) {
|
|
4318
4434
|
const source = this.source;
|
|
4319
|
-
if (!_optionalChain([source, 'optionalAccess',
|
|
4435
|
+
if (!_optionalChain([source, 'optionalAccess', _381 => _381.track])) {
|
|
4320
4436
|
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Local video is not prepared");
|
|
4321
4437
|
}
|
|
4322
4438
|
if (signal.aborted) {
|
|
@@ -4324,7 +4440,7 @@ var LocalVideoController = class {
|
|
|
4324
4440
|
}
|
|
4325
4441
|
try {
|
|
4326
4442
|
await this.rewind(source, signal);
|
|
4327
|
-
await this.wait(source, Promise.all([_optionalChain([source, 'access',
|
|
4443
|
+
await this.wait(source, Promise.all([_optionalChain([source, 'access', _382 => _382.audioContext, 'optionalAccess', _383 => _383.resume, 'call', _384 => _384()]), this.play(source, signal)]), signal);
|
|
4328
4444
|
} catch (error) {
|
|
4329
4445
|
source.video.pause();
|
|
4330
4446
|
throw error;
|
|
@@ -4334,7 +4450,7 @@ var LocalVideoController = class {
|
|
|
4334
4450
|
* 暂停文件音视频,保留当前预览;重新开始生成时回到文件开头。
|
|
4335
4451
|
*/
|
|
4336
4452
|
pause() {
|
|
4337
|
-
_optionalChain([this, 'access',
|
|
4453
|
+
_optionalChain([this, 'access', _385 => _385.source, 'optionalAccess', _386 => _386.video, 'access', _387 => _387.pause, 'call', _388 => _388()]);
|
|
4338
4454
|
}
|
|
4339
4455
|
/**
|
|
4340
4456
|
* 释放播放器、预览、定时器、轨道、音频上下文和对象 URL。
|
|
@@ -4364,12 +4480,12 @@ var LocalVideoController = class {
|
|
|
4364
4480
|
source.video.pause();
|
|
4365
4481
|
source.video.removeAttribute("src");
|
|
4366
4482
|
source.video.load();
|
|
4367
|
-
_optionalChain([source, 'access',
|
|
4368
|
-
_optionalChain([source, 'access',
|
|
4369
|
-
_optionalChain([source, 'access',
|
|
4370
|
-
_optionalChain([source, 'access',
|
|
4483
|
+
_optionalChain([source, 'access', _389 => _389.stream, 'optionalAccess', _390 => _390.getTracks, 'call', _391 => _391(), 'access', _392 => _392.forEach, 'call', _393 => _393((track) => track.stop())]);
|
|
4484
|
+
_optionalChain([source, 'access', _394 => _394.audioDestination, 'optionalAccess', _395 => _395.stream, 'access', _396 => _396.getTracks, 'call', _397 => _397(), 'access', _398 => _398.forEach, 'call', _399 => _399((track) => track.stop())]);
|
|
4485
|
+
_optionalChain([source, 'access', _400 => _400.audioSource, 'optionalAccess', _401 => _401.disconnect, 'call', _402 => _402()]);
|
|
4486
|
+
_optionalChain([source, 'access', _403 => _403.audioDestination, 'optionalAccess', _404 => _404.disconnect, 'call', _405 => _405()]);
|
|
4371
4487
|
URL.revokeObjectURL(source.url);
|
|
4372
|
-
await _optionalChain([source, 'access',
|
|
4488
|
+
await _optionalChain([source, 'access', _406 => _406.audioContext, 'optionalAccess', _407 => _407.close, 'call', _408 => _408(), 'access', _409 => _409.catch, 'call', _410 => _410(() => {
|
|
4373
4489
|
})]);
|
|
4374
4490
|
}
|
|
4375
4491
|
/**
|
|
@@ -4517,7 +4633,7 @@ var RealtimeContext = class {
|
|
|
4517
4633
|
__publicField(this, "referencePath");
|
|
4518
4634
|
this.referenceVideo = init.referenceVideo && Object.freeze({ ...init.referenceVideo });
|
|
4519
4635
|
this.prompt = init.prompt.trim();
|
|
4520
|
-
const normalizedReferencePath = _optionalChain([init, 'access',
|
|
4636
|
+
const normalizedReferencePath = _optionalChain([init, 'access', _411 => _411.referencePath, 'optionalAccess', _412 => _412.trim, 'call', _413 => _413()]);
|
|
4521
4637
|
this.referencePath = normalizedReferencePath || void 0;
|
|
4522
4638
|
}
|
|
4523
4639
|
};
|
|
@@ -4785,7 +4901,7 @@ var RealtimeSessionService = class _RealtimeSessionService {
|
|
|
4785
4901
|
return;
|
|
4786
4902
|
}
|
|
4787
4903
|
_RealtimeSessionService.ensureSessionActive(session);
|
|
4788
|
-
await _optionalChain([handlers, 'access',
|
|
4904
|
+
await _optionalChain([handlers, 'access', _414 => _414.onRefresh, 'optionalCall', _415 => _415(session)]);
|
|
4789
4905
|
} catch (error) {
|
|
4790
4906
|
if (this.heartbeatVersion !== version) {
|
|
4791
4907
|
return;
|
|
@@ -4998,7 +5114,7 @@ var RealtimeState = class {
|
|
|
4998
5114
|
* @param other 待比较的状态。
|
|
4999
5115
|
*/
|
|
5000
5116
|
equals(other) {
|
|
5001
|
-
return this.connectionState === other.connectionState && this.sessionID === other.sessionID && this.taskID === other.taskID && _optionalChain([this, 'access',
|
|
5117
|
+
return this.connectionState === other.connectionState && this.sessionID === other.sessionID && this.taskID === other.taskID && _optionalChain([this, 'access', _416 => _416.reason, 'optionalAccess', _417 => _417.kind]) === _optionalChain([other, 'access', _418 => _418.reason, 'optionalAccess', _419 => _419.kind]);
|
|
5002
5118
|
}
|
|
5003
5119
|
};
|
|
5004
5120
|
|
|
@@ -5043,12 +5159,13 @@ var RoomEvent = class _RoomEvent {
|
|
|
5043
5159
|
event: "start",
|
|
5044
5160
|
params: {
|
|
5045
5161
|
..._RoomEvent.generationParameters(options),
|
|
5162
|
+
mirror: _nullishCoalesce(options.mirror, () => ( false)),
|
|
5046
5163
|
...options.context.referenceVideo && {
|
|
5047
5164
|
ref_video_path: options.context.referenceVideo.path,
|
|
5048
5165
|
sample_method: options.context.referenceVideo.sampleMethod,
|
|
5049
5166
|
target_size: [
|
|
5050
|
-
_nullishCoalesce(_optionalChain([options, 'access',
|
|
5051
|
-
_nullishCoalesce(_optionalChain([options, 'access',
|
|
5167
|
+
_nullishCoalesce(_optionalChain([options, 'access', _420 => _420.targetSize, 'optionalAccess', _421 => _421.width]), () => ( options.videoFormat.width)),
|
|
5168
|
+
_nullishCoalesce(_optionalChain([options, 'access', _422 => _422.targetSize, 'optionalAccess', _423 => _423.height]), () => ( options.videoFormat.height))
|
|
5052
5169
|
]
|
|
5053
5170
|
}
|
|
5054
5171
|
},
|
|
@@ -5495,6 +5612,7 @@ var RoomController = class {
|
|
|
5495
5612
|
startGeneration(options) {
|
|
5496
5613
|
return this.send(
|
|
5497
5614
|
RoomEvent.start({
|
|
5615
|
+
mirror: _nullishCoalesce(options.mirror, () => ( false)),
|
|
5498
5616
|
userID: this.requireUserID(),
|
|
5499
5617
|
taskID: options.taskID,
|
|
5500
5618
|
videoFormat: options.videoFormat,
|
|
@@ -5592,7 +5710,7 @@ var RoomController = class {
|
|
|
5592
5710
|
if (targetUserID && ownUserID && targetUserID !== ownUserID) {
|
|
5593
5711
|
return;
|
|
5594
5712
|
}
|
|
5595
|
-
_optionalChain([this, 'access',
|
|
5713
|
+
_optionalChain([this, 'access', _424 => _424.listener, 'optionalAccess', _425 => _425.onRoomMessage, 'call', _426 => _426(senderUserID, message)]);
|
|
5596
5714
|
}
|
|
5597
5715
|
/**
|
|
5598
5716
|
* 发送房间信令并输出日志。
|
|
@@ -5646,6 +5764,7 @@ var _EncodingController = class _EncodingController {
|
|
|
5646
5764
|
* 基础层组件
|
|
5647
5765
|
*/
|
|
5648
5766
|
__publicField(this, "rtcManager");
|
|
5767
|
+
__publicField(this, "lastAppliedConfiguration");
|
|
5649
5768
|
this.rtcManager = options.rtcManager;
|
|
5650
5769
|
}
|
|
5651
5770
|
/**
|
|
@@ -5681,14 +5800,38 @@ var _EncodingController = class _EncodingController {
|
|
|
5681
5800
|
"Minimum bitrate must not exceed maximum bitrate after applying SDK defaults"
|
|
5682
5801
|
);
|
|
5683
5802
|
}
|
|
5684
|
-
|
|
5803
|
+
const configuration = {
|
|
5685
5804
|
width: videoFormat.width,
|
|
5686
5805
|
height: videoFormat.height,
|
|
5687
5806
|
frameRate: videoFormat.fps,
|
|
5688
5807
|
minimumBitrate: minimum,
|
|
5689
5808
|
maximumBitrate: maximum,
|
|
5690
5809
|
encoderPreference: ENCODER_PREFERENCE_MAP[videoFormat.encoderPreference]
|
|
5810
|
+
};
|
|
5811
|
+
await this.rtcManager.configureVideoEncoding(configuration);
|
|
5812
|
+
this.lastAppliedConfiguration = { ...configuration };
|
|
5813
|
+
}
|
|
5814
|
+
/** 只替换目标帧率,保留最近成功应用的尺寸、已解析码率区间和偏好。 */
|
|
5815
|
+
async updateFrameRate(fps) {
|
|
5816
|
+
const previous = this.lastAppliedConfiguration;
|
|
5817
|
+
if (!previous) {
|
|
5818
|
+
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Apply an encoder configuration before updating frame rate");
|
|
5819
|
+
}
|
|
5820
|
+
const format = new RealtimeVideoFormat({
|
|
5821
|
+
width: previous.width,
|
|
5822
|
+
height: previous.height,
|
|
5823
|
+
fps,
|
|
5824
|
+
minimumBitrate: previous.minimumBitrate,
|
|
5825
|
+
maximumBitrate: previous.maximumBitrate,
|
|
5826
|
+
encoderPreference: previous.encoderPreference === "maintainFramerate" /* maintainFramerate */ ? "maintainFramerate" /* maintainFramerate */ : "maintainQuality" /* maintainQuality */
|
|
5691
5827
|
});
|
|
5828
|
+
format.validate();
|
|
5829
|
+
if (fps !== previous.frameRate) {
|
|
5830
|
+
const next = { ...previous, frameRate: fps };
|
|
5831
|
+
await this.rtcManager.configureVideoEncoding(next);
|
|
5832
|
+
this.lastAppliedConfiguration = next;
|
|
5833
|
+
}
|
|
5834
|
+
return format;
|
|
5692
5835
|
}
|
|
5693
5836
|
/**
|
|
5694
5837
|
* 按像素面积与帧率计算码率区间(kbps):流畅优先为最低,画质优先为最高。
|
|
@@ -5849,7 +5992,7 @@ var StreamController = class {
|
|
|
5849
5992
|
this.roomController.setListener({
|
|
5850
5993
|
onRoomMessage: (sender, message) => {
|
|
5851
5994
|
this.handleNetworkVideoCompletion(sender, message);
|
|
5852
|
-
_optionalChain([this, 'access',
|
|
5995
|
+
_optionalChain([this, 'access', _427 => _427.roomListener, 'optionalAccess', _428 => _428.onRoomMessage, 'call', _429 => _429(sender, message)]);
|
|
5853
5996
|
}
|
|
5854
5997
|
});
|
|
5855
5998
|
this.rtcManager.setEventListener({
|
|
@@ -5859,18 +6002,18 @@ var StreamController = class {
|
|
|
5859
6002
|
onError: (error) => this.errorListener(error),
|
|
5860
6003
|
onNetworkStatistics: (statistics) => {
|
|
5861
6004
|
if (this.state.roomID) {
|
|
5862
|
-
_optionalChain([this, 'access',
|
|
6005
|
+
_optionalChain([this, 'access', _430 => _430.networkStatisticsListener, 'optionalCall', _431 => _431(statistics)]);
|
|
5863
6006
|
}
|
|
5864
6007
|
},
|
|
5865
6008
|
onRemoteVideoStatistics: (statistics) => {
|
|
5866
|
-
const userID = _optionalChain([this, 'access',
|
|
5867
|
-
_optionalChain([this, 'access',
|
|
6009
|
+
const userID = _optionalChain([this, 'access', _432 => _432.state, 'access', _433 => _433.activeRemoteStream, 'optionalAccess', _434 => _434.userID]);
|
|
6010
|
+
_optionalChain([this, 'access', _435 => _435.remoteVideoStatisticsListener, 'optionalCall', _436 => _436(
|
|
5868
6011
|
userID ? statistics.find((item) => item.userID === userID) : void 0
|
|
5869
6012
|
)]);
|
|
5870
6013
|
},
|
|
5871
6014
|
onLocalVideoStatistics: (statistics) => {
|
|
5872
6015
|
if (this.state.localVideoPublished) {
|
|
5873
|
-
_optionalChain([this, 'access',
|
|
6016
|
+
_optionalChain([this, 'access', _437 => _437.localVideoStatisticsListener, 'optionalCall', _438 => _438(statistics)]);
|
|
5874
6017
|
}
|
|
5875
6018
|
},
|
|
5876
6019
|
onCustomMessageReceived: (senderUserID, message) => {
|
|
@@ -5926,9 +6069,13 @@ var StreamController = class {
|
|
|
5926
6069
|
*
|
|
5927
6070
|
* @throws 格式无效、码率区间无效或 RTC 配置失败时抛出错误。
|
|
5928
6071
|
*/
|
|
5929
|
-
async
|
|
6072
|
+
async updateUplinkVideoFormat(videoFormat) {
|
|
5930
6073
|
await this.encodingController.configure(videoFormat);
|
|
5931
6074
|
}
|
|
6075
|
+
/** 不根据新帧率重新推算码率区间。 */
|
|
6076
|
+
async updateUplinkFrameRate(fps) {
|
|
6077
|
+
return this.encodingController.updateFrameRate(fps);
|
|
6078
|
+
}
|
|
5932
6079
|
/**
|
|
5933
6080
|
* 加入 RTC 房间并发布本地媒体流。
|
|
5934
6081
|
*
|
|
@@ -5943,7 +6090,7 @@ var StreamController = class {
|
|
|
5943
6090
|
\u2514\u2500 roomID: ${connection.roomID}, botID: ${_nullishCoalesce(connection.botID, () => ( "(\u672A\u8BBE\u7F6E)"))}`
|
|
5944
6091
|
);
|
|
5945
6092
|
if (publishLocalMedia) {
|
|
5946
|
-
await _optionalChain([beforePublish, 'optionalCall',
|
|
6093
|
+
await _optionalChain([beforePublish, 'optionalCall', _439 => _439()]);
|
|
5947
6094
|
ensureActive2();
|
|
5948
6095
|
await this.publishLocalStream(includeLocalAudio);
|
|
5949
6096
|
}
|
|
@@ -6014,6 +6161,7 @@ var StreamController = class {
|
|
|
6014
6161
|
try {
|
|
6015
6162
|
const sending = this.roomController.startGeneration({
|
|
6016
6163
|
taskID,
|
|
6164
|
+
mirror: _nullishCoalesce(options.mirror, () => ( false)),
|
|
6017
6165
|
videoFormat: options.videoFormat,
|
|
6018
6166
|
targetSize: options.targetSize,
|
|
6019
6167
|
context: options.context
|
|
@@ -6021,7 +6169,7 @@ var StreamController = class {
|
|
|
6021
6169
|
const state2 = this.state;
|
|
6022
6170
|
const sent = Promise.resolve(sending).then(async () => {
|
|
6023
6171
|
if (this.state !== state2 || state2.generationTaskID !== taskID) return;
|
|
6024
|
-
await _optionalChain([options, 'access',
|
|
6172
|
+
await _optionalChain([options, 'access', _440 => _440.onStartSent, 'optionalCall', _441 => _441()]);
|
|
6025
6173
|
if (this.state !== state2 || state2.generationTaskID !== taskID) return;
|
|
6026
6174
|
for (const userID of state2.publishedRemoteUserIDs) {
|
|
6027
6175
|
void this.handleRemoteVideoPublished(userID, true);
|
|
@@ -6087,7 +6235,7 @@ var StreamController = class {
|
|
|
6087
6235
|
*
|
|
6088
6236
|
* @throws 操作已取消、房间未就绪或信令发送失败时抛出错误。
|
|
6089
6237
|
*/
|
|
6090
|
-
async
|
|
6238
|
+
async updateDownlinkVideoResolution(taskID, targetSize, ensureActive2) {
|
|
6091
6239
|
try {
|
|
6092
6240
|
await this.roomController.changeTargetSize({ taskID, targetSize, ensureActive: ensureActive2 });
|
|
6093
6241
|
} catch (error) {
|
|
@@ -6156,7 +6304,7 @@ var StreamController = class {
|
|
|
6156
6304
|
deliverNetworkVideoCompletion() {
|
|
6157
6305
|
const state2 = this.state;
|
|
6158
6306
|
const completion = state2.networkVideoCompletion;
|
|
6159
|
-
if (!_optionalChain([completion, 'optionalAccess',
|
|
6307
|
+
if (!_optionalChain([completion, 'optionalAccess', _442 => _442.finished]) || !completion.onFinish || completion.scheduled) {
|
|
6160
6308
|
return;
|
|
6161
6309
|
}
|
|
6162
6310
|
completion.scheduled = true;
|
|
@@ -6165,7 +6313,7 @@ var StreamController = class {
|
|
|
6165
6313
|
return;
|
|
6166
6314
|
}
|
|
6167
6315
|
try {
|
|
6168
|
-
void Promise.resolve(_optionalChain([completion, 'access',
|
|
6316
|
+
void Promise.resolve(_optionalChain([completion, 'access', _443 => _443.onFinish, 'optionalCall', _444 => _444()])).catch(() => {
|
|
6169
6317
|
});
|
|
6170
6318
|
} catch (e23) {
|
|
6171
6319
|
}
|
|
@@ -6176,7 +6324,7 @@ var StreamController = class {
|
|
|
6176
6324
|
*/
|
|
6177
6325
|
configureRoom(options) {
|
|
6178
6326
|
const roomID = options.roomID.trim();
|
|
6179
|
-
const botID = _nullishCoalesce(_optionalChain([options, 'access',
|
|
6327
|
+
const botID = _nullishCoalesce(_optionalChain([options, 'access', _445 => _445.botID, 'optionalAccess', _446 => _446.trim, 'call', _447 => _447()]), () => ( ""));
|
|
6180
6328
|
if (!roomID) {
|
|
6181
6329
|
throw new XmaxError(
|
|
6182
6330
|
"INVALID_CONFIGURATION" /* invalidConfiguration */,
|
|
@@ -6259,7 +6407,7 @@ var StreamController = class {
|
|
|
6259
6407
|
return;
|
|
6260
6408
|
}
|
|
6261
6409
|
this.state.subscribedRemoteUserIDs.delete(trimmedUserID);
|
|
6262
|
-
if (_optionalChain([this, 'access',
|
|
6410
|
+
if (_optionalChain([this, 'access', _448 => _448.state, 'access', _449 => _449.activeRemoteStream, 'optionalAccess', _450 => _450.userID]) === trimmedUserID) {
|
|
6263
6411
|
await this.unsubscribeRemoteAudio(trimmedUserID);
|
|
6264
6412
|
this.state.activeRemoteStream = void 0;
|
|
6265
6413
|
this.clearRemoteStream();
|
|
@@ -6449,7 +6597,7 @@ var StreamController = class {
|
|
|
6449
6597
|
*/
|
|
6450
6598
|
resolveGenerationStart(taskID) {
|
|
6451
6599
|
const waiter = this.state.generationWaiter;
|
|
6452
|
-
if (this.state.generationTaskID !== taskID || _optionalChain([waiter, 'optionalAccess',
|
|
6600
|
+
if (this.state.generationTaskID !== taskID || _optionalChain([waiter, 'optionalAccess', _451 => _451.taskID]) !== taskID) {
|
|
6453
6601
|
return;
|
|
6454
6602
|
}
|
|
6455
6603
|
this.state.generationWaiter = void 0;
|
|
@@ -6461,7 +6609,7 @@ var StreamController = class {
|
|
|
6461
6609
|
*/
|
|
6462
6610
|
rejectGenerationStart(taskID, error) {
|
|
6463
6611
|
const waiter = this.state.generationWaiter;
|
|
6464
|
-
if (this.state.generationTaskID !== taskID || _optionalChain([waiter, 'optionalAccess',
|
|
6612
|
+
if (this.state.generationTaskID !== taskID || _optionalChain([waiter, 'optionalAccess', _452 => _452.taskID]) !== taskID) {
|
|
6465
6613
|
return;
|
|
6466
6614
|
}
|
|
6467
6615
|
this.state.generationWaiter = void 0;
|
|
@@ -6472,7 +6620,7 @@ var StreamController = class {
|
|
|
6472
6620
|
* 通知渲染层清理远端生成流;失败仅记录日志。
|
|
6473
6621
|
*/
|
|
6474
6622
|
clearRemoteStream() {
|
|
6475
|
-
_optionalChain([this, 'access',
|
|
6623
|
+
_optionalChain([this, 'access', _453 => _453.remoteVideoStatisticsListener, 'optionalCall', _454 => _454(void 0)]);
|
|
6476
6624
|
try {
|
|
6477
6625
|
this.remoteStreamListener(null);
|
|
6478
6626
|
} catch (error) {
|
|
@@ -6509,6 +6657,195 @@ var StreamController = class {
|
|
|
6509
6657
|
}
|
|
6510
6658
|
};
|
|
6511
6659
|
|
|
6660
|
+
// src/Stream/Quality/QualityTiers.ts
|
|
6661
|
+
var INITIAL_QUALITY_LEVEL = 2;
|
|
6662
|
+
var QUALITY_TIERS = {
|
|
6663
|
+
L1: { width: 1024, height: 1920, frameRate: 30 },
|
|
6664
|
+
L2: { width: 768, height: 1440, frameRate: 24 },
|
|
6665
|
+
L3: { width: 640, height: 1200, frameRate: 24 },
|
|
6666
|
+
L4: { width: 512, height: 960, frameRate: 20 },
|
|
6667
|
+
L5: { width: 384, height: 720, frameRate: 16 }
|
|
6668
|
+
};
|
|
6669
|
+
|
|
6670
|
+
// src/Stream/Quality/QualityPolicy.ts
|
|
6671
|
+
var DEFAULT_POLICY = {
|
|
6672
|
+
poorSamples: 3,
|
|
6673
|
+
goodSamples: 5,
|
|
6674
|
+
stabilizationMs: 4e3,
|
|
6675
|
+
probeMs: 2e4,
|
|
6676
|
+
upgradeCooldownMs: 6e4,
|
|
6677
|
+
sampleTimeoutMs: 5e3
|
|
6678
|
+
};
|
|
6679
|
+
|
|
6680
|
+
// src/Stream/Quality/QualityController.ts
|
|
6681
|
+
var ORDERED_QUALITY_TIERS = Object.values(QUALITY_TIERS);
|
|
6682
|
+
var QualityController = class {
|
|
6683
|
+
constructor(apply, now = () => performance.now(), policy = {}) {
|
|
6684
|
+
__publicField(this, "apply", apply);
|
|
6685
|
+
__publicField(this, "now", now);
|
|
6686
|
+
__publicField(this, "policy");
|
|
6687
|
+
__publicField(this, "active", false);
|
|
6688
|
+
__publicField(this, "index", 0);
|
|
6689
|
+
__publicField(this, "good", 0);
|
|
6690
|
+
__publicField(this, "poor", 0);
|
|
6691
|
+
__publicField(this, "lastSampleAt");
|
|
6692
|
+
__publicField(this, "stableUntil", 0);
|
|
6693
|
+
__publicField(this, "upgradeAfter", 0);
|
|
6694
|
+
__publicField(this, "probeUntil", 0);
|
|
6695
|
+
__publicField(this, "switching", false);
|
|
6696
|
+
__publicField(this, "lifecycle", new AbortController());
|
|
6697
|
+
this.policy = { ...DEFAULT_POLICY, ...policy };
|
|
6698
|
+
for (const value of Object.values(this.policy)) {
|
|
6699
|
+
if (!Number.isFinite(value) || value < 0) throw new Error("Invalid quality policy");
|
|
6700
|
+
}
|
|
6701
|
+
for (const value of [this.policy.poorSamples, this.policy.goodSamples]) {
|
|
6702
|
+
if (!Number.isInteger(value) || value < 1) throw new Error("Sample counts must be positive integers");
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
get snapshot() {
|
|
6706
|
+
return Object.freeze({
|
|
6707
|
+
active: this.active,
|
|
6708
|
+
level: this.index + 1,
|
|
6709
|
+
...ORDERED_QUALITY_TIERS[this.index],
|
|
6710
|
+
switching: this.switching,
|
|
6711
|
+
upgradeAfter: this.upgradeAfter
|
|
6712
|
+
});
|
|
6713
|
+
}
|
|
6714
|
+
/** 传入调用方保存的档位,不在 start 中擅自改写编码配置。 */
|
|
6715
|
+
start(level = 1) {
|
|
6716
|
+
if (!Number.isInteger(level) || level < 1 || level > ORDERED_QUALITY_TIERS.length) {
|
|
6717
|
+
throw new Error("Unsupported quality level");
|
|
6718
|
+
}
|
|
6719
|
+
this.stop();
|
|
6720
|
+
this.lifecycle = new AbortController();
|
|
6721
|
+
this.index = level - 1;
|
|
6722
|
+
this.active = true;
|
|
6723
|
+
this.stableUntil = this.upgradeAfter = this.probeUntil = 0;
|
|
6724
|
+
}
|
|
6725
|
+
/** 取消旧会话的迟到结果;底层尚未完成时仍保持串行限制。 */
|
|
6726
|
+
stop() {
|
|
6727
|
+
this.active = false;
|
|
6728
|
+
this.lifecycle.abort();
|
|
6729
|
+
this.resetSamples();
|
|
6730
|
+
}
|
|
6731
|
+
/** 前台操作期间丢弃累计样本,但保留试升失败后的冷却时间。 */
|
|
6732
|
+
resetSamples() {
|
|
6733
|
+
this.resetCounts();
|
|
6734
|
+
this.lastSampleAt = void 0;
|
|
6735
|
+
}
|
|
6736
|
+
/** 只接收质量事件,不得用定时器重复提交同一份缓存统计。异常由调用方记录。 */
|
|
6737
|
+
async observe(quality, sampleAt = this.now()) {
|
|
6738
|
+
if (!this.active || this.switching || !Number.isFinite(sampleAt)) return;
|
|
6739
|
+
const now = this.now();
|
|
6740
|
+
if (sampleAt > now) return;
|
|
6741
|
+
if (this.lastSampleAt !== void 0) {
|
|
6742
|
+
if (sampleAt <= this.lastSampleAt) return;
|
|
6743
|
+
if (sampleAt - this.lastSampleAt > this.policy.sampleTimeoutMs) this.resetCounts();
|
|
6744
|
+
}
|
|
6745
|
+
this.lastSampleAt = sampleAt;
|
|
6746
|
+
if (now - sampleAt > this.policy.sampleTimeoutMs || sampleAt < this.stableUntil) {
|
|
6747
|
+
this.resetCounts();
|
|
6748
|
+
return;
|
|
6749
|
+
}
|
|
6750
|
+
if (quality === 4 || quality === 5) {
|
|
6751
|
+
this.good = 0;
|
|
6752
|
+
this.poor++;
|
|
6753
|
+
if (this.poor >= this.policy.poorSamples && this.index < ORDERED_QUALITY_TIERS.length - 1) {
|
|
6754
|
+
return this.change(this.index + 1, now < this.probeUntil ? "failedProbe" : "poorNetwork");
|
|
6755
|
+
}
|
|
6756
|
+
} else if (quality === 1 || quality === 2) {
|
|
6757
|
+
this.poor = 0;
|
|
6758
|
+
if (sampleAt < this.upgradeAfter) {
|
|
6759
|
+
this.good = 0;
|
|
6760
|
+
return;
|
|
6761
|
+
}
|
|
6762
|
+
this.good++;
|
|
6763
|
+
if (this.good >= this.policy.goodSamples && this.index > 0) {
|
|
6764
|
+
return this.change(this.index - 1, "probeUpgrade");
|
|
6765
|
+
}
|
|
6766
|
+
} else {
|
|
6767
|
+
this.resetCounts();
|
|
6768
|
+
}
|
|
6769
|
+
return;
|
|
6770
|
+
}
|
|
6771
|
+
resetCounts() {
|
|
6772
|
+
this.good = this.poor = 0;
|
|
6773
|
+
}
|
|
6774
|
+
async change(index, reason) {
|
|
6775
|
+
const lifecycle = this.lifecycle;
|
|
6776
|
+
const change = { from: this.index + 1, to: index + 1, ...ORDERED_QUALITY_TIERS[index], reason };
|
|
6777
|
+
this.switching = true;
|
|
6778
|
+
this.resetCounts();
|
|
6779
|
+
try {
|
|
6780
|
+
await this.apply(change, lifecycle.signal);
|
|
6781
|
+
if (lifecycle.signal.aborted) return;
|
|
6782
|
+
this.index = index;
|
|
6783
|
+
const now = this.now();
|
|
6784
|
+
this.stableUntil = now + this.policy.stabilizationMs;
|
|
6785
|
+
this.probeUntil = reason === "probeUpgrade" ? now + this.policy.probeMs : 0;
|
|
6786
|
+
if (reason === "failedProbe") this.upgradeAfter = now + this.policy.upgradeCooldownMs;
|
|
6787
|
+
return change;
|
|
6788
|
+
} catch (error) {
|
|
6789
|
+
if (!lifecycle.signal.aborted) {
|
|
6790
|
+
this.stableUntil = this.now() + this.policy.stabilizationMs;
|
|
6791
|
+
throw error;
|
|
6792
|
+
}
|
|
6793
|
+
return;
|
|
6794
|
+
} finally {
|
|
6795
|
+
this.switching = false;
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
};
|
|
6799
|
+
|
|
6800
|
+
// src/Stream/Quality/QualityVideoFormat.ts
|
|
6801
|
+
function qualityVideoSize(baseline, level) {
|
|
6802
|
+
const tier = Object.values(QUALITY_TIERS)[level - 1];
|
|
6803
|
+
if (!Number.isInteger(level) || !tier) throw new Error("Unsupported quality level");
|
|
6804
|
+
baseline.validate();
|
|
6805
|
+
const scale = tier.width / QUALITY_TIERS.L1.width;
|
|
6806
|
+
const even = (value) => Math.max(2, Math.floor(value / 2) * 2);
|
|
6807
|
+
return { width: even(baseline.width * scale), height: even(baseline.height * scale) };
|
|
6808
|
+
}
|
|
6809
|
+
function qualityVideoFormat(baseline, level) {
|
|
6810
|
+
const size = qualityVideoSize(baseline, level);
|
|
6811
|
+
const tier = Object.values(QUALITY_TIERS)[level - 1];
|
|
6812
|
+
return new RealtimeVideoFormat({
|
|
6813
|
+
...baseline,
|
|
6814
|
+
...size,
|
|
6815
|
+
fps: Math.min(baseline.fps, tier.frameRate)
|
|
6816
|
+
});
|
|
6817
|
+
}
|
|
6818
|
+
|
|
6819
|
+
// src/Stream/Quality/QualityHistory.ts
|
|
6820
|
+
var QualityHistory = class {
|
|
6821
|
+
constructor(model) {
|
|
6822
|
+
__publicField(this, "model", model);
|
|
6823
|
+
}
|
|
6824
|
+
/** 无记录、损坏、SSR 或浏览器禁止存储时使用默认 L2。 */
|
|
6825
|
+
read(direction) {
|
|
6826
|
+
try {
|
|
6827
|
+
const level = Number(globalThis.localStorage.getItem(this.key(direction)));
|
|
6828
|
+
if (this.isValid(level)) return level;
|
|
6829
|
+
} catch (e24) {
|
|
6830
|
+
}
|
|
6831
|
+
return INITIAL_QUALITY_LEVEL;
|
|
6832
|
+
}
|
|
6833
|
+
/** 仅在应用成功后调用;下行成功表示信令已发送,不代表服务端已确认生效。 */
|
|
6834
|
+
write(direction, level) {
|
|
6835
|
+
if (!this.isValid(level)) return;
|
|
6836
|
+
try {
|
|
6837
|
+
globalThis.localStorage.setItem(this.key(direction), String(level));
|
|
6838
|
+
} catch (e25) {
|
|
6839
|
+
}
|
|
6840
|
+
}
|
|
6841
|
+
key(direction) {
|
|
6842
|
+
return `xmax:quality:v1:agora:${encodeURIComponent(this.model)}:${direction}`;
|
|
6843
|
+
}
|
|
6844
|
+
isValid(level) {
|
|
6845
|
+
return Number.isInteger(level) && level >= 1 && level <= Object.keys(QUALITY_TIERS).length;
|
|
6846
|
+
}
|
|
6847
|
+
};
|
|
6848
|
+
|
|
6512
6849
|
// src/Core/Realtime/RealtimeCoordinator.ts
|
|
6513
6850
|
function scopeAffects(scope, kind) {
|
|
6514
6851
|
if (scope === 1 /* all */) {
|
|
@@ -6611,6 +6948,10 @@ var RealtimeCoordinator = class _RealtimeCoordinator {
|
|
|
6611
6948
|
get currentState() {
|
|
6612
6949
|
return this.state;
|
|
6613
6950
|
}
|
|
6951
|
+
/** 后台自动调档仅在没有前台操作或清理时申请操作租约。 */
|
|
6952
|
+
get isBusy() {
|
|
6953
|
+
return this.activeOperation !== void 0 || this.termination !== void 0;
|
|
6954
|
+
}
|
|
6614
6955
|
/**
|
|
6615
6956
|
* 设置实时状态监听器;设置后立即回放当前状态。
|
|
6616
6957
|
*
|
|
@@ -6743,7 +7084,7 @@ var RealtimeCoordinator = class _RealtimeCoordinator {
|
|
|
6743
7084
|
}
|
|
6744
7085
|
throw _RealtimeCoordinator.cancelledError();
|
|
6745
7086
|
}
|
|
6746
|
-
const terminationTask = await _asyncNullishCoalesce(await _asyncNullishCoalesce(operation.terminationTask, async () => ( _optionalChain([this, 'access',
|
|
7087
|
+
const terminationTask = await _asyncNullishCoalesce(await _asyncNullishCoalesce(operation.terminationTask, async () => ( _optionalChain([this, 'access', _455 => _455.termination, 'optionalAccess', _456 => _456.task]))), async () => ( await this.requestTermination(
|
|
6747
7088
|
_nullishCoalesce(operation.lease.failureScope, () => ( 0)) /* connection */,
|
|
6748
7089
|
void 0,
|
|
6749
7090
|
RealtimeReason.normal,
|
|
@@ -6872,7 +7213,7 @@ var RealtimeCoordinator = class _RealtimeCoordinator {
|
|
|
6872
7213
|
* 结束指定操作,释放操作准入场。
|
|
6873
7214
|
*/
|
|
6874
7215
|
finish(operation) {
|
|
6875
|
-
if (_optionalChain([this, 'access',
|
|
7216
|
+
if (_optionalChain([this, 'access', _457 => _457.activeOperation, 'optionalAccess', _458 => _458.id]) === operation.id) {
|
|
6876
7217
|
this.activeOperation = void 0;
|
|
6877
7218
|
}
|
|
6878
7219
|
}
|
|
@@ -6884,7 +7225,7 @@ var RealtimeCoordinator = class _RealtimeCoordinator {
|
|
|
6884
7225
|
return;
|
|
6885
7226
|
}
|
|
6886
7227
|
this.state = nextState;
|
|
6887
|
-
_optionalChain([this, 'access',
|
|
7228
|
+
_optionalChain([this, 'access', _459 => _459.stateListener, 'optionalCall', _460 => _460(nextState)]);
|
|
6888
7229
|
}
|
|
6889
7230
|
/**
|
|
6890
7231
|
* 构造统一的操作取消错误。
|
|
@@ -7021,9 +7362,9 @@ var RealtimeLaunchTimer = class {
|
|
|
7021
7362
|
*/
|
|
7022
7363
|
notify() {
|
|
7023
7364
|
try {
|
|
7024
|
-
void Promise.resolve(_optionalChain([this, 'access',
|
|
7365
|
+
void Promise.resolve(_optionalChain([this, 'access', _461 => _461.listener, 'optionalCall', _462 => _462(this.snapshot)])).catch(() => {
|
|
7025
7366
|
});
|
|
7026
|
-
} catch (
|
|
7367
|
+
} catch (e26) {
|
|
7027
7368
|
}
|
|
7028
7369
|
}
|
|
7029
7370
|
};
|
|
@@ -7053,7 +7394,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7053
7394
|
* 当前活动会话标识;尚未连接或清理完成后为空。
|
|
7054
7395
|
*/
|
|
7055
7396
|
get currentSessionID() {
|
|
7056
|
-
return _optionalChain([this, 'access',
|
|
7397
|
+
return _optionalChain([this, 'access', _463 => _463.activeSession, 'optionalAccess', _464 => _464.id]);
|
|
7057
7398
|
}
|
|
7058
7399
|
/**
|
|
7059
7400
|
* 未配置 API 服务时在连接操作开始前报错,不影响本地预览。
|
|
@@ -7087,7 +7428,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7087
7428
|
}
|
|
7088
7429
|
const refreshVersion = ++this.refreshVersion;
|
|
7089
7430
|
this.credentialController = new AbortController();
|
|
7090
|
-
const videoFormat = options.localTrack.videoFormat;
|
|
7431
|
+
const videoFormat = _nullishCoalesce(options.localVideoFormat, () => ( options.localTrack.videoFormat));
|
|
7091
7432
|
if (!videoFormat) {
|
|
7092
7433
|
throw new XmaxError(
|
|
7093
7434
|
"INTERNAL_ERROR" /* internalError */,
|
|
@@ -7096,7 +7437,9 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7096
7437
|
}
|
|
7097
7438
|
const publishLocalMedia = _nullishCoalesce(options.publishLocalMedia, () => ( true));
|
|
7098
7439
|
if (publishLocalMedia) {
|
|
7099
|
-
await streamController.
|
|
7440
|
+
await streamController.updateUplinkVideoFormat(videoFormat);
|
|
7441
|
+
options.ensureCurrent();
|
|
7442
|
+
_optionalChain([options, 'access', _465 => _465.onVideoEncoderConfigured, 'optionalCall', _466 => _466()]);
|
|
7100
7443
|
}
|
|
7101
7444
|
options.ensureCurrent();
|
|
7102
7445
|
let completePublish;
|
|
@@ -7104,13 +7447,13 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7104
7447
|
options.ensureCurrent();
|
|
7105
7448
|
}, async () => {
|
|
7106
7449
|
options.ensureCurrent();
|
|
7107
|
-
await _optionalChain([options, 'access',
|
|
7450
|
+
await _optionalChain([options, 'access', _467 => _467.beforePublish, 'optionalCall', _468 => _468()]);
|
|
7108
7451
|
completeConnection();
|
|
7109
7452
|
completePublish = this.dependencies.timing.startPublish();
|
|
7110
7453
|
}, publishLocalMedia);
|
|
7111
7454
|
options.ensureCurrent();
|
|
7112
7455
|
completeConnection();
|
|
7113
|
-
_optionalChain([completePublish, 'optionalCall',
|
|
7456
|
+
_optionalChain([completePublish, 'optionalCall', _469 => _469()]);
|
|
7114
7457
|
options.onPublished();
|
|
7115
7458
|
sessionService.startHeartbeat(session.id, {
|
|
7116
7459
|
onFailure: (sessionID, error) => {
|
|
@@ -7133,24 +7476,24 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7133
7476
|
* 更新已绑定远端视图的插帧配置;传 undefined 停用插帧。
|
|
7134
7477
|
*/
|
|
7135
7478
|
setFrameInterpolation(options) {
|
|
7136
|
-
_optionalChain([this, 'access',
|
|
7479
|
+
_optionalChain([this, 'access', _470 => _470.remoteTarget, 'optionalAccess', _471 => _471.setFrameInterpolation, 'optionalCall', _472 => _472(options)]);
|
|
7137
7480
|
}
|
|
7138
7481
|
/**
|
|
7139
7482
|
* 清空远端视图的媒体流,保留轨道与视图绑定以供统一清理。
|
|
7140
7483
|
*/
|
|
7141
7484
|
clearRemoteMedia() {
|
|
7142
|
-
_optionalChain([this, 'access',
|
|
7485
|
+
_optionalChain([this, 'access', _473 => _473.remoteTarget, 'optionalAccess', _474 => _474.setMediaStream, 'call', _475 => _475(null)]);
|
|
7143
7486
|
}
|
|
7144
7487
|
/**
|
|
7145
7488
|
* 停止会话心跳;未配置会话服务时不执行操作。
|
|
7146
7489
|
*/
|
|
7147
7490
|
stopHeartbeat() {
|
|
7148
7491
|
this.refreshVersion++;
|
|
7149
|
-
_optionalChain([this, 'access',
|
|
7492
|
+
_optionalChain([this, 'access', _476 => _476.credentialController, 'optionalAccess', _477 => _477.abort, 'call', _478 => _478()]);
|
|
7150
7493
|
this.credentialController = void 0;
|
|
7151
7494
|
this.credentialRefresh = void 0;
|
|
7152
7495
|
this.credentialApplication = Promise.resolve();
|
|
7153
|
-
_optionalChain([this, 'access',
|
|
7496
|
+
_optionalChain([this, 'access', _479 => _479.dependencies, 'access', _480 => _480.sessionService, 'optionalAccess', _481 => _481.stopHeartbeat, 'call', _482 => _482()]);
|
|
7154
7497
|
}
|
|
7155
7498
|
/**
|
|
7156
7499
|
* RTC Token 过期时复用会话心跳获取新凭据,并合并同一实例的并发请求。
|
|
@@ -7158,14 +7501,14 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7158
7501
|
async refreshCredentials() {
|
|
7159
7502
|
if (this.credentialRefresh) return this.credentialRefresh;
|
|
7160
7503
|
const current = this.activeSession;
|
|
7161
|
-
if (!_optionalChain([current, 'optionalAccess',
|
|
7504
|
+
if (!_optionalChain([current, 'optionalAccess', _483 => _483.connection]) || current.connection.provider === "trtc" /* trtc */) return;
|
|
7162
7505
|
const version = this.refreshVersion;
|
|
7163
7506
|
const operation = (async () => {
|
|
7164
7507
|
try {
|
|
7165
7508
|
const session = await this.requireSessionService().heartbeatSession(current.id);
|
|
7166
7509
|
await this.handleSessionRefresh(session, version, true);
|
|
7167
7510
|
} catch (error) {
|
|
7168
|
-
if (version === this.refreshVersion && _optionalChain([this, 'access',
|
|
7511
|
+
if (version === this.refreshVersion && _optionalChain([this, 'access', _484 => _484.activeSession, 'optionalAccess', _485 => _485.id]) === current.id) {
|
|
7169
7512
|
this.dependencies.onHeartbeatFailure(current.id, XmaxError.from(error));
|
|
7170
7513
|
}
|
|
7171
7514
|
}
|
|
@@ -7182,7 +7525,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7182
7525
|
*/
|
|
7183
7526
|
async waitUntilRemoteTrackReady(timeoutMs, signal) {
|
|
7184
7527
|
if (signal.aborted) throw RealtimeCoordinator.cancelledError();
|
|
7185
|
-
const mediaTrack = _optionalChain([this, 'access',
|
|
7528
|
+
const mediaTrack = _optionalChain([this, 'access', _486 => _486.activeRemoteTrack, 'optionalAccess', _487 => _487.mediaStreamTrack]);
|
|
7186
7529
|
if (!mediaTrack || !mediaTrack.muted) return;
|
|
7187
7530
|
await new Promise((resolve, reject) => {
|
|
7188
7531
|
const cleanup = () => {
|
|
@@ -7219,7 +7562,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7219
7562
|
if (track) {
|
|
7220
7563
|
track.mediaStreamTrack = void 0;
|
|
7221
7564
|
}
|
|
7222
|
-
_optionalChain([this, 'access',
|
|
7565
|
+
_optionalChain([this, 'access', _488 => _488.remoteTarget, 'optionalAccess', _489 => _489.setMediaStream, 'call', _490 => _490(null)]);
|
|
7223
7566
|
return;
|
|
7224
7567
|
}
|
|
7225
7568
|
if (!track) {
|
|
@@ -7229,7 +7572,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7229
7572
|
);
|
|
7230
7573
|
}
|
|
7231
7574
|
track.mediaStreamTrack = binding.videoTrack;
|
|
7232
|
-
_optionalChain([this, 'access',
|
|
7575
|
+
_optionalChain([this, 'access', _491 => _491.remoteTarget, 'optionalAccess', _492 => _492.setMediaStream, 'call', _493 => _493(new MediaStream([binding.videoTrack]))]);
|
|
7233
7576
|
}
|
|
7234
7577
|
/**
|
|
7235
7578
|
* 为远端轨道注册渲染绑定:attach 时挂流占位,媒体轨到达后送入画面。
|
|
@@ -7242,8 +7585,8 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7242
7585
|
}
|
|
7243
7586
|
},
|
|
7244
7587
|
attachHandler: (view) => {
|
|
7245
|
-
_optionalChain([this, 'access',
|
|
7246
|
-
view.isMirrored =
|
|
7588
|
+
_optionalChain([this, 'access', _494 => _494.remoteTarget, 'optionalAccess', _495 => _495.setFrameInterpolation, 'optionalCall', _496 => _496(void 0)]);
|
|
7589
|
+
view.isMirrored = false;
|
|
7247
7590
|
this.remoteTarget = view;
|
|
7248
7591
|
this.dependencies.onRenderAttached();
|
|
7249
7592
|
const mediaTrack = track.mediaStreamTrack;
|
|
@@ -7254,19 +7597,11 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7254
7597
|
this.dependencies.onRenderDetached();
|
|
7255
7598
|
this.remoteTarget = void 0;
|
|
7256
7599
|
}
|
|
7257
|
-
_optionalChain([view, 'access',
|
|
7600
|
+
_optionalChain([view, 'access', _497 => _497.setFrameInterpolation, 'optionalCall', _498 => _498(void 0)]);
|
|
7258
7601
|
view.setMediaStream(null);
|
|
7259
7602
|
}
|
|
7260
7603
|
});
|
|
7261
7604
|
}
|
|
7262
|
-
/**
|
|
7263
|
-
* 同步远端结果画面的镜像状态:与当前本地摄像头位置保持一致。
|
|
7264
|
-
*/
|
|
7265
|
-
updateRemoteMirror() {
|
|
7266
|
-
if (this.remoteTarget) {
|
|
7267
|
-
this.remoteTarget.isMirrored = this.dependencies.isMirrored();
|
|
7268
|
-
}
|
|
7269
|
-
}
|
|
7270
7605
|
/**
|
|
7271
7606
|
* 构造当前远端生成结果媒体流。
|
|
7272
7607
|
*/
|
|
@@ -7312,7 +7647,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7312
7647
|
return;
|
|
7313
7648
|
}
|
|
7314
7649
|
if (next.provider !== "trtc" /* trtc */ && (force || !previous || previous.provider === "trtc" /* trtc */ || next.roomToken !== previous.roomToken)) {
|
|
7315
|
-
await this.dependencies.streamController.updateCredentials(next, _optionalChain([this, 'access',
|
|
7650
|
+
await this.dependencies.streamController.updateCredentials(next, _optionalChain([this, 'access', _499 => _499.credentialController, 'optionalAccess', _500 => _500.signal]));
|
|
7316
7651
|
if (version !== this.refreshVersion || this.activeSession !== current) return;
|
|
7317
7652
|
}
|
|
7318
7653
|
this.activeSession = new RealtimeSession({
|
|
@@ -7327,7 +7662,7 @@ var XmaxRealtimeConnectionManager = class {
|
|
|
7327
7662
|
* 尽力清理全部连接资源,即使退房失败也关闭服务端会话。
|
|
7328
7663
|
*/
|
|
7329
7664
|
async disconnect() {
|
|
7330
|
-
const sessionID = _optionalChain([this, 'access',
|
|
7665
|
+
const sessionID = _optionalChain([this, 'access', _501 => _501.activeSession, 'optionalAccess', _502 => _502.id]);
|
|
7331
7666
|
this.stopHeartbeat();
|
|
7332
7667
|
this.clearRemoteMedia();
|
|
7333
7668
|
try {
|
|
@@ -7410,6 +7745,8 @@ var XmaxRealtimeGenerationManager = class _XmaxRealtimeGenerationManager {
|
|
|
7410
7745
|
taskID,
|
|
7411
7746
|
videoFormat: options.videoFormat,
|
|
7412
7747
|
context,
|
|
7748
|
+
...options.targetSize && { targetSize: options.targetSize },
|
|
7749
|
+
mirror: _nullishCoalesce(options.mirror, () => ( false)),
|
|
7413
7750
|
...options.onStartSent && { onStartSent: options.onStartSent }
|
|
7414
7751
|
});
|
|
7415
7752
|
await this.awaitConfirmation(confirmation, options.signal);
|
|
@@ -7436,7 +7773,8 @@ var XmaxRealtimeGenerationManager = class _XmaxRealtimeGenerationManager {
|
|
|
7436
7773
|
await this.streamController.updateGeneration({
|
|
7437
7774
|
taskID,
|
|
7438
7775
|
videoFormat: options.videoFormat,
|
|
7439
|
-
context
|
|
7776
|
+
context,
|
|
7777
|
+
...options.targetSize && { targetSize: options.targetSize }
|
|
7440
7778
|
});
|
|
7441
7779
|
if (this.activeTaskID !== taskID) throw RealtimeCoordinator.cancelledError();
|
|
7442
7780
|
this.currentContext = context;
|
|
@@ -7462,7 +7800,7 @@ var XmaxRealtimeGenerationManager = class _XmaxRealtimeGenerationManager {
|
|
|
7462
7800
|
try {
|
|
7463
7801
|
await completion;
|
|
7464
7802
|
} finally {
|
|
7465
|
-
if (_optionalChain([this, 'access',
|
|
7803
|
+
if (_optionalChain([this, 'access', _503 => _503.pendingStop, 'optionalAccess', _504 => _504.completion]) === completion) this.pendingStop = void 0;
|
|
7466
7804
|
}
|
|
7467
7805
|
}
|
|
7468
7806
|
/**
|
|
@@ -7573,6 +7911,14 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7573
7911
|
__publicField(this, "connectionManager");
|
|
7574
7912
|
__publicField(this, "generationManager");
|
|
7575
7913
|
__publicField(this, "streamController");
|
|
7914
|
+
__publicField(this, "qualityController");
|
|
7915
|
+
__publicField(this, "qualityHistory");
|
|
7916
|
+
__publicField(this, "qualityStates", /* @__PURE__ */ new WeakMap());
|
|
7917
|
+
__publicField(this, "downlinkQualityController");
|
|
7918
|
+
/** 无服务端生效 ACK;level/size 表示最后成功发送的目标,而非实际接收规格。 */
|
|
7919
|
+
__publicField(this, "downlinkQualityState");
|
|
7920
|
+
__publicField(this, "adaptiveQualityPending", false);
|
|
7921
|
+
__publicField(this, "adaptiveQualityRevision", 0);
|
|
7576
7922
|
/**
|
|
7577
7923
|
* 音量配置
|
|
7578
7924
|
*/
|
|
@@ -7581,19 +7927,19 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7581
7927
|
this.options = options;
|
|
7582
7928
|
this.mediaService = new MediaService(options.model);
|
|
7583
7929
|
this.interpolationRequested = options.isFrameInterpolationEnabled;
|
|
7584
|
-
this.supportsInterpolation = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess',
|
|
7930
|
+
this.supportsInterpolation = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _505 => _505.supportsFrameInterpolation]), () => ( (async (size) => await frameInterpolationAdapter(size) !== null)));
|
|
7585
7931
|
this.errorHandler = new RealtimeErrorHandler();
|
|
7586
|
-
const rtcManager = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess',
|
|
7932
|
+
const rtcManager = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _506 => _506.rtcManager]), () => ( createRtcManager(options.provider, _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _507 => _507.environment]), () => ( "china")) /* china */)));
|
|
7587
7933
|
this.rtcManager = rtcManager;
|
|
7588
|
-
this.cameraController = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess',
|
|
7934
|
+
this.cameraController = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _508 => _508.cameraController]), () => ( new CameraController({
|
|
7589
7935
|
rtcManager,
|
|
7590
7936
|
mediaService: this.mediaService,
|
|
7591
7937
|
errorListener: (error) => {
|
|
7592
7938
|
void this.errorHandler.report(error);
|
|
7593
7939
|
}
|
|
7594
7940
|
})));
|
|
7595
|
-
const sessionService = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess',
|
|
7596
|
-
this.streamController = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess',
|
|
7941
|
+
const sessionService = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _509 => _509.sessionService]), () => ( (_optionalChain([dependencies, 'optionalAccess', _510 => _510.apiService]) ? new RealtimeSessionService({ apiService: dependencies.apiService, provider: options.provider }) : void 0)));
|
|
7942
|
+
this.streamController = _nullishCoalesce(_optionalChain([dependencies, 'optionalAccess', _511 => _511.streamController]), () => ( new StreamController({
|
|
7597
7943
|
rtcManager,
|
|
7598
7944
|
onCredentialsRequired: () => {
|
|
7599
7945
|
void this.connectionManager.refreshCredentials();
|
|
@@ -7611,12 +7957,11 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7611
7957
|
sessionService,
|
|
7612
7958
|
streamController: this.streamController,
|
|
7613
7959
|
timing: this.launchTimer,
|
|
7614
|
-
isMirrored: () => _optionalChain([this, 'access', _487 => _487.cameraController, 'access', _488 => _488.currentTrack, 'optionalAccess', _489 => _489.position]) === "front" /* front */,
|
|
7615
7960
|
remoteAudioVolume: () => this.storedRemoteAudioVolume,
|
|
7616
7961
|
onHeartbeatFailure: (sessionID, error) => {
|
|
7617
7962
|
void this.handleHeartbeatFailure(sessionID, error);
|
|
7618
7963
|
},
|
|
7619
|
-
onFrameDisplayed: () => _optionalChain([this, 'access',
|
|
7964
|
+
onFrameDisplayed: () => _optionalChain([this, 'access', _512 => _512.remoteFrameDisplayHandler, 'optionalCall', _513 => _513()]),
|
|
7620
7965
|
onRenderAttached: () => this.applyRemoteInterpolation(),
|
|
7621
7966
|
onRenderDetached: () => {
|
|
7622
7967
|
this.interpolationRevision++;
|
|
@@ -7627,6 +7972,31 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7627
7972
|
errorHandler: this.errorHandler,
|
|
7628
7973
|
cleanup: (scope, taskID) => this.performCleanup(scope, taskID)
|
|
7629
7974
|
});
|
|
7975
|
+
if (options.provider === "agora" /* agora */) {
|
|
7976
|
+
this.qualityHistory = new QualityHistory(options.model);
|
|
7977
|
+
this.qualityController = new QualityController(async (change, signal) => {
|
|
7978
|
+
if (signal.aborted || this.currentState.connectionState !== "Generating" /* generating */) {
|
|
7979
|
+
throw new XmaxError("CANCELLED" /* cancelled */, "Adaptive video format update was cancelled");
|
|
7980
|
+
}
|
|
7981
|
+
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
7982
|
+
const track = _nullishCoalesce(this.localVideoController.currentTrack, () => ( this.cameraController.currentTrack));
|
|
7983
|
+
const state2 = track && this.qualityStates.get(track);
|
|
7984
|
+
if (!track || !state2) throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Adaptive video baseline is unavailable");
|
|
7985
|
+
const format = qualityVideoFormat(state2.baseline, change.to);
|
|
7986
|
+
await this.streamController.updateUplinkVideoFormat(format);
|
|
7987
|
+
token.ensureCurrent();
|
|
7988
|
+
_nullishCoalesce(this.generationVideoFormat, () => ( (this.generationVideoFormat = state2.baseline)));
|
|
7989
|
+
track.updateVideoFormat(format);
|
|
7990
|
+
state2.level = change.to;
|
|
7991
|
+
_optionalChain([this, 'access', _514 => _514.qualityHistory, 'optionalAccess', _515 => _515.write, 'call', _516 => _516("uplink", change.to)]);
|
|
7992
|
+
});
|
|
7993
|
+
});
|
|
7994
|
+
this.downlinkQualityController = new QualityController(async (change, signal) => {
|
|
7995
|
+
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
7996
|
+
await this.applyDownlinkQuality(change.to, token, signal);
|
|
7997
|
+
});
|
|
7998
|
+
});
|
|
7999
|
+
}
|
|
7630
8000
|
this.streamController.setLocalVideoStatisticsListener((statistics) => {
|
|
7631
8001
|
if (this.acceptsVideoStatistics) {
|
|
7632
8002
|
this.localVideoStatistics = statistics ? Object.freeze({ ...statistics }) : void 0;
|
|
@@ -7636,6 +8006,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7636
8006
|
this.streamController.setNetworkStatisticsListener((statistics) => {
|
|
7637
8007
|
if (this.acceptsVideoStatistics) {
|
|
7638
8008
|
this.networkStatistics = statistics ? Object.freeze({ ...statistics }) : void 0;
|
|
8009
|
+
this.handleAdaptiveQuality(statistics);
|
|
7639
8010
|
this.notifyNetworkStatistics();
|
|
7640
8011
|
}
|
|
7641
8012
|
});
|
|
@@ -7663,7 +8034,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7663
8034
|
*/
|
|
7664
8035
|
async setFrameInterpolationEnabled(enabled) {
|
|
7665
8036
|
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
7666
|
-
const format = _nullishCoalesce(this.generationVideoFormat, () => ( _optionalChain([this, 'access',
|
|
8037
|
+
const format = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _517 => _517.downlinkQualityState, 'optionalAccess', _518 => _518.size]), () => ( this.generationVideoFormat)), () => ( _optionalChain([this, 'access', _519 => _519.currentLocalTrack, 'optionalAccess', _520 => _520.videoFormat])));
|
|
7667
8038
|
const size = format && enabled ? this.mediaService.resolveFrameInterpolationSize(format) : void 0;
|
|
7668
8039
|
if (enabled && !await this.checkInterpolationSupport(size, token)) {
|
|
7669
8040
|
token.ensureCurrent();
|
|
@@ -7675,6 +8046,43 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7675
8046
|
this.applyRemoteInterpolation();
|
|
7676
8047
|
});
|
|
7677
8048
|
}
|
|
8049
|
+
/** 手动调试与自动调档使用同一尺寸信令路径,不修改生成或上行配置。 */
|
|
8050
|
+
async adjustDownlinkQuality(direction) {
|
|
8051
|
+
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
8052
|
+
const controller = this.downlinkQualityController;
|
|
8053
|
+
const state2 = this.downlinkQualityState;
|
|
8054
|
+
if (!controller || !state2 || this.currentState.connectionState !== "Generating" /* generating */ || direction !== "upgrade" && direction !== "downgrade") {
|
|
8055
|
+
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Downlink quality adjustment requires an active Agora generation and a valid direction");
|
|
8056
|
+
}
|
|
8057
|
+
const level = Math.max(1, Math.min(Object.keys(QUALITY_TIERS).length, state2.level + (direction === "upgrade" ? -1 : 1)));
|
|
8058
|
+
if (level === state2.level) return;
|
|
8059
|
+
this.adaptiveQualityRevision++;
|
|
8060
|
+
controller.resetSamples();
|
|
8061
|
+
await this.applyDownlinkQuality(level, token);
|
|
8062
|
+
controller.start(level);
|
|
8063
|
+
});
|
|
8064
|
+
}
|
|
8065
|
+
async applyDownlinkQuality(level, token, signal) {
|
|
8066
|
+
const state2 = this.downlinkQualityState;
|
|
8067
|
+
const ensureActive2 = () => {
|
|
8068
|
+
token.ensureCurrent();
|
|
8069
|
+
if (_optionalChain([signal, 'optionalAccess', _521 => _521.aborted]) || !state2 || state2 !== this.downlinkQualityState || this.currentState.connectionState !== "Generating" /* generating */ || this.currentState.taskID !== state2.taskID) {
|
|
8070
|
+
throw new XmaxError("CANCELLED" /* cancelled */, "Target size update was cancelled");
|
|
8071
|
+
}
|
|
8072
|
+
};
|
|
8073
|
+
ensureActive2();
|
|
8074
|
+
if (!state2) return;
|
|
8075
|
+
const size = qualityVideoSize(state2.baseline, level);
|
|
8076
|
+
await this.streamController.updateDownlinkVideoResolution(state2.taskID, size, ensureActive2);
|
|
8077
|
+
ensureActive2();
|
|
8078
|
+
state2.level = level;
|
|
8079
|
+
state2.size = size;
|
|
8080
|
+
_optionalChain([this, 'access', _522 => _522.qualityHistory, 'optionalAccess', _523 => _523.write, 'call', _524 => _524("downlink", level)]);
|
|
8081
|
+
if (this.interpolationRequested) {
|
|
8082
|
+
this.interpolationSize = size;
|
|
8083
|
+
this.applyRemoteInterpolation();
|
|
8084
|
+
}
|
|
8085
|
+
}
|
|
7678
8086
|
/**
|
|
7679
8087
|
* 根据当前视频尺寸准备插帧,能力不可用时降级为原视频,并在应用前校验租约。
|
|
7680
8088
|
*/
|
|
@@ -7788,9 +8196,9 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7788
8196
|
*/
|
|
7789
8197
|
notifyRemoteVideoStatistics() {
|
|
7790
8198
|
try {
|
|
7791
|
-
void Promise.resolve(_optionalChain([this, 'access',
|
|
8199
|
+
void Promise.resolve(_optionalChain([this, 'access', _525 => _525.remoteVideoStatisticsListener, 'optionalCall', _526 => _526(this.remoteVideoStatistics)])).catch(() => {
|
|
7792
8200
|
});
|
|
7793
|
-
} catch (
|
|
8201
|
+
} catch (e27) {
|
|
7794
8202
|
}
|
|
7795
8203
|
}
|
|
7796
8204
|
/**
|
|
@@ -7805,9 +8213,9 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7805
8213
|
*/
|
|
7806
8214
|
notifyNetworkStatistics() {
|
|
7807
8215
|
try {
|
|
7808
|
-
void Promise.resolve(_optionalChain([this, 'access',
|
|
8216
|
+
void Promise.resolve(_optionalChain([this, 'access', _527 => _527.networkStatisticsListener, 'optionalCall', _528 => _528(this.networkStatistics)])).catch(() => {
|
|
7809
8217
|
});
|
|
7810
|
-
} catch (
|
|
8218
|
+
} catch (e28) {
|
|
7811
8219
|
}
|
|
7812
8220
|
}
|
|
7813
8221
|
/**
|
|
@@ -7825,15 +8233,19 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7825
8233
|
*/
|
|
7826
8234
|
notifyLocalVideoStatistics() {
|
|
7827
8235
|
try {
|
|
7828
|
-
void Promise.resolve(_optionalChain([this, 'access',
|
|
8236
|
+
void Promise.resolve(_optionalChain([this, 'access', _529 => _529.localVideoStatisticsListener, 'optionalCall', _530 => _530(this.localVideoStatistics)])).catch(() => {
|
|
7829
8237
|
});
|
|
7830
|
-
} catch (
|
|
8238
|
+
} catch (e29) {
|
|
7831
8239
|
}
|
|
7832
8240
|
}
|
|
7833
8241
|
/**
|
|
7834
8242
|
* 停止接收媒体统计并清空各类快照,仅对曾有数据的统计发出清空通知。
|
|
7835
8243
|
*/
|
|
7836
8244
|
clearVideoStatistics() {
|
|
8245
|
+
_optionalChain([this, 'access', _531 => _531.qualityController, 'optionalAccess', _532 => _532.stop, 'call', _533 => _533()]);
|
|
8246
|
+
_optionalChain([this, 'access', _534 => _534.downlinkQualityController, 'optionalAccess', _535 => _535.stop, 'call', _536 => _536()]);
|
|
8247
|
+
this.downlinkQualityState = void 0;
|
|
8248
|
+
this.adaptiveQualityRevision++;
|
|
7837
8249
|
this.acceptsVideoStatistics = false;
|
|
7838
8250
|
const hadNetworkStatistics = this.networkStatistics !== void 0;
|
|
7839
8251
|
this.networkStatistics = void 0;
|
|
@@ -7899,7 +8311,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7899
8311
|
const completeCamera = this.launchTimer.startCamera();
|
|
7900
8312
|
this.clearVideoStatistics();
|
|
7901
8313
|
this.disposePermissionWatch();
|
|
7902
|
-
const permissionWatch = await watchMediaPermissionPrompt(_nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
8314
|
+
const permissionWatch = await watchMediaPermissionPrompt(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _537 => _537.useMicrophone]), () => ( false)));
|
|
7903
8315
|
if (permissionWatch) {
|
|
7904
8316
|
const completePermission = this.launchTimer.startPermission();
|
|
7905
8317
|
void permissionWatch.decided.then(() => completePermission()).catch(() => {
|
|
@@ -7916,7 +8328,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7916
8328
|
throw error;
|
|
7917
8329
|
}
|
|
7918
8330
|
token.ensureCurrent();
|
|
7919
|
-
this.generationVideoFormat = _optionalChain([stream, 'access',
|
|
8331
|
+
this.generationVideoFormat = _optionalChain([stream, 'access', _538 => _538.videoTrack, 'optionalAccess', _539 => _539.videoFormat]);
|
|
7920
8332
|
completeCamera();
|
|
7921
8333
|
this.cameraController.setPreviewReadyHandler((isCurrent) => {
|
|
7922
8334
|
void this.coordinator.localPreviewDidBecomeReady(isCurrent);
|
|
@@ -7937,7 +8349,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7937
8349
|
this.clearVideoStatistics();
|
|
7938
8350
|
await this.rtcManager.initialize();
|
|
7939
8351
|
token.ensureCurrent();
|
|
7940
|
-
this.generationVideoFormat = _optionalChain([stream, 'access',
|
|
8352
|
+
this.generationVideoFormat = _optionalChain([stream, 'access', _540 => _540.videoTrack, 'optionalAccess', _541 => _541.videoFormat]);
|
|
7941
8353
|
await this.coordinator.commit(new RealtimeState({ connectionState: "Ready" /* ready */ }), token);
|
|
7942
8354
|
return stream;
|
|
7943
8355
|
});
|
|
@@ -7963,7 +8375,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7963
8375
|
audioTrack: this.localVideoController.audioTrack
|
|
7964
8376
|
});
|
|
7965
8377
|
token.ensureCurrent();
|
|
7966
|
-
this.generationVideoFormat = _optionalChain([stream, 'access',
|
|
8378
|
+
this.generationVideoFormat = _optionalChain([stream, 'access', _542 => _542.videoTrack, 'optionalAccess', _543 => _543.videoFormat]);
|
|
7967
8379
|
await this.coordinator.commit(new RealtimeState({ connectionState: "Ready" /* ready */ }), token);
|
|
7968
8380
|
return stream;
|
|
7969
8381
|
});
|
|
@@ -7986,7 +8398,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7986
8398
|
* 移除媒体权限弹窗观察;授权决定已记录或不再需要观察时调用。
|
|
7987
8399
|
*/
|
|
7988
8400
|
disposePermissionWatch() {
|
|
7989
|
-
_optionalChain([this, 'access',
|
|
8401
|
+
_optionalChain([this, 'access', _544 => _544.permissionWatchDispose, 'optionalCall', _545 => _545()]);
|
|
7990
8402
|
this.permissionWatchDispose = void 0;
|
|
7991
8403
|
}
|
|
7992
8404
|
/**
|
|
@@ -7995,18 +8407,94 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
7995
8407
|
*
|
|
7996
8408
|
* @throws 无本地相机或文件视频流、参数无效、操作冲突或底层编码更新失败时抛错。
|
|
7997
8409
|
*/
|
|
7998
|
-
async
|
|
8410
|
+
async updateUplinkVideoFormat(videoFormat) {
|
|
7999
8411
|
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
8000
8412
|
const track = _nullishCoalesce(this.localVideoController.currentTrack, () => ( this.cameraController.currentTrack));
|
|
8001
|
-
const previousFormat = _optionalChain([track, 'optionalAccess',
|
|
8413
|
+
const previousFormat = _optionalChain([track, 'optionalAccess', _546 => _546.videoFormat]);
|
|
8002
8414
|
if (!track || !previousFormat) {
|
|
8003
8415
|
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Local camera or file video stream is not started");
|
|
8004
8416
|
}
|
|
8005
8417
|
videoFormat.validate();
|
|
8006
|
-
|
|
8418
|
+
_optionalChain([this, 'access', _547 => _547.qualityController, 'optionalAccess', _548 => _548.stop, 'call', _549 => _549()]);
|
|
8419
|
+
await this.streamController.updateUplinkVideoFormat(videoFormat);
|
|
8007
8420
|
token.ensureCurrent();
|
|
8008
8421
|
_nullishCoalesce(this.generationVideoFormat, () => ( (this.generationVideoFormat = previousFormat)));
|
|
8009
8422
|
track.updateVideoFormat(videoFormat);
|
|
8423
|
+
this.qualityStates.set(track, { baseline: videoFormat, level: 1 });
|
|
8424
|
+
_optionalChain([this, 'access', _550 => _550.qualityHistory, 'optionalAccess', _551 => _551.write, 'call', _552 => _552("uplink", 1)]);
|
|
8425
|
+
});
|
|
8426
|
+
}
|
|
8427
|
+
/** 已连接时仅替换帧率;与其他配置及生命周期操作共享同一操作租约。 */
|
|
8428
|
+
async updateUplinkFrameRate(fps) {
|
|
8429
|
+
await this.coordinator.run("configuration" /* configuration */, void 0, async (token) => {
|
|
8430
|
+
_optionalChain([this, 'access', _553 => _553.qualityController, 'optionalAccess', _554 => _554.stop, 'call', _555 => _555()]);
|
|
8431
|
+
await this.applyUplinkFrameRate(fps, token);
|
|
8432
|
+
const track = this.currentLocalTrack;
|
|
8433
|
+
if (_optionalChain([track, 'optionalAccess', _556 => _556.videoFormat])) {
|
|
8434
|
+
this.qualityStates.set(track, { baseline: track.videoFormat, level: 1 });
|
|
8435
|
+
_optionalChain([this, 'access', _557 => _557.qualityHistory, 'optionalAccess', _558 => _558.write, 'call', _559 => _559("uplink", 1)]);
|
|
8436
|
+
}
|
|
8437
|
+
});
|
|
8438
|
+
}
|
|
8439
|
+
/** 手动仅调帧接口,成功后的当前格式将成为新的自适应 L1 基准。 */
|
|
8440
|
+
async applyUplinkFrameRate(fps, token) {
|
|
8441
|
+
const track = _nullishCoalesce(this.localVideoController.currentTrack, () => ( this.cameraController.currentTrack));
|
|
8442
|
+
const previous = _optionalChain([track, 'optionalAccess', _560 => _560.videoFormat]);
|
|
8443
|
+
const state2 = this.currentState.connectionState;
|
|
8444
|
+
if (!track || !previous || state2 !== "Connected" /* connected */ && state2 !== "Generating" /* generating */) {
|
|
8445
|
+
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Frame rate updates require a connected local camera or file stream");
|
|
8446
|
+
}
|
|
8447
|
+
if (!Number.isFinite(fps) || fps <= 0) {
|
|
8448
|
+
throw new XmaxError("INVALID_CONFIGURATION" /* invalidConfiguration */, "Video frame rate must be greater than zero");
|
|
8449
|
+
}
|
|
8450
|
+
const format = await this.streamController.updateUplinkFrameRate(fps);
|
|
8451
|
+
token.ensureCurrent();
|
|
8452
|
+
_nullishCoalesce(this.generationVideoFormat, () => ( (this.generationVideoFormat = previous)));
|
|
8453
|
+
track.updateVideoFormat(format);
|
|
8454
|
+
}
|
|
8455
|
+
/** 上下行独立判断;串行应用同一原始事件,避免同时降档争抢配置租约。 */
|
|
8456
|
+
handleAdaptiveQuality(statistics) {
|
|
8457
|
+
const revision = ++this.adaptiveQualityRevision;
|
|
8458
|
+
const controller = this.qualityController;
|
|
8459
|
+
const downlink = this.downlinkQualityController;
|
|
8460
|
+
if (!controller || !downlink) return;
|
|
8461
|
+
const taskID = this.currentState.taskID;
|
|
8462
|
+
if (this.currentState.connectionState !== "Generating" /* generating */ || !taskID) {
|
|
8463
|
+
controller.stop();
|
|
8464
|
+
downlink.stop();
|
|
8465
|
+
return;
|
|
8466
|
+
}
|
|
8467
|
+
if (!statistics || this.coordinator.isBusy || this.adaptiveQualityPending) {
|
|
8468
|
+
controller.resetSamples();
|
|
8469
|
+
downlink.resetSamples();
|
|
8470
|
+
return;
|
|
8471
|
+
}
|
|
8472
|
+
const track = _nullishCoalesce(this.localVideoController.currentTrack, () => ( this.cameraController.currentTrack));
|
|
8473
|
+
if (!track) {
|
|
8474
|
+
controller.stop();
|
|
8475
|
+
} else if (!controller.snapshot.active) {
|
|
8476
|
+
const format = track.videoFormat;
|
|
8477
|
+
if (format) {
|
|
8478
|
+
const state3 = _nullishCoalesce(this.qualityStates.get(track), () => ( { baseline: format, level: 1 }));
|
|
8479
|
+
this.qualityStates.set(track, state3);
|
|
8480
|
+
controller.start(state3.level);
|
|
8481
|
+
}
|
|
8482
|
+
}
|
|
8483
|
+
const state2 = this.downlinkQualityState;
|
|
8484
|
+
if (state2 && !downlink.snapshot.active) downlink.start(state2.level);
|
|
8485
|
+
const sampleAt = performance.now();
|
|
8486
|
+
this.adaptiveQualityPending = true;
|
|
8487
|
+
void (async () => {
|
|
8488
|
+
await controller.observe(statistics.uplinkQuality, sampleAt).catch(() => {
|
|
8489
|
+
});
|
|
8490
|
+
if (revision !== this.adaptiveQualityRevision || this.currentState.taskID !== taskID || state2 !== this.downlinkQualityState || this.currentState.connectionState !== "Generating" /* generating */ || this.coordinator.isBusy) {
|
|
8491
|
+
downlink.resetSamples();
|
|
8492
|
+
return;
|
|
8493
|
+
}
|
|
8494
|
+
await downlink.observe(statistics.downlinkQuality, sampleAt).catch(() => {
|
|
8495
|
+
});
|
|
8496
|
+
})().finally(() => {
|
|
8497
|
+
this.adaptiveQualityPending = false;
|
|
8010
8498
|
});
|
|
8011
8499
|
}
|
|
8012
8500
|
/**
|
|
@@ -8046,9 +8534,9 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8046
8534
|
"cameraSwitch" /* cameraSwitch */,
|
|
8047
8535
|
void 0,
|
|
8048
8536
|
async (token) => {
|
|
8537
|
+
_optionalChain([this, 'access', _561 => _561.qualityController, 'optionalAccess', _562 => _562.stop, 'call', _563 => _563()]);
|
|
8049
8538
|
const stream = await this.cameraController.switchCamera();
|
|
8050
8539
|
token.ensureCurrent();
|
|
8051
|
-
this.connectionManager.updateRemoteMirror();
|
|
8052
8540
|
return stream;
|
|
8053
8541
|
}
|
|
8054
8542
|
);
|
|
@@ -8116,6 +8604,7 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8116
8604
|
if (currentState.connectionState === "Generating" /* generating */) {
|
|
8117
8605
|
await this.generationManager.update(currentState.taskID, {
|
|
8118
8606
|
videoFormat,
|
|
8607
|
+
targetSize: this.downlinkQualityController ? _optionalChain([this, 'access', _564 => _564.downlinkQualityState, 'optionalAccess', _565 => _565.size]) : void 0,
|
|
8119
8608
|
context: options.context
|
|
8120
8609
|
});
|
|
8121
8610
|
token.ensureCurrent();
|
|
@@ -8153,6 +8642,15 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8153
8642
|
this.clearVideoStatistics();
|
|
8154
8643
|
await this.coordinator.terminate(1 /* all */);
|
|
8155
8644
|
}
|
|
8645
|
+
/** 仅为尚无档位记录的本地上行选择初始档位;不应用配置或覆盖重连状态。 */
|
|
8646
|
+
resolveInitialUplinkQuality(track) {
|
|
8647
|
+
if (!this.qualityController) return void 0;
|
|
8648
|
+
if (this.networkVideoController.currentTrack) return void 0;
|
|
8649
|
+
if (this.qualityStates.has(track)) return void 0;
|
|
8650
|
+
const baseline = track.videoFormat;
|
|
8651
|
+
if (!baseline) return void 0;
|
|
8652
|
+
return { baseline, level: this.qualityHistory.read("uplink") };
|
|
8653
|
+
}
|
|
8156
8654
|
/**
|
|
8157
8655
|
* 建立实时连接:创建会话、进房发布、启动心跳并准备远端渲染轨道。
|
|
8158
8656
|
*
|
|
@@ -8188,9 +8686,19 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8188
8686
|
});
|
|
8189
8687
|
beforePublish = () => cameraReady;
|
|
8190
8688
|
}
|
|
8689
|
+
const initialQuality = this.resolveInitialUplinkQuality(localTrack);
|
|
8690
|
+
const initialFormat = initialQuality ? qualityVideoFormat(initialQuality.baseline, initialQuality.level) : void 0;
|
|
8191
8691
|
const remote = await this.connectionManager.connect({
|
|
8192
8692
|
localTrack,
|
|
8193
|
-
remoteVideoFormat: this.generationVideoFormat,
|
|
8693
|
+
remoteVideoFormat: _nullishCoalesce(this.generationVideoFormat, () => ( localTrack.videoFormat)),
|
|
8694
|
+
localVideoFormat: initialFormat,
|
|
8695
|
+
onVideoEncoderConfigured: () => {
|
|
8696
|
+
if (!initialQuality || !initialFormat) return;
|
|
8697
|
+
_nullishCoalesce(this.generationVideoFormat, () => ( (this.generationVideoFormat = initialQuality.baseline)));
|
|
8698
|
+
localTrack.updateVideoFormat(initialFormat);
|
|
8699
|
+
this.qualityStates.set(localTrack, initialQuality);
|
|
8700
|
+
_optionalChain([this, 'access', _566 => _566.qualityHistory, 'optionalAccess', _567 => _567.write, 'call', _568 => _568("uplink", initialQuality.level)]);
|
|
8701
|
+
},
|
|
8194
8702
|
model: this.options.model,
|
|
8195
8703
|
includeLocalAudio: this.localVideoController.isActive ? this.localVideoController.audioTrack !== void 0 : !this.networkVideoController.currentTrack && this.cameraController.useMicrophone,
|
|
8196
8704
|
publishLocalMedia: !this.networkVideoController.currentTrack,
|
|
@@ -8218,14 +8726,18 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8218
8726
|
*/
|
|
8219
8727
|
async performStartGeneration(token, videoFormat, context) {
|
|
8220
8728
|
token.setFailureScope(0 /* connection */);
|
|
8221
|
-
|
|
8729
|
+
const initialLevel = _nullishCoalesce(_optionalChain([this, 'access', _569 => _569.qualityHistory, 'optionalAccess', _570 => _570.read, 'call', _571 => _571("downlink")]), () => ( 1));
|
|
8730
|
+
const targetSize = this.downlinkQualityController ? qualityVideoSize(videoFormat, initialLevel) : void 0;
|
|
8731
|
+
await this.prepareFrameInterpolation(_nullishCoalesce(targetSize, () => ( videoFormat)), token);
|
|
8222
8732
|
const completeFirstFrame = this.launchTimer.startFirstFrame();
|
|
8223
8733
|
this.remoteFrameDisplayHandler = () => {
|
|
8224
8734
|
if (!token.signal.aborted) completeFirstFrame();
|
|
8225
8735
|
};
|
|
8226
8736
|
const taskID = await this.generationManager.start({
|
|
8227
8737
|
videoFormat,
|
|
8738
|
+
targetSize,
|
|
8228
8739
|
context,
|
|
8740
|
+
mirror: this.currentLocalTrack === this.cameraController.currentTrack && _optionalChain([this, 'access', _572 => _572.cameraController, 'access', _573 => _573.currentTrack, 'optionalAccess', _574 => _574.position]) === "front" /* front */,
|
|
8229
8741
|
signal: token.signal,
|
|
8230
8742
|
ensureCurrent: () => token.ensureCurrent(),
|
|
8231
8743
|
onStartSent: this.localVideoController.isActive ? async () => {
|
|
@@ -8242,10 +8754,18 @@ var XmaxRealtimeManager = class _XmaxRealtimeManager {
|
|
|
8242
8754
|
if (!sessionID) {
|
|
8243
8755
|
throw new XmaxError("SESSION_ERROR" /* sessionError */, "Realtime session is unavailable");
|
|
8244
8756
|
}
|
|
8757
|
+
_optionalChain([this, 'access', _575 => _575.downlinkQualityController, 'optionalAccess', _576 => _576.stop, 'call', _577 => _577()]);
|
|
8758
|
+
this.downlinkQualityState = {
|
|
8759
|
+
taskID,
|
|
8760
|
+
baseline: videoFormat,
|
|
8761
|
+
level: initialLevel,
|
|
8762
|
+
size: _nullishCoalesce(targetSize, () => ( { width: videoFormat.width, height: videoFormat.height }))
|
|
8763
|
+
};
|
|
8245
8764
|
await this.coordinator.commit(
|
|
8246
8765
|
new RealtimeState({ connectionState: "Generating" /* generating */, sessionID, taskID }),
|
|
8247
8766
|
token
|
|
8248
8767
|
);
|
|
8768
|
+
_optionalChain([this, 'access', _578 => _578.qualityHistory, 'optionalAccess', _579 => _579.write, 'call', _580 => _580("downlink", initialLevel)]);
|
|
8249
8769
|
const onFinish = this.networkVideoController.onFinish;
|
|
8250
8770
|
if (this.networkVideoController.currentTrack) {
|
|
8251
8771
|
this.streamController.activateNetworkVideoCompletion(onFinish && (() => {
|
|
@@ -8397,7 +8917,7 @@ var NonRealtimeTaskService = class {
|
|
|
8397
8917
|
* 提交一次任务;请求结果不确定时也不自动重试,以免重复扣费。
|
|
8398
8918
|
*/
|
|
8399
8919
|
async submitTask(options) {
|
|
8400
|
-
const model = _optionalChain([options, 'access',
|
|
8920
|
+
const model = _optionalChain([options, 'access', _581 => _581.model, 'optionalAccess', _582 => _582.trim, 'call', _583 => _583()]);
|
|
8401
8921
|
if (!model) {
|
|
8402
8922
|
invalid("Model must not be empty");
|
|
8403
8923
|
}
|
|
@@ -8490,7 +9010,7 @@ function validateURL(value) {
|
|
|
8490
9010
|
let url;
|
|
8491
9011
|
try {
|
|
8492
9012
|
url = new URL(value.trim());
|
|
8493
|
-
} catch (
|
|
9013
|
+
} catch (e30) {
|
|
8494
9014
|
return invalid("Resource must be an uploaded HTTP(S) URL");
|
|
8495
9015
|
}
|
|
8496
9016
|
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) {
|
|
@@ -8537,7 +9057,7 @@ function parseTask(value) {
|
|
|
8537
9057
|
const uid = field(data, "uid", "string");
|
|
8538
9058
|
const status = field(data, "status", "string");
|
|
8539
9059
|
const quality = field(data, "quality", "string");
|
|
8540
|
-
if (!_optionalChain([uid, 'optionalAccess',
|
|
9060
|
+
if (!_optionalChain([uid, 'optionalAccess', _584 => _584.trim, 'call', _585 => _585()]) || !Object.values(NonRealtimeTaskStatus).includes(status)) {
|
|
8541
9061
|
malformed("Missing task UID or invalid status");
|
|
8542
9062
|
}
|
|
8543
9063
|
if (quality !== void 0 && !Object.values(NonRealtimeQuality).includes(quality)) {
|
|
@@ -8619,7 +9139,7 @@ var XmaxNonRealtimeManager = class {
|
|
|
8619
9139
|
* 取得任务快照,不把服务端失败终态当成查询失败。
|
|
8620
9140
|
*/
|
|
8621
9141
|
getTask(taskUid, options) {
|
|
8622
|
-
return this.tasks.getTask(taskUid, _optionalChain([options, 'optionalAccess',
|
|
9142
|
+
return this.tasks.getTask(taskUid, _optionalChain([options, 'optionalAccess', _586 => _586.signal]));
|
|
8623
9143
|
}
|
|
8624
9144
|
/**
|
|
8625
9145
|
* 批量取得任务快照。
|
|
@@ -8653,8 +9173,8 @@ var XmaxNonRealtimeManager = class {
|
|
|
8653
9173
|
const controller = new AbortController();
|
|
8654
9174
|
let timedOut = false;
|
|
8655
9175
|
const abort = () => controller.abort();
|
|
8656
|
-
_optionalChain([options, 'access',
|
|
8657
|
-
if (_optionalChain([options, 'access',
|
|
9176
|
+
_optionalChain([options, 'access', _587 => _587.signal, 'optionalAccess', _588 => _588.addEventListener, 'call', _589 => _589("abort", abort, { once: true })]);
|
|
9177
|
+
if (_optionalChain([options, 'access', _590 => _590.signal, 'optionalAccess', _591 => _591.aborted])) {
|
|
8658
9178
|
abort();
|
|
8659
9179
|
}
|
|
8660
9180
|
const timer = options.timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
@@ -8680,9 +9200,9 @@ var XmaxNonRealtimeManager = class {
|
|
|
8680
9200
|
ensureActive(controller.signal);
|
|
8681
9201
|
failures = 0;
|
|
8682
9202
|
try {
|
|
8683
|
-
void Promise.resolve(_optionalChain([options, 'access',
|
|
9203
|
+
void Promise.resolve(_optionalChain([options, 'access', _592 => _592.onTaskUpdated, 'optionalCall', _593 => _593(task)])).catch(() => {
|
|
8684
9204
|
});
|
|
8685
|
-
} catch (
|
|
9205
|
+
} catch (e31) {
|
|
8686
9206
|
}
|
|
8687
9207
|
ensureActive(controller.signal);
|
|
8688
9208
|
if (task.status === "error" /* error */) {
|
|
@@ -8710,7 +9230,7 @@ var XmaxNonRealtimeManager = class {
|
|
|
8710
9230
|
throw error;
|
|
8711
9231
|
} finally {
|
|
8712
9232
|
clearTimeout(timer);
|
|
8713
|
-
_optionalChain([options, 'access',
|
|
9233
|
+
_optionalChain([options, 'access', _594 => _594.signal, 'optionalAccess', _595 => _595.removeEventListener, 'call', _596 => _596("abort", abort)]);
|
|
8714
9234
|
}
|
|
8715
9235
|
}
|
|
8716
9236
|
};
|
|
@@ -8754,13 +9274,13 @@ function isTransient(error) {
|
|
|
8754
9274
|
}
|
|
8755
9275
|
function isResultAvailable(task) {
|
|
8756
9276
|
const result = task.result;
|
|
8757
|
-
if (!_optionalChain([result, 'optionalAccess',
|
|
9277
|
+
if (!_optionalChain([result, 'optionalAccess', _597 => _597.url, 'optionalAccess', _598 => _598.trim, 'call', _599 => _599()]) || _optionalChain([result, 'access', _600 => _600.uploadError, 'optionalAccess', _601 => _601.trim, 'call', _602 => _602()]) || result.uploadStatus !== void 0 && result.uploadStatus !== "success") {
|
|
8758
9278
|
return false;
|
|
8759
9279
|
}
|
|
8760
9280
|
try {
|
|
8761
9281
|
const url = new URL(result.url);
|
|
8762
9282
|
return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password;
|
|
8763
|
-
} catch (
|
|
9283
|
+
} catch (e32) {
|
|
8764
9284
|
return false;
|
|
8765
9285
|
}
|
|
8766
9286
|
}
|
|
@@ -8884,6 +9404,146 @@ var VideoContentMode = /* @__PURE__ */ ((VideoContentMode2) => {
|
|
|
8884
9404
|
return VideoContentMode2;
|
|
8885
9405
|
})(VideoContentMode || {});
|
|
8886
9406
|
|
|
9407
|
+
// src/Render/Video/RenderStatisticsController.ts
|
|
9408
|
+
var RenderStatisticsController = class {
|
|
9409
|
+
/**
|
|
9410
|
+
* 绑定用于观察原视频帧的元素,调用 start 后才开始采集。
|
|
9411
|
+
*/
|
|
9412
|
+
constructor(video) {
|
|
9413
|
+
__publicField(this, "video", video);
|
|
9414
|
+
/**
|
|
9415
|
+
* 统计回调
|
|
9416
|
+
*/
|
|
9417
|
+
__publicField(this, "handler");
|
|
9418
|
+
/**
|
|
9419
|
+
* 帧观察与采样生命周期
|
|
9420
|
+
*/
|
|
9421
|
+
__publicField(this, "timer");
|
|
9422
|
+
__publicField(this, "callbackID");
|
|
9423
|
+
__publicField(this, "sequence", 0);
|
|
9424
|
+
/**
|
|
9425
|
+
* 采样窗口与输出方式
|
|
9426
|
+
*/
|
|
9427
|
+
__publicField(this, "startedAt", 0);
|
|
9428
|
+
__publicField(this, "originalFrames", 0);
|
|
9429
|
+
__publicField(this, "interpolatedFrames", 0);
|
|
9430
|
+
__publicField(this, "interpolationActive", false);
|
|
9431
|
+
__publicField(this, "previousPresentedFrames");
|
|
9432
|
+
}
|
|
9433
|
+
/**
|
|
9434
|
+
* 独立于统计面板可见性采集;没有监听者时不占用定时器。
|
|
9435
|
+
*/
|
|
9436
|
+
start() {
|
|
9437
|
+
if (this.timer !== void 0 || !this.video.srcObject && !this.video.getAttribute("src") || !this.handler || typeof this.video.requestVideoFrameCallback !== "function") {
|
|
9438
|
+
return;
|
|
9439
|
+
}
|
|
9440
|
+
this.reset();
|
|
9441
|
+
const sequence = this.sequence;
|
|
9442
|
+
const observe = () => {
|
|
9443
|
+
this.callbackID = this.video.requestVideoFrameCallback((_now, metadata) => {
|
|
9444
|
+
if (sequence !== this.sequence) {
|
|
9445
|
+
return;
|
|
9446
|
+
}
|
|
9447
|
+
this.callbackID = void 0;
|
|
9448
|
+
if (!this.interpolationActive && !document.hidden) {
|
|
9449
|
+
this.recordVideoFrames(metadata.presentedFrames);
|
|
9450
|
+
} else {
|
|
9451
|
+
this.previousPresentedFrames = void 0;
|
|
9452
|
+
}
|
|
9453
|
+
observe();
|
|
9454
|
+
});
|
|
9455
|
+
};
|
|
9456
|
+
observe();
|
|
9457
|
+
this.timer = setInterval(() => this.sample(), 1e3);
|
|
9458
|
+
}
|
|
9459
|
+
/**
|
|
9460
|
+
* 切换输出方式并清空采样窗口,避免原视频和画布重复计数。
|
|
9461
|
+
*/
|
|
9462
|
+
setInterpolationActive(active) {
|
|
9463
|
+
this.interpolationActive = active;
|
|
9464
|
+
this.reset();
|
|
9465
|
+
}
|
|
9466
|
+
/**
|
|
9467
|
+
* 记录实际提交到画布的原帧或插值帧,不统计未呈现的计算结果。
|
|
9468
|
+
*/
|
|
9469
|
+
recordCanvasFrame(interpolated) {
|
|
9470
|
+
if (interpolated) {
|
|
9471
|
+
this.interpolatedFrames++;
|
|
9472
|
+
} else {
|
|
9473
|
+
this.originalFrames++;
|
|
9474
|
+
}
|
|
9475
|
+
}
|
|
9476
|
+
/**
|
|
9477
|
+
* 按浏览器累计呈现帧数的增量统计,包含两次回调之间已呈现但未回调的帧。
|
|
9478
|
+
*/
|
|
9479
|
+
recordVideoFrames(presentedFrames) {
|
|
9480
|
+
if (!Number.isSafeInteger(presentedFrames) || presentedFrames < 0) {
|
|
9481
|
+
this.previousPresentedFrames = void 0;
|
|
9482
|
+
return;
|
|
9483
|
+
}
|
|
9484
|
+
const previous = this.previousPresentedFrames;
|
|
9485
|
+
this.previousPresentedFrames = presentedFrames;
|
|
9486
|
+
if (previous === void 0 || presentedFrames < previous) {
|
|
9487
|
+
this.originalFrames += presentedFrames > 0 ? 1 : 0;
|
|
9488
|
+
return;
|
|
9489
|
+
}
|
|
9490
|
+
this.originalFrames += presentedFrames - previous;
|
|
9491
|
+
}
|
|
9492
|
+
/**
|
|
9493
|
+
* 取消采样及帧观察,忽略已排队的旧回调并清空对外统计。
|
|
9494
|
+
*/
|
|
9495
|
+
stop() {
|
|
9496
|
+
this.sequence++;
|
|
9497
|
+
clearInterval(this.timer);
|
|
9498
|
+
this.timer = void 0;
|
|
9499
|
+
if (this.callbackID !== void 0) {
|
|
9500
|
+
this.video.cancelVideoFrameCallback(this.callbackID);
|
|
9501
|
+
}
|
|
9502
|
+
this.callbackID = void 0;
|
|
9503
|
+
this.reset();
|
|
9504
|
+
}
|
|
9505
|
+
/**
|
|
9506
|
+
* 清空采样计数,避免换流或切换输出方式时混入旧数据。
|
|
9507
|
+
*/
|
|
9508
|
+
reset() {
|
|
9509
|
+
this.startedAt = performance.now();
|
|
9510
|
+
this.originalFrames = 0;
|
|
9511
|
+
this.interpolatedFrames = 0;
|
|
9512
|
+
this.previousPresentedFrames = void 0;
|
|
9513
|
+
this.notify(void 0);
|
|
9514
|
+
}
|
|
9515
|
+
/**
|
|
9516
|
+
* 按实际经过的时间计算帧率;没有新呈现时输出 0,后台页面不报告帧率。
|
|
9517
|
+
*/
|
|
9518
|
+
sample() {
|
|
9519
|
+
const now = performance.now();
|
|
9520
|
+
const seconds = (now - this.startedAt) / 1e3;
|
|
9521
|
+
if (document.hidden || seconds <= 0) {
|
|
9522
|
+
this.reset();
|
|
9523
|
+
return;
|
|
9524
|
+
}
|
|
9525
|
+
const statistics = Object.freeze({
|
|
9526
|
+
source: this.interpolationActive ? "canvas" : "video",
|
|
9527
|
+
frameRate: (this.originalFrames + this.interpolatedFrames) / seconds,
|
|
9528
|
+
originalFrameRate: this.originalFrames / seconds,
|
|
9529
|
+
interpolatedFrameRate: this.interpolatedFrames / seconds
|
|
9530
|
+
});
|
|
9531
|
+
this.startedAt = now;
|
|
9532
|
+
this.originalFrames = 0;
|
|
9533
|
+
this.interpolatedFrames = 0;
|
|
9534
|
+
this.notify(statistics);
|
|
9535
|
+
}
|
|
9536
|
+
/**
|
|
9537
|
+
* 隔离接入方回调异常,避免影响播放和后续采样。
|
|
9538
|
+
*/
|
|
9539
|
+
notify(statistics) {
|
|
9540
|
+
try {
|
|
9541
|
+
_optionalChain([this, 'access', _603 => _603.handler, 'optionalCall', _604 => _604(statistics)]);
|
|
9542
|
+
} catch (e33) {
|
|
9543
|
+
}
|
|
9544
|
+
}
|
|
9545
|
+
};
|
|
9546
|
+
|
|
8887
9547
|
// ../../node_modules/.pnpm/framegen@1.4.0/node_modules/framegen/rt.js
|
|
8888
9548
|
var WG = 8;
|
|
8889
9549
|
var texBgSeq = 0;
|
|
@@ -11006,11 +11666,11 @@ var _FrameInterpolationManager = class _FrameInterpolationManager {
|
|
|
11006
11666
|
if (this.destroyed) return;
|
|
11007
11667
|
this.destroyed = true;
|
|
11008
11668
|
this.device.removeEventListener("uncapturederror", this.onGPUError);
|
|
11009
|
-
_optionalChain([this, 'access',
|
|
11669
|
+
_optionalChain([this, 'access', _605 => _605.runtime, 'optionalAccess', _606 => _606.destroy, 'call', _607 => _607()]);
|
|
11010
11670
|
this.runtime = void 0;
|
|
11011
11671
|
this.textures.forEach((texture) => texture.destroy());
|
|
11012
11672
|
this.textures = [];
|
|
11013
|
-
_optionalChain([this, 'access',
|
|
11673
|
+
_optionalChain([this, 'access', _608 => _608.context, 'optionalAccess', _609 => _609.unconfigure, 'call', _610 => _610()]);
|
|
11014
11674
|
this.device.destroy();
|
|
11015
11675
|
}
|
|
11016
11676
|
};
|
|
@@ -11047,6 +11707,10 @@ var RemoteVideoFramePipeline = class {
|
|
|
11047
11707
|
__publicField(this, "previousPresented");
|
|
11048
11708
|
__publicField(this, "slowPairs", 0);
|
|
11049
11709
|
__publicField(this, "active", false);
|
|
11710
|
+
/**
|
|
11711
|
+
* 帧时间基准:媒体时间异常后,本管线持续使用回调时钟,避免反复切换。
|
|
11712
|
+
*/
|
|
11713
|
+
__publicField(this, "timeSource", "mediaTime");
|
|
11050
11714
|
/** vsync 显示节拍:弹出到点的帧并显示最新的一张。 */
|
|
11051
11715
|
__publicField(this, "tick", (now) => {
|
|
11052
11716
|
if (this.stopped) return;
|
|
@@ -11093,8 +11757,8 @@ var RemoteVideoFramePipeline = class {
|
|
|
11093
11757
|
if (!this.loading) void this.initialize();
|
|
11094
11758
|
return;
|
|
11095
11759
|
}
|
|
11096
|
-
const time =
|
|
11097
|
-
if (
|
|
11760
|
+
const time = this.resolveFrameTime(now, metadata);
|
|
11761
|
+
if (time === void 0) return;
|
|
11098
11762
|
const previous = this.previousTime;
|
|
11099
11763
|
const interval = previous === void 0 ? 0 : time - previous;
|
|
11100
11764
|
const consecutive = this.previousPresented === void 0 || metadata.presentedFrames === this.previousPresented + 1;
|
|
@@ -11119,6 +11783,22 @@ var RemoteVideoFramePipeline = class {
|
|
|
11119
11783
|
}
|
|
11120
11784
|
this.interpolate(previousSlot, slot, previous, time, interval);
|
|
11121
11785
|
}
|
|
11786
|
+
/**
|
|
11787
|
+
* 优先使用媒体时间;新帧的媒体时间异常时切换到单调回调时钟。
|
|
11788
|
+
*/
|
|
11789
|
+
resolveFrameTime(now, metadata) {
|
|
11790
|
+
if (this.previousPresented !== void 0 && metadata.presentedFrames <= this.previousPresented) {
|
|
11791
|
+
return void 0;
|
|
11792
|
+
}
|
|
11793
|
+
let time = this.timeSource === "mediaTime" ? metadata.mediaTime * 1e3 : now;
|
|
11794
|
+
if (!Number.isFinite(time) || this.previousTime !== void 0 && time <= this.previousTime) {
|
|
11795
|
+
if (this.timeSource === "callback" || !Number.isFinite(now)) return void 0;
|
|
11796
|
+
this.timeSource = "callback";
|
|
11797
|
+
this.resetTimeline(true);
|
|
11798
|
+
time = now;
|
|
11799
|
+
}
|
|
11800
|
+
return time;
|
|
11801
|
+
}
|
|
11122
11802
|
/** 帧按显示时间升序入队;同一时间的内容后到先出。 */
|
|
11123
11803
|
enqueue(frame) {
|
|
11124
11804
|
const index = this.queue.findIndex((queued) => queued.time >= frame.time);
|
|
@@ -11145,8 +11825,10 @@ var RemoteVideoFramePipeline = class {
|
|
|
11145
11825
|
this.fail(new Error("Interpolation exceeded the GPU frame budget for 5 consecutive pairs"));
|
|
11146
11826
|
return;
|
|
11147
11827
|
}
|
|
11148
|
-
if (this.position(performance.now()) >= midpoint)
|
|
11149
|
-
|
|
11828
|
+
if (this.position(performance.now()) >= midpoint) {
|
|
11829
|
+
return;
|
|
11830
|
+
}
|
|
11831
|
+
this.enqueue({ slot, time: midpoint, interpolated: true });
|
|
11150
11832
|
}).catch((error) => {
|
|
11151
11833
|
if (!this.stopped) this.fail(error);
|
|
11152
11834
|
});
|
|
@@ -11165,6 +11847,7 @@ var RemoteVideoFramePipeline = class {
|
|
|
11165
11847
|
this.displayedTime = frame.time;
|
|
11166
11848
|
this.canvas.style.visibility = "visible";
|
|
11167
11849
|
this.setActive(true);
|
|
11850
|
+
_optionalChain([this, 'access', _611 => _611.options, 'access', _612 => _612.onFramePresented, 'optionalCall', _613 => _613(_nullishCoalesce(frame.interpolated, () => ( false)))]);
|
|
11168
11851
|
}
|
|
11169
11852
|
async initialize() {
|
|
11170
11853
|
this.loading = true;
|
|
@@ -11192,13 +11875,15 @@ var RemoteVideoFramePipeline = class {
|
|
|
11192
11875
|
setActive(active) {
|
|
11193
11876
|
if (active === this.active) return;
|
|
11194
11877
|
this.active = active;
|
|
11195
|
-
_optionalChain([this, 'access',
|
|
11878
|
+
_optionalChain([this, 'access', _614 => _614.options, 'access', _615 => _615.onActiveChange, 'optionalCall', _616 => _616(active)]);
|
|
11196
11879
|
}
|
|
11197
|
-
resetTimeline() {
|
|
11880
|
+
resetTimeline(preserveGpuTimeout = false) {
|
|
11198
11881
|
this.generation++;
|
|
11199
11882
|
this.queue = [];
|
|
11200
|
-
|
|
11201
|
-
|
|
11883
|
+
if (!preserveGpuTimeout) {
|
|
11884
|
+
clearTimeout(this.stallTimer);
|
|
11885
|
+
this.stallTimer = void 0;
|
|
11886
|
+
}
|
|
11202
11887
|
if (this.raf !== void 0) cancelAnimationFrame(this.raf);
|
|
11203
11888
|
this.raf = void 0;
|
|
11204
11889
|
this.anchor = void 0;
|
|
@@ -11223,7 +11908,7 @@ var RemoteVideoFramePipeline = class {
|
|
|
11223
11908
|
this.callback = void 0;
|
|
11224
11909
|
clearTimeout(this.initializationTimer);
|
|
11225
11910
|
this.resetTimeline();
|
|
11226
|
-
_optionalChain([this, 'access',
|
|
11911
|
+
_optionalChain([this, 'access', _617 => _617.processor, 'optionalAccess', _618 => _618.destroy, 'call', _619 => _619()]);
|
|
11227
11912
|
this.processor = void 0;
|
|
11228
11913
|
}
|
|
11229
11914
|
};
|
|
@@ -11277,16 +11962,21 @@ var XmaxVideoView = class {
|
|
|
11277
11962
|
__publicField(this, "interpolationOptions");
|
|
11278
11963
|
__publicField(this, "interpolationPipeline");
|
|
11279
11964
|
__publicField(this, "interpolationCanvas");
|
|
11965
|
+
/**
|
|
11966
|
+
* 呈现统计组件
|
|
11967
|
+
*/
|
|
11968
|
+
__publicField(this, "statisticsController");
|
|
11280
11969
|
/**
|
|
11281
11970
|
* DOM 挂载状态
|
|
11282
11971
|
*/
|
|
11283
11972
|
__publicField(this, "detached", false);
|
|
11284
|
-
this.contentMode = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
11973
|
+
this.contentMode = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _620 => _620.videoContentMode]), () => ( "fill")) /* fill */;
|
|
11285
11974
|
this.element = document.createElement("div");
|
|
11286
11975
|
this.element.style.position = "relative";
|
|
11287
11976
|
this.element.style.overflow = "hidden";
|
|
11288
11977
|
this.element.style.backgroundColor = "black";
|
|
11289
11978
|
this.videoElement = document.createElement("video");
|
|
11979
|
+
this.statisticsController = new RenderStatisticsController(this.videoElement);
|
|
11290
11980
|
this.videoElement.autoplay = true;
|
|
11291
11981
|
this.videoElement.playsInline = true;
|
|
11292
11982
|
this.videoElement.muted = true;
|
|
@@ -11303,6 +11993,20 @@ var XmaxVideoView = class {
|
|
|
11303
11993
|
get track() {
|
|
11304
11994
|
return this.currentTrack;
|
|
11305
11995
|
}
|
|
11996
|
+
/**
|
|
11997
|
+
* 每秒接收当前视图的呈现统计;换流、卸载或不可统计时返回 undefined。
|
|
11998
|
+
*/
|
|
11999
|
+
get renderStatisticsHandler() {
|
|
12000
|
+
return this.statisticsController.handler;
|
|
12001
|
+
}
|
|
12002
|
+
/**
|
|
12003
|
+
* 更新统计回调,不影响播放;移除回调时停止采集。
|
|
12004
|
+
*/
|
|
12005
|
+
set renderStatisticsHandler(handler) {
|
|
12006
|
+
this.statisticsController.handler = handler;
|
|
12007
|
+
this.statisticsController.stop();
|
|
12008
|
+
this.startRenderStatistics();
|
|
12009
|
+
}
|
|
11306
12010
|
/**
|
|
11307
12011
|
* 解绑旧轨道后接入新轨道,并为新内容重新启用一次性首帧通知。
|
|
11308
12012
|
*/
|
|
@@ -11362,6 +12066,7 @@ var XmaxVideoView = class {
|
|
|
11362
12066
|
});
|
|
11363
12067
|
}
|
|
11364
12068
|
this.startInterpolation();
|
|
12069
|
+
this.startRenderStatistics();
|
|
11365
12070
|
if ((this.videoElement.srcObject || this.videoElement.getAttribute("src")) && !this.hasNotifiedFrameDisplay) {
|
|
11366
12071
|
this.armFrameDisplayNotification();
|
|
11367
12072
|
}
|
|
@@ -11371,6 +12076,7 @@ var XmaxVideoView = class {
|
|
|
11371
12076
|
*/
|
|
11372
12077
|
detach() {
|
|
11373
12078
|
this.detached = true;
|
|
12079
|
+
this.statisticsController.stop();
|
|
11374
12080
|
this.stopInterpolation();
|
|
11375
12081
|
this.cancelFrameDisplayNotification();
|
|
11376
12082
|
if (this.videoElement.getAttribute("src")) {
|
|
@@ -11382,6 +12088,7 @@ var XmaxVideoView = class {
|
|
|
11382
12088
|
* 设置网络视频预览;静音播放一次,不捕获或发布媒体轨道。 @internal
|
|
11383
12089
|
*/
|
|
11384
12090
|
setVideoURL(url) {
|
|
12091
|
+
this.statisticsController.stop();
|
|
11385
12092
|
this.stopInterpolation();
|
|
11386
12093
|
this.cancelFrameDisplayNotification();
|
|
11387
12094
|
this.hasNotifiedFrameDisplay = false;
|
|
@@ -11395,6 +12102,7 @@ var XmaxVideoView = class {
|
|
|
11395
12102
|
this.armFrameDisplayNotification();
|
|
11396
12103
|
}
|
|
11397
12104
|
this.videoElement.load();
|
|
12105
|
+
this.startRenderStatistics();
|
|
11398
12106
|
}
|
|
11399
12107
|
/**
|
|
11400
12108
|
* 直接设置渲染用的媒体流(绑定管线和直接渲染共用)。 @internal
|
|
@@ -11403,6 +12111,7 @@ var XmaxVideoView = class {
|
|
|
11403
12111
|
if (this.videoElement.srcObject === stream) {
|
|
11404
12112
|
return;
|
|
11405
12113
|
}
|
|
12114
|
+
this.statisticsController.stop();
|
|
11406
12115
|
this.stopInterpolation();
|
|
11407
12116
|
this.cancelFrameDisplayNotification();
|
|
11408
12117
|
this.hasNotifiedFrameDisplay = false;
|
|
@@ -11411,6 +12120,7 @@ var XmaxVideoView = class {
|
|
|
11411
12120
|
this.videoElement.autoplay = true;
|
|
11412
12121
|
this.armFrameDisplayNotification();
|
|
11413
12122
|
this.startInterpolation();
|
|
12123
|
+
this.startRenderStatistics();
|
|
11414
12124
|
}
|
|
11415
12125
|
}
|
|
11416
12126
|
/**
|
|
@@ -11440,7 +12150,18 @@ var XmaxVideoView = class {
|
|
|
11440
12150
|
this.interpolationCanvas = canvas;
|
|
11441
12151
|
this.applyContentMode();
|
|
11442
12152
|
this.element.appendChild(canvas);
|
|
11443
|
-
const
|
|
12153
|
+
const options = this.interpolationOptions;
|
|
12154
|
+
const pipeline = new RemoteVideoFramePipeline(this.videoElement, canvas, {
|
|
12155
|
+
...options,
|
|
12156
|
+
onActiveChange: (active) => {
|
|
12157
|
+
this.statisticsController.setInterpolationActive(active);
|
|
12158
|
+
_optionalChain([options, 'access', _621 => _621.onActiveChange, 'optionalCall', _622 => _622(active)]);
|
|
12159
|
+
},
|
|
12160
|
+
onFramePresented: (interpolated) => {
|
|
12161
|
+
this.statisticsController.recordCanvasFrame(interpolated);
|
|
12162
|
+
_optionalChain([options, 'access', _623 => _623.onFramePresented, 'optionalCall', _624 => _624(interpolated)]);
|
|
12163
|
+
}
|
|
12164
|
+
});
|
|
11444
12165
|
this.interpolationPipeline = pipeline;
|
|
11445
12166
|
pipeline.start();
|
|
11446
12167
|
}
|
|
@@ -11450,8 +12171,8 @@ var XmaxVideoView = class {
|
|
|
11450
12171
|
stopInterpolation() {
|
|
11451
12172
|
const pipeline = this.interpolationPipeline;
|
|
11452
12173
|
this.interpolationPipeline = void 0;
|
|
11453
|
-
_optionalChain([pipeline, 'optionalAccess',
|
|
11454
|
-
_optionalChain([this, 'access',
|
|
12174
|
+
_optionalChain([pipeline, 'optionalAccess', _625 => _625.stop, 'call', _626 => _626()]);
|
|
12175
|
+
_optionalChain([this, 'access', _627 => _627.interpolationCanvas, 'optionalAccess', _628 => _628.remove, 'call', _629 => _629()]);
|
|
11455
12176
|
this.interpolationCanvas = void 0;
|
|
11456
12177
|
}
|
|
11457
12178
|
/**
|
|
@@ -11475,9 +12196,10 @@ var XmaxVideoView = class {
|
|
|
11475
12196
|
* 解绑当前轨道并清空渲染内容。
|
|
11476
12197
|
*/
|
|
11477
12198
|
detachCurrentTrack() {
|
|
12199
|
+
this.statisticsController.stop();
|
|
11478
12200
|
const track = this.currentTrack;
|
|
11479
12201
|
if (track) {
|
|
11480
|
-
_optionalChain([VideoRenderRegistry, 'access',
|
|
12202
|
+
_optionalChain([VideoRenderRegistry, 'access', _630 => _630.binding, 'call', _631 => _631(track), 'optionalAccess', _632 => _632.detachHandler, 'call', _633 => _633(this)]);
|
|
11481
12203
|
}
|
|
11482
12204
|
this.setFrameInterpolation(void 0);
|
|
11483
12205
|
this.cancelFrameDisplayNotification();
|
|
@@ -11500,8 +12222,8 @@ var XmaxVideoView = class {
|
|
|
11500
12222
|
}
|
|
11501
12223
|
this.hasNotifiedFrameDisplay = true;
|
|
11502
12224
|
this.cancelFrameDisplayNotification();
|
|
11503
|
-
_optionalChain([binding, 'optionalAccess',
|
|
11504
|
-
_optionalChain([this, 'access',
|
|
12225
|
+
_optionalChain([binding, 'optionalAccess', _634 => _634.frameDisplayHandler, 'optionalCall', _635 => _635()]);
|
|
12226
|
+
_optionalChain([this, 'access', _636 => _636.frameDisplayHandler, 'optionalCall', _637 => _637()]);
|
|
11505
12227
|
};
|
|
11506
12228
|
if (typeof this.videoElement.requestVideoFrameCallback === "function") {
|
|
11507
12229
|
this.videoFrameCallbackID = this.videoElement.requestVideoFrameCallback(notify);
|
|
@@ -11540,6 +12262,12 @@ var XmaxVideoView = class {
|
|
|
11540
12262
|
this.interpolationCanvas.style.transform = this.mirrored ? "scaleX(-1)" : "";
|
|
11541
12263
|
}
|
|
11542
12264
|
}
|
|
12265
|
+
/**
|
|
12266
|
+
* 视图未卸载时启动呈现统计,采样及媒体就绪检查由统计组件负责。
|
|
12267
|
+
*/
|
|
12268
|
+
startRenderStatistics() {
|
|
12269
|
+
if (!this.detached) this.statisticsController.start();
|
|
12270
|
+
}
|
|
11543
12271
|
};
|
|
11544
12272
|
|
|
11545
12273
|
// src/Render/Video/XmaxRealtimeVideoView.ts
|
|
@@ -11571,9 +12299,9 @@ var XmaxRealtimeVideoView = class {
|
|
|
11571
12299
|
__publicField(this, "currentLocalTrack");
|
|
11572
12300
|
__publicField(this, "currentRemoteTrack");
|
|
11573
12301
|
__publicField(this, "contentMode");
|
|
11574
|
-
this.contentMode = _nullishCoalesce(_optionalChain([options, 'optionalAccess',
|
|
11575
|
-
this.currentLocalTrack = _optionalChain([options, 'optionalAccess',
|
|
11576
|
-
this.currentRemoteTrack = _optionalChain([options, 'optionalAccess',
|
|
12302
|
+
this.contentMode = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _638 => _638.videoContentMode]), () => ( "fill")) /* fill */;
|
|
12303
|
+
this.currentLocalTrack = _optionalChain([options, 'optionalAccess', _639 => _639.localTrack]);
|
|
12304
|
+
this.currentRemoteTrack = _optionalChain([options, 'optionalAccess', _640 => _640.remoteTrack]);
|
|
11577
12305
|
this.element = document.createElement("div");
|
|
11578
12306
|
this.element.style.position = "relative";
|
|
11579
12307
|
this.element.style.overflow = "hidden";
|
|
@@ -11739,4 +12467,4 @@ var XmaxRealtimeVideoView = class {
|
|
|
11739
12467
|
|
|
11740
12468
|
|
|
11741
12469
|
exports.XmaxEnvironment = XmaxEnvironment; exports.apiBaseURL = apiBaseURL; exports.XmaxLoggerOption = XmaxLoggerOption; exports.XmaxLogger = XmaxLogger; exports.XmaxErrorCode = XmaxErrorCode; exports.XmaxError = XmaxError; exports.RealtimeVideoEncoderPreference = RealtimeVideoEncoderPreference; exports.RealtimeVideoFormat = RealtimeVideoFormat; exports.RtcProvider = RtcProvider; exports.RealtimeModel = RealtimeModel; exports.modelDisplayName = modelDisplayName; exports.defaultFrameRate = defaultFrameRate; exports.defaultCameraVideoFormat = defaultCameraVideoFormat; exports.supportedRtcProviders = supportedRtcProviders; exports.MediaService = MediaService; exports.StoredFile = StoredFile; exports.StorageService = StorageService; exports.CameraPosition = CameraPosition; exports.RealtimeVideoTrack = RealtimeVideoTrack; exports.RealtimeMediaStream = RealtimeMediaStream; exports.RealtimeVideoSampleMethod = RealtimeVideoSampleMethod; exports.RealtimeContext = RealtimeContext; exports.RealtimeConnectionState = RealtimeConnectionState; exports.RealtimeReason = RealtimeReason; exports.RealtimeState = RealtimeState; exports.XmaxConfiguration = XmaxConfiguration; exports.NonRealtimeQuality = NonRealtimeQuality; exports.NonRealtimeTaskStatus = NonRealtimeTaskStatus; exports.NonRealtimeTaskError = NonRealtimeTaskError; exports.XmaxClient = XmaxClient; exports.RealtimeConfiguration = RealtimeConfiguration; exports.VideoContentMode = VideoContentMode; exports.XmaxVideoView = XmaxVideoView; exports.XmaxRealtimeVideoView = XmaxRealtimeVideoView;
|
|
11742
|
-
//# sourceMappingURL=chunk-
|
|
12470
|
+
//# sourceMappingURL=chunk-NWNRFTLE.cjs.map
|