@xmaxai/sdk 1.0.1 → 1.0.3
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/CHANGELOG.md +11 -2
- package/README.md +19 -5
- package/dist/{chunk-LCPC56BK.js → chunk-B5EAQTBY.js} +497 -136
- package/dist/chunk-B5EAQTBY.js.map +1 -0
- package/dist/{chunk-V4NR6CPP.js → chunk-ZMLV7YQP.js} +24 -184
- package/dist/chunk-ZMLV7YQP.js.map +1 -0
- package/dist/index.cjs +53 -273
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +380 -8
- package/dist/index.d.ts +380 -8
- package/dist/index.js +1004 -9
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +30 -271
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1 -3
- package/dist/react/index.d.ts +1 -3
- package/dist/react/index.js +6 -26
- package/dist/react/index.js.map +1 -1
- package/dist/{rtc-manager-gYDkADGw.d.ts → rtc-manager-Bk2lIJ0d.d.cts} +7 -17
- package/dist/{rtc-manager-gYDkADGw.d.cts → rtc-manager-Bk2lIJ0d.d.ts} +7 -17
- package/dist/video-file-stream-OVPBV7IX.js +3 -0
- package/dist/{video-file-stream-K7GQMIJ5.js.map → video-file-stream-OVPBV7IX.js.map} +1 -1
- package/package.json +1 -6
- package/dist/chunk-4YHBCQ2C.js +0 -432
- package/dist/chunk-4YHBCQ2C.js.map +0 -1
- package/dist/chunk-LCPC56BK.js.map +0 -1
- package/dist/chunk-V4NR6CPP.js.map +0 -1
- package/dist/chunk-VLJZ56PT.js +0 -997
- package/dist/chunk-VLJZ56PT.js.map +0 -1
- package/dist/experimental/index.cjs +0 -3897
- package/dist/experimental/index.cjs.map +0 -1
- package/dist/experimental/index.d.cts +0 -2
- package/dist/experimental/index.d.ts +0 -2
- package/dist/experimental/index.js +0 -5
- package/dist/experimental/index.js.map +0 -1
- package/dist/index-Cw8C8LbO.d.ts +0 -367
- package/dist/index-Dg1ElHAj.d.cts +0 -367
- package/dist/video-file-stream-K7GQMIJ5.js +0 -4
package/dist/index.cjs
CHANGED
|
@@ -36,6 +36,8 @@ var init_en_US = __esm({
|
|
|
36
36
|
"errors.sessionJoinInfoIncomplete": "session does not contain complete RTC join info",
|
|
37
37
|
"errors.sessionUidMissing": "session does not contain sessionUid",
|
|
38
38
|
"errors.refImageMissing": "missing reference image",
|
|
39
|
+
"errors.imageCheckMissingUrl": "image check response missing url",
|
|
40
|
+
"errors.imageCheckUnsafe": "image did not pass safety check",
|
|
39
41
|
"errors.captureStreamUnsupported": "captureStream is not supported in this browser",
|
|
40
42
|
"errors.videoTrackMissing": "failed to create video track from file",
|
|
41
43
|
"errors.imageTrackMissing": "failed to create video track from image file",
|
|
@@ -97,6 +99,8 @@ var init_zh_CN = __esm({
|
|
|
97
99
|
"errors.sessionJoinInfoIncomplete": "session \u7F3A\u5C11\u5B8C\u6574\u7684 RTC \u8FDB\u623F\u4FE1\u606F",
|
|
98
100
|
"errors.sessionUidMissing": "session \u7F3A\u5C11 sessionUid",
|
|
99
101
|
"errors.refImageMissing": "\u7F3A\u5C11\u53C2\u8003\u56FE",
|
|
102
|
+
"errors.imageCheckMissingUrl": "\u56FE\u7247\u68C0\u67E5\u54CD\u5E94\u7F3A\u5C11 url",
|
|
103
|
+
"errors.imageCheckUnsafe": "\u56FE\u7247\u672A\u901A\u8FC7\u5B89\u5168\u68C0\u67E5",
|
|
100
104
|
"errors.captureStreamUnsupported": "\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 captureStream",
|
|
101
105
|
"errors.videoTrackMissing": "\u672A\u80FD\u4ECE\u89C6\u9891\u6587\u4EF6\u521B\u5EFA video track",
|
|
102
106
|
"errors.imageTrackMissing": "\u672A\u80FD\u4ECE\u56FE\u7247\u6587\u4EF6\u521B\u5EFA video track",
|
|
@@ -441,13 +445,12 @@ function resolveRtcPublishFps(options = {}) {
|
|
|
441
445
|
function resolveRtcPublishFrameIntervalS(options) {
|
|
442
446
|
return 1 / resolveRtcPublishFps(options);
|
|
443
447
|
}
|
|
444
|
-
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = void 0; exports.RTC_PUBLISH_FPS_WEB = void 0; exports.RTC_PUBLISH_FPS_MOBILE = void 0; exports.
|
|
448
|
+
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = void 0; exports.RTC_PUBLISH_FPS_WEB = void 0; exports.RTC_PUBLISH_FPS_MOBILE = void 0; exports.RTC_PUBLISH_FRAME_INTERVAL_S = void 0; exports.RTC_PUBLISH_FRAME_INTERVAL_MS = void 0; exports.MEDIA_TIME_EPSILON_S = void 0; exports.MEDIA_TIME_LOOP_JUMP_S = void 0;
|
|
445
449
|
var init_publish_fps = __esm({
|
|
446
450
|
"src/rtc/publish-fps.ts"() {
|
|
447
451
|
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = 768;
|
|
448
452
|
exports.RTC_PUBLISH_FPS_WEB = 30;
|
|
449
453
|
exports.RTC_PUBLISH_FPS_MOBILE = 24;
|
|
450
|
-
exports.RTC_PUBLISH_FPS = exports.RTC_PUBLISH_FPS_WEB;
|
|
451
454
|
exports.RTC_PUBLISH_FRAME_INTERVAL_S = 1 / exports.RTC_PUBLISH_FPS_WEB;
|
|
452
455
|
exports.RTC_PUBLISH_FRAME_INTERVAL_MS = 1e3 / exports.RTC_PUBLISH_FPS_WEB;
|
|
453
456
|
exports.MEDIA_TIME_EPSILON_S = 1e-3;
|
|
@@ -627,17 +630,6 @@ function shouldSampleAtMediaTime(lastMediaTimeS, mediaTimeS) {
|
|
|
627
630
|
}
|
|
628
631
|
return mediaTimeS > lastMediaTimeS + exports.MEDIA_TIME_EPSILON_S;
|
|
629
632
|
}
|
|
630
|
-
function sampleCanvasFingerprint(ctx, width, height) {
|
|
631
|
-
const points = [
|
|
632
|
-
[0, 0],
|
|
633
|
-
[Math.max(0, (width >> 1) - 1), Math.max(0, (height >> 1) - 1)],
|
|
634
|
-
[Math.max(0, width - 1), Math.max(0, height - 1)]
|
|
635
|
-
];
|
|
636
|
-
return points.map(([x, y]) => {
|
|
637
|
-
const data = ctx.getImageData(x, y, 1, 1).data;
|
|
638
|
-
return `${data[0]},${data[1]},${data[2]}`;
|
|
639
|
-
}).join("|");
|
|
640
|
-
}
|
|
641
633
|
async function applyPublishTrackConstraints(track, width, height) {
|
|
642
634
|
if (typeof track.applyConstraints !== "function") {
|
|
643
635
|
return;
|
|
@@ -710,12 +702,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
710
702
|
let lastDrawMediaTimeS = -1;
|
|
711
703
|
let videoFrameCallbackId = null;
|
|
712
704
|
let rafId = null;
|
|
713
|
-
const logPublishFrames = options.logPublishFrames ?? false;
|
|
714
|
-
let publishFrameIndex = 0;
|
|
715
|
-
let lastPublishWallMs = 0;
|
|
716
|
-
let lastPublishMediaTimeS = -1;
|
|
717
|
-
let publishFramesInWindow = 0;
|
|
718
|
-
let publishWindowStartMs = 0;
|
|
719
705
|
const drawFrame = () => {
|
|
720
706
|
if (destroyed) {
|
|
721
707
|
return;
|
|
@@ -729,52 +715,13 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
729
715
|
sourceHeight
|
|
730
716
|
);
|
|
731
717
|
};
|
|
732
|
-
const
|
|
733
|
-
if (!logPublishFrames) {
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
publishFrameIndex += 1;
|
|
737
|
-
const wallNowMs = performance.now();
|
|
738
|
-
const wallDeltaMs = lastPublishWallMs > 0 ? wallNowMs - lastPublishWallMs : 0;
|
|
739
|
-
const mediaDeltaS = lastPublishMediaTimeS >= 0 ? mediaTimeS - lastPublishMediaTimeS : 0;
|
|
740
|
-
lastPublishWallMs = wallNowMs;
|
|
741
|
-
lastPublishMediaTimeS = mediaTimeS;
|
|
742
|
-
publishFramesInWindow += 1;
|
|
743
|
-
if (publishWindowStartMs === 0) {
|
|
744
|
-
publishWindowStartMs = wallNowMs;
|
|
745
|
-
}
|
|
746
|
-
const fingerprint = sampleCanvasFingerprint(ctx, outputWidth, outputHeight);
|
|
747
|
-
console.warn("[upload-video \u2192 publishFrame]", {
|
|
748
|
-
frameIndex: publishFrameIndex,
|
|
749
|
-
mediaTimeS: Number(mediaTimeS.toFixed(4)),
|
|
750
|
-
mediaDeltaS: Number(mediaDeltaS.toFixed(4)),
|
|
751
|
-
wallDeltaMs: Number(wallDeltaMs.toFixed(1)),
|
|
752
|
-
effectiveFps: wallDeltaMs > 0 ? Number((1e3 / wallDeltaMs).toFixed(1)) : null,
|
|
753
|
-
presentedFrames,
|
|
754
|
-
size: `${outputWidth}\xD7${outputHeight}`,
|
|
755
|
-
fingerprint
|
|
756
|
-
});
|
|
757
|
-
const windowElapsedMs = wallNowMs - publishWindowStartMs;
|
|
758
|
-
if (windowElapsedMs >= 1e3) {
|
|
759
|
-
console.warn("[upload-video \u2192 publishFps]", {
|
|
760
|
-
framesInLast1s: publishFramesInWindow,
|
|
761
|
-
avgFps: Number((publishFramesInWindow / (windowElapsedMs / 1e3)).toFixed(2)),
|
|
762
|
-
videoCurrentTime: Number(videoEl.currentTime.toFixed(4)),
|
|
763
|
-
videoPaused: videoEl.paused,
|
|
764
|
-
videoReadyState: videoEl.readyState
|
|
765
|
-
});
|
|
766
|
-
publishFramesInWindow = 0;
|
|
767
|
-
publishWindowStartMs = wallNowMs;
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
const onPlaybackSample = (mediaTimeS, presentedFrames) => {
|
|
718
|
+
const onPlaybackSample = (mediaTimeS) => {
|
|
771
719
|
if (destroyed || !shouldSampleAtMediaTime(lastDrawMediaTimeS, mediaTimeS)) {
|
|
772
720
|
return;
|
|
773
721
|
}
|
|
774
722
|
lastDrawMediaTimeS = mediaTimeS;
|
|
775
723
|
lastAdvanceAt = Date.now();
|
|
776
724
|
drawFrame();
|
|
777
|
-
logPublishedFrame(mediaTimeS, presentedFrames);
|
|
778
725
|
};
|
|
779
726
|
const schedulePlaybackWatch = () => {
|
|
780
727
|
if (destroyed) {
|
|
@@ -783,7 +730,7 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
783
730
|
const video = videoEl;
|
|
784
731
|
if (video.requestVideoFrameCallback) {
|
|
785
732
|
videoFrameCallbackId = video.requestVideoFrameCallback((_now, metadata) => {
|
|
786
|
-
onPlaybackSample(metadata.mediaTime
|
|
733
|
+
onPlaybackSample(metadata.mediaTime);
|
|
787
734
|
schedulePlaybackWatch();
|
|
788
735
|
});
|
|
789
736
|
return;
|
|
@@ -794,7 +741,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
794
741
|
});
|
|
795
742
|
};
|
|
796
743
|
drawFrame();
|
|
797
|
-
logPublishedFrame(videoEl.currentTime);
|
|
798
744
|
schedulePlaybackWatch();
|
|
799
745
|
const ensurePlaying = () => {
|
|
800
746
|
if (destroyed) {
|
|
@@ -816,18 +762,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
816
762
|
videoEl.addEventListener("ended", ensurePlaying);
|
|
817
763
|
videoEl.addEventListener("stalled", ensurePlaying);
|
|
818
764
|
videoEl.addEventListener("waiting", ensurePlaying);
|
|
819
|
-
if (logPublishFrames) {
|
|
820
|
-
const logPlaybackEvent = (eventName) => {
|
|
821
|
-
console.warn("[upload-video \u2192 playbackEvent]", {
|
|
822
|
-
event: eventName,
|
|
823
|
-
currentTime: Number(videoEl.currentTime.toFixed(4)),
|
|
824
|
-
readyState: videoEl.readyState,
|
|
825
|
-
paused: videoEl.paused
|
|
826
|
-
});
|
|
827
|
-
};
|
|
828
|
-
videoEl.addEventListener("waiting", () => logPlaybackEvent("waiting"));
|
|
829
|
-
videoEl.addEventListener("stalled", () => logPlaybackEvent("stalled"));
|
|
830
|
-
}
|
|
831
765
|
const healthIntervalMs = options.healthIntervalMs ?? 3e3;
|
|
832
766
|
let healthTimer = null;
|
|
833
767
|
if (options.onHealthReport) {
|
|
@@ -1009,148 +943,13 @@ var init_video_file_stream = __esm({
|
|
|
1009
943
|
// src/sdk/client.ts
|
|
1010
944
|
init_i18n();
|
|
1011
945
|
|
|
1012
|
-
// src/shared/browser-toast.ts
|
|
1013
|
-
var TOAST_ROOT_ID = "Xmax-sdk-toast-root";
|
|
1014
|
-
var TOAST_DURATION_MS = 3e3;
|
|
1015
|
-
var toastSeed = 0;
|
|
1016
|
-
var timeoutMap = /* @__PURE__ */ new Map();
|
|
1017
|
-
var elementMap = /* @__PURE__ */ new Map();
|
|
1018
|
-
function ensureToastRoot() {
|
|
1019
|
-
if (typeof document === "undefined") {
|
|
1020
|
-
return null;
|
|
1021
|
-
}
|
|
1022
|
-
let root = document.getElementById(TOAST_ROOT_ID);
|
|
1023
|
-
if (root) {
|
|
1024
|
-
return root;
|
|
1025
|
-
}
|
|
1026
|
-
root = document.createElement("div");
|
|
1027
|
-
root.id = TOAST_ROOT_ID;
|
|
1028
|
-
root.setAttribute("aria-live", "polite");
|
|
1029
|
-
Object.assign(root.style, {
|
|
1030
|
-
position: "fixed",
|
|
1031
|
-
left: "50%",
|
|
1032
|
-
top: "24px",
|
|
1033
|
-
transform: "translateX(-50%)",
|
|
1034
|
-
zIndex: "3000",
|
|
1035
|
-
display: "flex",
|
|
1036
|
-
flexDirection: "column",
|
|
1037
|
-
alignItems: "center",
|
|
1038
|
-
gap: "12px",
|
|
1039
|
-
pointerEvents: "none"
|
|
1040
|
-
});
|
|
1041
|
-
document.body.appendChild(root);
|
|
1042
|
-
return root;
|
|
1043
|
-
}
|
|
1044
|
-
function createIcon(type) {
|
|
1045
|
-
const icon = document.createElement("span");
|
|
1046
|
-
icon.setAttribute("aria-hidden", "true");
|
|
1047
|
-
icon.innerHTML = type === "success" ? '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M10 3L4.5 8.5 2 6" stroke="#4ade80" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>' : '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><circle cx="6" cy="6" r="5" stroke="#f87171" stroke-width="1.5"/><path d="M4 4l4 4M8 4L4 8" stroke="#f87171" stroke-width="1.5" stroke-linecap="round"/></svg>';
|
|
1048
|
-
Object.assign(icon.style, {
|
|
1049
|
-
display: "inline-flex",
|
|
1050
|
-
width: "12px",
|
|
1051
|
-
height: "12px",
|
|
1052
|
-
flexShrink: "0"
|
|
1053
|
-
});
|
|
1054
|
-
return icon;
|
|
1055
|
-
}
|
|
1056
|
-
function clearToastTimer(id) {
|
|
1057
|
-
const timer = timeoutMap.get(id);
|
|
1058
|
-
if (timer) {
|
|
1059
|
-
window.clearTimeout(timer);
|
|
1060
|
-
timeoutMap.delete(id);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
function destroyToast(id) {
|
|
1064
|
-
if (!id) {
|
|
1065
|
-
timeoutMap.forEach((timer) => window.clearTimeout(timer));
|
|
1066
|
-
timeoutMap.clear();
|
|
1067
|
-
elementMap.forEach((element2) => element2.remove());
|
|
1068
|
-
elementMap.clear();
|
|
1069
|
-
const root2 = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
|
|
1070
|
-
root2?.remove();
|
|
1071
|
-
return;
|
|
1072
|
-
}
|
|
1073
|
-
clearToastTimer(id);
|
|
1074
|
-
const element = elementMap.get(id);
|
|
1075
|
-
element?.remove();
|
|
1076
|
-
elementMap.delete(id);
|
|
1077
|
-
const root = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
|
|
1078
|
-
if (root && !root.childElementCount) {
|
|
1079
|
-
root.remove();
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
function showToast(type, message, options) {
|
|
1083
|
-
const root = ensureToastRoot();
|
|
1084
|
-
if (!root) {
|
|
1085
|
-
return "";
|
|
1086
|
-
}
|
|
1087
|
-
const id = options?.key || `toast-${Date.now()}-${++toastSeed}`;
|
|
1088
|
-
clearToastTimer(id);
|
|
1089
|
-
elementMap.get(id)?.remove();
|
|
1090
|
-
const isMobile = typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches;
|
|
1091
|
-
const textSize = isMobile ? "12px" : "14px";
|
|
1092
|
-
const toast = document.createElement("div");
|
|
1093
|
-
toast.setAttribute("role", "status");
|
|
1094
|
-
Object.assign(toast.style, {
|
|
1095
|
-
pointerEvents: "auto",
|
|
1096
|
-
display: "flex",
|
|
1097
|
-
alignItems: "center",
|
|
1098
|
-
gap: "12px",
|
|
1099
|
-
minWidth: "240px",
|
|
1100
|
-
padding: "16px",
|
|
1101
|
-
borderRadius: "12px",
|
|
1102
|
-
border: "1px solid rgba(255, 255, 255, 0.20)",
|
|
1103
|
-
background: "rgba(0, 0, 0, 0.80)",
|
|
1104
|
-
boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
|
|
1105
|
-
fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
|
|
1106
|
-
fontSize: textSize,
|
|
1107
|
-
fontWeight: "400",
|
|
1108
|
-
lineHeight: "14px"
|
|
1109
|
-
});
|
|
1110
|
-
const content = document.createElement("span");
|
|
1111
|
-
content.textContent = message;
|
|
1112
|
-
Object.assign(content.style, {
|
|
1113
|
-
paddingRight: "0px",
|
|
1114
|
-
textAlign: "center",
|
|
1115
|
-
color: "#ffffff",
|
|
1116
|
-
fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
|
|
1117
|
-
fontSize: textSize,
|
|
1118
|
-
fontWeight: "400",
|
|
1119
|
-
lineHeight: "14px"
|
|
1120
|
-
});
|
|
1121
|
-
toast.appendChild(createIcon(type));
|
|
1122
|
-
toast.appendChild(content);
|
|
1123
|
-
root.appendChild(toast);
|
|
1124
|
-
elementMap.set(id, toast);
|
|
1125
|
-
const timer = window.setTimeout(() => {
|
|
1126
|
-
destroyToast(id);
|
|
1127
|
-
}, options?.duration ?? TOAST_DURATION_MS);
|
|
1128
|
-
timeoutMap.set(id, timer);
|
|
1129
|
-
return id;
|
|
1130
|
-
}
|
|
1131
|
-
var browserToast = {
|
|
1132
|
-
success(message, options) {
|
|
1133
|
-
return showToast("success", message, options);
|
|
1134
|
-
},
|
|
1135
|
-
error(message, options) {
|
|
1136
|
-
return showToast("error", message, options);
|
|
1137
|
-
},
|
|
1138
|
-
destroy(id) {
|
|
1139
|
-
destroyToast(id);
|
|
1140
|
-
}
|
|
1141
|
-
};
|
|
1142
|
-
|
|
1143
946
|
// src/shared/error-utils.ts
|
|
1144
947
|
function notifyError(error, notifier, fallbackMessage) {
|
|
1145
948
|
const resolved = error instanceof Error ? error : Object.assign(new Error(fallbackMessage), { cause: error });
|
|
1146
|
-
if (!resolved.__XmaxNotified) {
|
|
949
|
+
if (!resolved.__XmaxNotified && notifier) {
|
|
1147
950
|
resolved.__XmaxNotified = true;
|
|
1148
951
|
const message = resolved.message || fallbackMessage;
|
|
1149
|
-
|
|
1150
|
-
notifier(message, error);
|
|
1151
|
-
} else if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
1152
|
-
browserToast.error(message);
|
|
1153
|
-
}
|
|
952
|
+
notifier(message, error);
|
|
1154
953
|
}
|
|
1155
954
|
return resolved;
|
|
1156
955
|
}
|
|
@@ -1222,7 +1021,7 @@ var XmaxOpenClient = class {
|
|
|
1222
1021
|
}
|
|
1223
1022
|
throw notifyError(error, this.onError, message);
|
|
1224
1023
|
}
|
|
1225
|
-
/** Stop heartbeat, abort in-flight API requests, and suppress error
|
|
1024
|
+
/** Stop heartbeat, abort in-flight API requests, and suppress error notifications during teardown. */
|
|
1226
1025
|
beginTeardown() {
|
|
1227
1026
|
this.suppressErrorNotification = true;
|
|
1228
1027
|
this.stopHeartbeat();
|
|
@@ -1382,6 +1181,23 @@ var XmaxOpenClient = class {
|
|
|
1382
1181
|
async uploadVideo(file) {
|
|
1383
1182
|
return this.uploadObject(file, "video/");
|
|
1384
1183
|
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Upload an image then run Playground-style `/cos/image/check`.
|
|
1186
|
+
* Returns the checked URL. Existing {@link uploadImage} is unchanged.
|
|
1187
|
+
*/
|
|
1188
|
+
async uploadAndCheckImage(file) {
|
|
1189
|
+
const uploaded = await this.uploadImage(file);
|
|
1190
|
+
const data = await this.request("POST", "/cos/image/check", {
|
|
1191
|
+
url: uploaded.url
|
|
1192
|
+
});
|
|
1193
|
+
if (!data?.url) {
|
|
1194
|
+
this.throwError(this.i18n.t("errors.imageCheckMissingUrl"));
|
|
1195
|
+
}
|
|
1196
|
+
if (data.safe === false) {
|
|
1197
|
+
this.throwError(this.i18n.t("errors.imageCheckUnsafe"));
|
|
1198
|
+
}
|
|
1199
|
+
return data.url;
|
|
1200
|
+
}
|
|
1385
1201
|
startHeartbeat(sessionUid, intervalMs = 1e4, onHeartbeat, onError) {
|
|
1386
1202
|
this.stopHeartbeat();
|
|
1387
1203
|
const heartbeat = async () => {
|
|
@@ -2079,45 +1895,6 @@ var _RtcManager = class _RtcManager {
|
|
|
2079
1895
|
sentFrameRate: this.lastObservedSentFrameRate
|
|
2080
1896
|
});
|
|
2081
1897
|
}
|
|
2082
|
-
/** @deprecated Use {@link ensurePublishedInputBeforeStart}. */
|
|
2083
|
-
async waitForRtcOutboundBeforeStart(options) {
|
|
2084
|
-
const timeoutMs = options?.timeoutMs ?? PUBLISH_READY_TIMEOUT_MS;
|
|
2085
|
-
const publishAgeMs = this.publishStartedAtMs > 0 ? performance.now() - this.publishStartedAtMs : 0;
|
|
2086
|
-
const localFramesPromise = publishAgeMs >= PUBLISH_WARM_SKIP_MS ? Promise.resolve({ ready: true, frameCount: 0, elapsedMs: 0 }) : this.waitForPublishedInputFrames({
|
|
2087
|
-
minFrames: PUBLISH_START_MIN_FRAMES,
|
|
2088
|
-
timeoutMs: PUBLISH_START_FRAME_TIMEOUT_MS
|
|
2089
|
-
});
|
|
2090
|
-
const [, rtcReady] = await Promise.all([
|
|
2091
|
-
localFramesPromise,
|
|
2092
|
-
this.waitForLocalPublishReady({ timeoutMs })
|
|
2093
|
-
]);
|
|
2094
|
-
return rtcReady;
|
|
2095
|
-
}
|
|
2096
|
-
/** @deprecated Use {@link waitForRtcOutboundBeforeStart}. */
|
|
2097
|
-
async waitForPublishedInputFramesBeforeStart() {
|
|
2098
|
-
const waitOptions = this.resolveInputFrameWaitOptions();
|
|
2099
|
-
const waitTasks = [
|
|
2100
|
-
this.waitForLocalPublishReady({ timeoutMs: PUBLISH_READY_TIMEOUT_MS })
|
|
2101
|
-
];
|
|
2102
|
-
if (waitOptions) {
|
|
2103
|
-
waitTasks.push(
|
|
2104
|
-
this.waitForMinPublishDuration(waitOptions.minPublishMs),
|
|
2105
|
-
this.waitForPublishedInputFrames({
|
|
2106
|
-
minFrames: waitOptions.minFrames,
|
|
2107
|
-
timeoutMs: waitOptions.timeoutMs
|
|
2108
|
-
})
|
|
2109
|
-
);
|
|
2110
|
-
}
|
|
2111
|
-
const [rtcResult, ...rest] = await Promise.all(waitTasks);
|
|
2112
|
-
const rtcSend = rtcResult;
|
|
2113
|
-
const frameResult = waitOptions ? rest[1] : { ready: true, frameCount: 0, elapsedMs: 0 };
|
|
2114
|
-
return {
|
|
2115
|
-
...frameResult,
|
|
2116
|
-
rtcSendReady: rtcSend.ready,
|
|
2117
|
-
rtcSendReason: rtcSend.reason,
|
|
2118
|
-
rtcSendElapsedMs: rtcSend.elapsedSincePublishMs
|
|
2119
|
-
};
|
|
2120
|
-
}
|
|
2121
1898
|
async waitForMinPublishDuration(minMs) {
|
|
2122
1899
|
if (minMs <= 0 || this.publishStartedAtMs <= 0) {
|
|
2123
1900
|
return;
|
|
@@ -3612,9 +3389,6 @@ function getFitContentRect(rect, targetSize, fitMode = "contain") {
|
|
|
3612
3389
|
height
|
|
3613
3390
|
};
|
|
3614
3391
|
}
|
|
3615
|
-
function getContentRect(rect, targetSize) {
|
|
3616
|
-
return getFitContentRect(rect, targetSize, "contain");
|
|
3617
|
-
}
|
|
3618
3392
|
function findDragMediaElement(dragSurface) {
|
|
3619
3393
|
const root = dragSurface.parentElement ?? dragSurface;
|
|
3620
3394
|
if (typeof root.querySelector !== "function") {
|
|
@@ -4219,6 +3993,10 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4219
3993
|
this.currentPrompt = "";
|
|
4220
3994
|
this.currentGenerationModel = "";
|
|
4221
3995
|
this.disconnected = false;
|
|
3996
|
+
/** True only after `connect()` bootstrap succeeds — gates `onDisconnect`. */
|
|
3997
|
+
this.sessionEstablished = false;
|
|
3998
|
+
this.disconnectNotified = false;
|
|
3999
|
+
this.pendingDisconnectReason = "client";
|
|
4222
4000
|
this.remoteViewHost = null;
|
|
4223
4001
|
this.dragController = null;
|
|
4224
4002
|
this.dragTrackFitMode = "cover";
|
|
@@ -4232,6 +4010,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4232
4010
|
this.rtc = rtc;
|
|
4233
4011
|
this.reportError = reportError;
|
|
4234
4012
|
this.onRemoteStream = options.onRemoteStream;
|
|
4013
|
+
this.onDisconnect = options.onDisconnect;
|
|
4235
4014
|
this.onPublishPipelineWaitChange = clientOptions?.onPublishPipelineWaitChange;
|
|
4236
4015
|
if (options.remoteElement) {
|
|
4237
4016
|
this.remoteElement = options.remoteElement;
|
|
@@ -4260,7 +4039,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4260
4039
|
}
|
|
4261
4040
|
static async connect(stream, options, clientOptions) {
|
|
4262
4041
|
const sdkI18n = createSDKI18n({});
|
|
4263
|
-
const notifyUserError = clientOptions.onError;
|
|
4042
|
+
const notifyUserError = options.onError ?? clientOptions.onError;
|
|
4264
4043
|
const reportError = (error, fallbackMessage) => {
|
|
4265
4044
|
throw notifyError(error, notifyUserError, fallbackMessage ?? sdkI18n.t("errors.requestFailed"));
|
|
4266
4045
|
};
|
|
@@ -4281,6 +4060,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4281
4060
|
const session = new _RealtimeSession(client, rtc, reportError, options, clientOptions);
|
|
4282
4061
|
try {
|
|
4283
4062
|
await session.bootstrap(stream, options, clientOptions.heartbeatIntervalMs ?? 1e4, prewarmed);
|
|
4063
|
+
session.sessionEstablished = true;
|
|
4284
4064
|
return session;
|
|
4285
4065
|
} catch (error) {
|
|
4286
4066
|
await session.safeDisconnect();
|
|
@@ -4306,11 +4086,11 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4306
4086
|
heartbeatIntervalMs,
|
|
4307
4087
|
(heartbeatSession) => {
|
|
4308
4088
|
if (heartbeatSession.status !== ACTIVE_STATUS) {
|
|
4309
|
-
void this.safeDisconnect();
|
|
4089
|
+
void this.safeDisconnect({ reason: "session_inactive" });
|
|
4310
4090
|
}
|
|
4311
4091
|
},
|
|
4312
4092
|
() => {
|
|
4313
|
-
void this.safeDisconnect();
|
|
4093
|
+
void this.safeDisconnect({ reason: "heartbeat_error" });
|
|
4314
4094
|
}
|
|
4315
4095
|
);
|
|
4316
4096
|
const joinInfo = this.client.getRtcJoinInfo(createdSession);
|
|
@@ -4472,9 +4252,6 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4472
4252
|
this.reportError(error);
|
|
4473
4253
|
}
|
|
4474
4254
|
}
|
|
4475
|
-
async setMode(options) {
|
|
4476
|
-
return this.restart(options);
|
|
4477
|
-
}
|
|
4478
4255
|
async refreshRemoteOutput(options) {
|
|
4479
4256
|
if (!this.remoteVideoContainer) {
|
|
4480
4257
|
return;
|
|
@@ -4548,7 +4325,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4548
4325
|
return;
|
|
4549
4326
|
}
|
|
4550
4327
|
this.disconnected = true;
|
|
4551
|
-
await this.safeDisconnect(options);
|
|
4328
|
+
await this.safeDisconnect({ ...options, reason: "client" });
|
|
4552
4329
|
}
|
|
4553
4330
|
getSessionUid() {
|
|
4554
4331
|
return this.sessionUid;
|
|
@@ -4631,17 +4408,6 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4631
4408
|
mirrored: false,
|
|
4632
4409
|
enabled: true,
|
|
4633
4410
|
onTracks: (tracks) => {
|
|
4634
|
-
const media = this.remoteViewHost?.videoHost?.querySelector("video, canvas");
|
|
4635
|
-
const mediaRect = media?.getBoundingClientRect();
|
|
4636
|
-
const dragRect = dragHost.getBoundingClientRect();
|
|
4637
|
-
console.log("[Xmax] sendTracks", {
|
|
4638
|
-
taskUid: this.taskUid,
|
|
4639
|
-
targetSize: this.sessionTargetSize,
|
|
4640
|
-
fitMode: this.dragTrackFitMode,
|
|
4641
|
-
tracks,
|
|
4642
|
-
dragRect: dragRect ? { w: dragRect.width, h: dragRect.height } : null,
|
|
4643
|
-
mediaRect: mediaRect ? { w: mediaRect.width, h: mediaRect.height, l: mediaRect.left, t: mediaRect.top } : null
|
|
4644
|
-
});
|
|
4645
4411
|
void this.sendTracks(tracks);
|
|
4646
4412
|
}
|
|
4647
4413
|
});
|
|
@@ -4690,7 +4456,20 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4690
4456
|
this.remoteStreamNotifyTimer = null;
|
|
4691
4457
|
}
|
|
4692
4458
|
}
|
|
4459
|
+
emitDisconnect(reason) {
|
|
4460
|
+
if (!this.sessionEstablished || this.disconnectNotified) {
|
|
4461
|
+
return;
|
|
4462
|
+
}
|
|
4463
|
+
this.disconnectNotified = true;
|
|
4464
|
+
try {
|
|
4465
|
+
this.onDisconnect?.(reason);
|
|
4466
|
+
} catch {
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4693
4469
|
async safeDisconnect(options) {
|
|
4470
|
+
const reason = options?.reason ?? this.pendingDisconnectReason;
|
|
4471
|
+
this.pendingDisconnectReason = reason;
|
|
4472
|
+
this.disconnected = true;
|
|
4694
4473
|
this.clearRemoteStreamNotifyTimer();
|
|
4695
4474
|
this.lastNotifiedRemoteStream = null;
|
|
4696
4475
|
const activeSessionUid = this.sessionUid;
|
|
@@ -4741,6 +4520,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4741
4520
|
this.hiddenRemoteElement.remove();
|
|
4742
4521
|
this.hiddenRemoteElement = null;
|
|
4743
4522
|
}
|
|
4523
|
+
this.emitDisconnect(reason);
|
|
4744
4524
|
}
|
|
4745
4525
|
};
|
|
4746
4526
|
|
|
@@ -4780,7 +4560,8 @@ function createXmaxClient(options) {
|
|
|
4780
4560
|
files: {
|
|
4781
4561
|
uploadImage: (file) => httpClient.uploadImage(file),
|
|
4782
4562
|
uploadVideo: (file) => httpClient.uploadVideo(file),
|
|
4783
|
-
upload: (file) => httpClient.uploadImage(file)
|
|
4563
|
+
upload: (file) => httpClient.uploadImage(file),
|
|
4564
|
+
uploadAndCheckImage: (file) => httpClient.uploadAndCheckImage(file)
|
|
4784
4565
|
},
|
|
4785
4566
|
realtime: {
|
|
4786
4567
|
prewarm: (options2) => RealtimePrewarmHandle.create(options2.model, resolved),
|
|
@@ -5080,7 +4861,6 @@ exports.createTracksRtcRoomEvent = createTracksRtcRoomEvent;
|
|
|
5080
4861
|
exports.createVideoFileStream = createVideoFileStream;
|
|
5081
4862
|
exports.createXmaxClient = createXmaxClient;
|
|
5082
4863
|
exports.getCameraEnvironmentIssue = getCameraEnvironmentIssue;
|
|
5083
|
-
exports.getContentRect = getContentRect;
|
|
5084
4864
|
exports.getDefaultMessages = getDefaultMessages;
|
|
5085
4865
|
exports.isCameraAccessError = isCameraAccessError;
|
|
5086
4866
|
exports.isImageMediaFile = isImageMediaFile;
|