@xmaxai/sdk 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +10 -2
  2. package/README.md +9 -5
  3. package/dist/{chunk-V4NR6CPP.js → chunk-F567ONBH.js} +7 -184
  4. package/dist/chunk-F567ONBH.js.map +1 -0
  5. package/dist/{chunk-LCPC56BK.js → chunk-TFGYBN3Q.js} +493 -136
  6. package/dist/chunk-TFGYBN3Q.js.map +1 -0
  7. package/dist/index.cjs +30 -272
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +369 -8
  10. package/dist/index.d.ts +369 -8
  11. package/dist/index.js +1003 -9
  12. package/dist/index.js.map +1 -1
  13. package/dist/react/index.cjs +9 -271
  14. package/dist/react/index.cjs.map +1 -1
  15. package/dist/react/index.d.cts +1 -3
  16. package/dist/react/index.d.ts +1 -3
  17. package/dist/react/index.js +6 -26
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/{rtc-manager-gYDkADGw.d.ts → rtc-manager-DnQoznIg.d.cts} +2 -17
  20. package/dist/{rtc-manager-gYDkADGw.d.cts → rtc-manager-DnQoznIg.d.ts} +2 -17
  21. package/dist/video-file-stream-4TAGKL2Q.js +3 -0
  22. package/dist/{video-file-stream-K7GQMIJ5.js.map → video-file-stream-4TAGKL2Q.js.map} +1 -1
  23. package/package.json +1 -6
  24. package/dist/chunk-4YHBCQ2C.js +0 -432
  25. package/dist/chunk-4YHBCQ2C.js.map +0 -1
  26. package/dist/chunk-LCPC56BK.js.map +0 -1
  27. package/dist/chunk-V4NR6CPP.js.map +0 -1
  28. package/dist/chunk-VLJZ56PT.js +0 -997
  29. package/dist/chunk-VLJZ56PT.js.map +0 -1
  30. package/dist/experimental/index.cjs +0 -3897
  31. package/dist/experimental/index.cjs.map +0 -1
  32. package/dist/experimental/index.d.cts +0 -2
  33. package/dist/experimental/index.d.ts +0 -2
  34. package/dist/experimental/index.js +0 -5
  35. package/dist/experimental/index.js.map +0 -1
  36. package/dist/index-Cw8C8LbO.d.ts +0 -367
  37. package/dist/index-Dg1ElHAj.d.cts +0 -367
  38. package/dist/video-file-stream-K7GQMIJ5.js +0 -4
@@ -280,148 +280,13 @@ function createSDKI18n(input) {
280
280
  };
281
281
  }
282
282
 
283
- // src/shared/browser-toast.ts
284
- var TOAST_ROOT_ID = "Xmax-sdk-toast-root";
285
- var TOAST_DURATION_MS = 3e3;
286
- var toastSeed = 0;
287
- var timeoutMap = /* @__PURE__ */ new Map();
288
- var elementMap = /* @__PURE__ */ new Map();
289
- function ensureToastRoot() {
290
- if (typeof document === "undefined") {
291
- return null;
292
- }
293
- let root = document.getElementById(TOAST_ROOT_ID);
294
- if (root) {
295
- return root;
296
- }
297
- root = document.createElement("div");
298
- root.id = TOAST_ROOT_ID;
299
- root.setAttribute("aria-live", "polite");
300
- Object.assign(root.style, {
301
- position: "fixed",
302
- left: "50%",
303
- top: "24px",
304
- transform: "translateX(-50%)",
305
- zIndex: "3000",
306
- display: "flex",
307
- flexDirection: "column",
308
- alignItems: "center",
309
- gap: "12px",
310
- pointerEvents: "none"
311
- });
312
- document.body.appendChild(root);
313
- return root;
314
- }
315
- function createIcon(type) {
316
- const icon = document.createElement("span");
317
- icon.setAttribute("aria-hidden", "true");
318
- 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>';
319
- Object.assign(icon.style, {
320
- display: "inline-flex",
321
- width: "12px",
322
- height: "12px",
323
- flexShrink: "0"
324
- });
325
- return icon;
326
- }
327
- function clearToastTimer(id) {
328
- const timer = timeoutMap.get(id);
329
- if (timer) {
330
- window.clearTimeout(timer);
331
- timeoutMap.delete(id);
332
- }
333
- }
334
- function destroyToast(id) {
335
- if (!id) {
336
- timeoutMap.forEach((timer) => window.clearTimeout(timer));
337
- timeoutMap.clear();
338
- elementMap.forEach((element2) => element2.remove());
339
- elementMap.clear();
340
- const root2 = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
341
- root2?.remove();
342
- return;
343
- }
344
- clearToastTimer(id);
345
- const element = elementMap.get(id);
346
- element?.remove();
347
- elementMap.delete(id);
348
- const root = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
349
- if (root && !root.childElementCount) {
350
- root.remove();
351
- }
352
- }
353
- function showToast(type, message, options) {
354
- const root = ensureToastRoot();
355
- if (!root) {
356
- return "";
357
- }
358
- const id = options?.key || `toast-${Date.now()}-${++toastSeed}`;
359
- clearToastTimer(id);
360
- elementMap.get(id)?.remove();
361
- const isMobile = typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches;
362
- const textSize = isMobile ? "12px" : "14px";
363
- const toast = document.createElement("div");
364
- toast.setAttribute("role", "status");
365
- Object.assign(toast.style, {
366
- pointerEvents: "auto",
367
- display: "flex",
368
- alignItems: "center",
369
- gap: "12px",
370
- minWidth: "240px",
371
- padding: "16px",
372
- borderRadius: "12px",
373
- border: "1px solid rgba(255, 255, 255, 0.20)",
374
- background: "rgba(0, 0, 0, 0.80)",
375
- boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
376
- fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
377
- fontSize: textSize,
378
- fontWeight: "400",
379
- lineHeight: "14px"
380
- });
381
- const content = document.createElement("span");
382
- content.textContent = message;
383
- Object.assign(content.style, {
384
- paddingRight: "0px",
385
- textAlign: "center",
386
- color: "#ffffff",
387
- fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
388
- fontSize: textSize,
389
- fontWeight: "400",
390
- lineHeight: "14px"
391
- });
392
- toast.appendChild(createIcon(type));
393
- toast.appendChild(content);
394
- root.appendChild(toast);
395
- elementMap.set(id, toast);
396
- const timer = window.setTimeout(() => {
397
- destroyToast(id);
398
- }, options?.duration ?? TOAST_DURATION_MS);
399
- timeoutMap.set(id, timer);
400
- return id;
401
- }
402
- var browserToast = {
403
- success(message, options) {
404
- return showToast("success", message, options);
405
- },
406
- error(message, options) {
407
- return showToast("error", message, options);
408
- },
409
- destroy(id) {
410
- destroyToast(id);
411
- }
412
- };
413
-
414
283
  // src/shared/error-utils.ts
415
284
  function notifyError(error, notifier, fallbackMessage) {
416
285
  const resolved = error instanceof Error ? error : Object.assign(new Error(fallbackMessage), { cause: error });
417
- if (!resolved.__XmaxNotified) {
286
+ if (!resolved.__XmaxNotified && notifier) {
418
287
  resolved.__XmaxNotified = true;
419
288
  const message = resolved.message || fallbackMessage;
420
- if (notifier) {
421
- notifier(message, error);
422
- } else if (typeof window !== "undefined" && typeof document !== "undefined") {
423
- browserToast.error(message);
424
- }
289
+ notifier(message, error);
425
290
  }
426
291
  return resolved;
427
292
  }
@@ -483,7 +348,7 @@ var XmaxOpenClient = class {
483
348
  }
484
349
  throw notifyError(error, this.onError, message);
485
350
  }
486
- /** Stop heartbeat, abort in-flight API requests, and suppress error toasts during teardown. */
351
+ /** Stop heartbeat, abort in-flight API requests, and suppress error notifications during teardown. */
487
352
  beginTeardown() {
488
353
  this.suppressErrorNotification = true;
489
354
  this.stopHeartbeat();
@@ -1455,45 +1320,6 @@ var _RtcManager = class _RtcManager {
1455
1320
  sentFrameRate: this.lastObservedSentFrameRate
1456
1321
  });
1457
1322
  }
1458
- /** @deprecated Use {@link ensurePublishedInputBeforeStart}. */
1459
- async waitForRtcOutboundBeforeStart(options) {
1460
- const timeoutMs = options?.timeoutMs ?? PUBLISH_READY_TIMEOUT_MS;
1461
- const publishAgeMs = this.publishStartedAtMs > 0 ? performance.now() - this.publishStartedAtMs : 0;
1462
- const localFramesPromise = publishAgeMs >= PUBLISH_WARM_SKIP_MS ? Promise.resolve({ ready: true, frameCount: 0, elapsedMs: 0 }) : this.waitForPublishedInputFrames({
1463
- minFrames: PUBLISH_START_MIN_FRAMES,
1464
- timeoutMs: PUBLISH_START_FRAME_TIMEOUT_MS
1465
- });
1466
- const [, rtcReady] = await Promise.all([
1467
- localFramesPromise,
1468
- this.waitForLocalPublishReady({ timeoutMs })
1469
- ]);
1470
- return rtcReady;
1471
- }
1472
- /** @deprecated Use {@link waitForRtcOutboundBeforeStart}. */
1473
- async waitForPublishedInputFramesBeforeStart() {
1474
- const waitOptions = this.resolveInputFrameWaitOptions();
1475
- const waitTasks = [
1476
- this.waitForLocalPublishReady({ timeoutMs: PUBLISH_READY_TIMEOUT_MS })
1477
- ];
1478
- if (waitOptions) {
1479
- waitTasks.push(
1480
- this.waitForMinPublishDuration(waitOptions.minPublishMs),
1481
- this.waitForPublishedInputFrames({
1482
- minFrames: waitOptions.minFrames,
1483
- timeoutMs: waitOptions.timeoutMs
1484
- })
1485
- );
1486
- }
1487
- const [rtcResult, ...rest] = await Promise.all(waitTasks);
1488
- const rtcSend = rtcResult;
1489
- const frameResult = waitOptions ? rest[1] : { ready: true, frameCount: 0, elapsedMs: 0 };
1490
- return {
1491
- ...frameResult,
1492
- rtcSendReady: rtcSend.ready,
1493
- rtcSendReason: rtcSend.reason,
1494
- rtcSendElapsedMs: rtcSend.elapsedSincePublishMs
1495
- };
1496
- }
1497
1323
  async waitForMinPublishDuration(minMs) {
1498
1324
  if (minMs <= 0 || this.publishStartedAtMs <= 0) {
1499
1325
  return;
@@ -2457,17 +2283,6 @@ function shouldSampleAtMediaTime(lastMediaTimeS, mediaTimeS) {
2457
2283
  }
2458
2284
  return mediaTimeS > lastMediaTimeS + MEDIA_TIME_EPSILON_S;
2459
2285
  }
2460
- function sampleCanvasFingerprint(ctx, width, height) {
2461
- const points = [
2462
- [0, 0],
2463
- [Math.max(0, (width >> 1) - 1), Math.max(0, (height >> 1) - 1)],
2464
- [Math.max(0, width - 1), Math.max(0, height - 1)]
2465
- ];
2466
- return points.map(([x, y]) => {
2467
- const data = ctx.getImageData(x, y, 1, 1).data;
2468
- return `${data[0]},${data[1]},${data[2]}`;
2469
- }).join("|");
2470
- }
2471
2286
  async function applyPublishTrackConstraints(track, width, height) {
2472
2287
  if (typeof track.applyConstraints !== "function") {
2473
2288
  return;
@@ -2540,12 +2355,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
2540
2355
  let lastDrawMediaTimeS = -1;
2541
2356
  let videoFrameCallbackId = null;
2542
2357
  let rafId = null;
2543
- const logPublishFrames = options.logPublishFrames ?? false;
2544
- let publishFrameIndex = 0;
2545
- let lastPublishWallMs = 0;
2546
- let lastPublishMediaTimeS = -1;
2547
- let publishFramesInWindow = 0;
2548
- let publishWindowStartMs = 0;
2549
2358
  const drawFrame = () => {
2550
2359
  if (destroyed) {
2551
2360
  return;
@@ -2559,52 +2368,13 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
2559
2368
  sourceHeight
2560
2369
  );
2561
2370
  };
2562
- const logPublishedFrame = (mediaTimeS, presentedFrames) => {
2563
- if (!logPublishFrames) {
2564
- return;
2565
- }
2566
- publishFrameIndex += 1;
2567
- const wallNowMs = performance.now();
2568
- const wallDeltaMs = lastPublishWallMs > 0 ? wallNowMs - lastPublishWallMs : 0;
2569
- const mediaDeltaS = lastPublishMediaTimeS >= 0 ? mediaTimeS - lastPublishMediaTimeS : 0;
2570
- lastPublishWallMs = wallNowMs;
2571
- lastPublishMediaTimeS = mediaTimeS;
2572
- publishFramesInWindow += 1;
2573
- if (publishWindowStartMs === 0) {
2574
- publishWindowStartMs = wallNowMs;
2575
- }
2576
- const fingerprint = sampleCanvasFingerprint(ctx, outputWidth, outputHeight);
2577
- console.warn("[upload-video \u2192 publishFrame]", {
2578
- frameIndex: publishFrameIndex,
2579
- mediaTimeS: Number(mediaTimeS.toFixed(4)),
2580
- mediaDeltaS: Number(mediaDeltaS.toFixed(4)),
2581
- wallDeltaMs: Number(wallDeltaMs.toFixed(1)),
2582
- effectiveFps: wallDeltaMs > 0 ? Number((1e3 / wallDeltaMs).toFixed(1)) : null,
2583
- presentedFrames,
2584
- size: `${outputWidth}\xD7${outputHeight}`,
2585
- fingerprint
2586
- });
2587
- const windowElapsedMs = wallNowMs - publishWindowStartMs;
2588
- if (windowElapsedMs >= 1e3) {
2589
- console.warn("[upload-video \u2192 publishFps]", {
2590
- framesInLast1s: publishFramesInWindow,
2591
- avgFps: Number((publishFramesInWindow / (windowElapsedMs / 1e3)).toFixed(2)),
2592
- videoCurrentTime: Number(videoEl.currentTime.toFixed(4)),
2593
- videoPaused: videoEl.paused,
2594
- videoReadyState: videoEl.readyState
2595
- });
2596
- publishFramesInWindow = 0;
2597
- publishWindowStartMs = wallNowMs;
2598
- }
2599
- };
2600
- const onPlaybackSample = (mediaTimeS, presentedFrames) => {
2371
+ const onPlaybackSample = (mediaTimeS) => {
2601
2372
  if (destroyed || !shouldSampleAtMediaTime(lastDrawMediaTimeS, mediaTimeS)) {
2602
2373
  return;
2603
2374
  }
2604
2375
  lastDrawMediaTimeS = mediaTimeS;
2605
2376
  lastAdvanceAt = Date.now();
2606
2377
  drawFrame();
2607
- logPublishedFrame(mediaTimeS, presentedFrames);
2608
2378
  };
2609
2379
  const schedulePlaybackWatch = () => {
2610
2380
  if (destroyed) {
@@ -2613,7 +2383,7 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
2613
2383
  const video = videoEl;
2614
2384
  if (video.requestVideoFrameCallback) {
2615
2385
  videoFrameCallbackId = video.requestVideoFrameCallback((_now, metadata) => {
2616
- onPlaybackSample(metadata.mediaTime, metadata.presentedFrames);
2386
+ onPlaybackSample(metadata.mediaTime);
2617
2387
  schedulePlaybackWatch();
2618
2388
  });
2619
2389
  return;
@@ -2624,7 +2394,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
2624
2394
  });
2625
2395
  };
2626
2396
  drawFrame();
2627
- logPublishedFrame(videoEl.currentTime);
2628
2397
  schedulePlaybackWatch();
2629
2398
  const ensurePlaying = () => {
2630
2399
  if (destroyed) {
@@ -2646,18 +2415,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
2646
2415
  videoEl.addEventListener("ended", ensurePlaying);
2647
2416
  videoEl.addEventListener("stalled", ensurePlaying);
2648
2417
  videoEl.addEventListener("waiting", ensurePlaying);
2649
- if (logPublishFrames) {
2650
- const logPlaybackEvent = (eventName) => {
2651
- console.warn("[upload-video \u2192 playbackEvent]", {
2652
- event: eventName,
2653
- currentTime: Number(videoEl.currentTime.toFixed(4)),
2654
- readyState: videoEl.readyState,
2655
- paused: videoEl.paused
2656
- });
2657
- };
2658
- videoEl.addEventListener("waiting", () => logPlaybackEvent("waiting"));
2659
- videoEl.addEventListener("stalled", () => logPlaybackEvent("stalled"));
2660
- }
2661
2418
  const healthIntervalMs = options.healthIntervalMs ?? 3e3;
2662
2419
  let healthTimer = null;
2663
2420
  if (options.onHealthReport) {
@@ -3155,18 +2912,9 @@ function XmaxProvider({ config, children }) {
3155
2912
  const detachRemoteContainer = react.useCallback(() => {
3156
2913
  rtcManagerRef.current?.setRemoteVideoContainer(null);
3157
2914
  }, []);
3158
- const notifyUserError = react.useCallback((message, error) => {
3159
- if (externalOnError) {
3160
- externalOnError(message, error);
3161
- return;
3162
- }
3163
- if (typeof window !== "undefined" && typeof document !== "undefined") {
3164
- browserToast.error(message);
3165
- }
3166
- }, [externalOnError]);
3167
2915
  const reportError = react.useCallback((error, fallbackMessage) => {
3168
- return notifyError(error, notifyUserError, fallbackMessage ?? sdkI18n.t("errors.requestFailed"));
3169
- }, [notifyUserError, sdkI18n]);
2916
+ return notifyError(error, externalOnError, fallbackMessage ?? sdkI18n.t("errors.requestFailed"));
2917
+ }, [externalOnError, sdkI18n]);
3170
2918
  const rtcManagerRef = react.useRef(null);
3171
2919
  if (!rtcManagerRef.current) {
3172
2920
  rtcManagerRef.current = new RtcManager({
@@ -3195,11 +2943,11 @@ function XmaxProvider({ config, children }) {
3195
2943
  baseUrl: config.baseUrl,
3196
2944
  locale: config.locale,
3197
2945
  i18n: sdkI18n,
3198
- onError: notifyUserError
2946
+ onError: externalOnError
3199
2947
  });
3200
2948
  clientRef.current = created;
3201
2949
  return created;
3202
- }, [config.apiKey, config.authToken, config.baseUrl, config.locale, notifyUserError, sdkI18n]);
2950
+ }, [config.apiKey, config.authToken, config.baseUrl, config.locale, externalOnError, sdkI18n]);
3203
2951
  const ensureConnected = react.useCallback(async () => {
3204
2952
  const client = getClient();
3205
2953
  const rtc = rtcManagerRef.current;
@@ -3609,11 +3357,6 @@ function XmaxProvider({ config, children }) {
3609
3357
  if (!activeTaskUid) {
3610
3358
  return;
3611
3359
  }
3612
- console.log("[Xmax] sendTracks", {
3613
- taskUid: activeTaskUid,
3614
- targetSize: sessionTargetSize,
3615
- tracks: options.tracks
3616
- });
3617
3360
  try {
3618
3361
  const event = createTracksRtcRoomEvent({
3619
3362
  userId: rtc.snapshot.userId ?? void 0,
@@ -3666,9 +3409,6 @@ function XmaxProvider({ config, children }) {
3666
3409
  debugLogRef.current("lifecycle", "warn", "remote output stalled", info);
3667
3410
  };
3668
3411
  }, []);
3669
- const changeModel = react.useCallback(async () => {
3670
- return;
3671
- }, []);
3672
3412
  const bindLocalView = react.useCallback((el) => {
3673
3413
  localContainerRef.current = el;
3674
3414
  rtcManagerRef.current?.setLocalVideoContainer(el);
@@ -3711,7 +3451,6 @@ function XmaxProvider({ config, children }) {
3711
3451
  start,
3712
3452
  sendTracks,
3713
3453
  stop,
3714
- changeModel,
3715
3454
  bindLocalView,
3716
3455
  bindRemoteView
3717
3456
  }), [
@@ -3736,7 +3475,6 @@ function XmaxProvider({ config, children }) {
3736
3475
  start,
3737
3476
  sendTracks,
3738
3477
  stop,
3739
- changeModel,
3740
3478
  bindLocalView,
3741
3479
  bindRemoteView
3742
3480
  ]);