@vivix-ai/ivi-frontend-sdk 0.3.10 → 0.3.12

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/dist/index.d.cts CHANGED
@@ -311,6 +311,8 @@ declare class TrtcSourceManager {
311
311
  */
312
312
  private applyAudioPolicy;
313
313
  private applyAIDenoiserPolicy;
314
+ private endRemoteVideoAvailableWait;
315
+ private failRemoteVideoAvailableWait;
314
316
  /**
315
317
  * 销毁单个 source 会话:
316
318
  * 解绑事件、停止远端视频、退出房间并销毁客户端。
package/dist/index.d.ts CHANGED
@@ -311,6 +311,8 @@ declare class TrtcSourceManager {
311
311
  */
312
312
  private applyAudioPolicy;
313
313
  private applyAIDenoiserPolicy;
314
+ private endRemoteVideoAvailableWait;
315
+ private failRemoteVideoAvailableWait;
314
316
  /**
315
317
  * 销毁单个 source 会话:
316
318
  * 解绑事件、停止远端视频、退出房间并销毁客户端。
package/dist/index.js CHANGED
@@ -1538,14 +1538,14 @@ var TrtcSourceManager = class {
1538
1538
  const client = TRTC.create();
1539
1539
  const onRemoteVideoAvailable = (event) => {
1540
1540
  this.log("info", `\u8FDC\u7AEF\u89C6\u9891\u53EF\u7528 source=${session.sourceId} userId=${event.userId} streamType=${event.streamType}`);
1541
- recordIviTelemetrySpan(
1542
- "ivi.media.trtc.remote_video_available",
1543
- this.telemetry,
1544
- buildTrtcMediaTelemetryAttributes(session.sourceId, event.userId, event.streamType)
1545
- );
1541
+ const telemetryAttributes = buildTrtcMediaTelemetryAttributes(session.sourceId, event.userId, event.streamType);
1546
1542
  const remoteVideoKey = buildRemoteVideoKey(event.userId, String(event.streamType));
1547
1543
  session.remoteVideoStreams.add(remoteVideoKey);
1548
1544
  if (!session.hasEverReceivedRemoteVideo) {
1545
+ this.endRemoteVideoAvailableWait(session, {
1546
+ ...telemetryAttributes,
1547
+ "ivi.media.trtc.waiting_remote_video_available.result": "available"
1548
+ });
1549
1549
  session.hasEverReceivedRemoteVideo = true;
1550
1550
  for (const waiter of session.remoteVideoWaiters) {
1551
1551
  waiter(true);
@@ -1592,15 +1592,38 @@ var TrtcSourceManager = class {
1592
1592
  client.on(TRTC.EVENT.REMOTE_AUDIO_AVAILABLE, onRemoteAudioAvailable);
1593
1593
  client.on(TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE, onRemoteAudioUnavailable);
1594
1594
  this.log("info", `\u6B63\u5728\u8FDB\u623F source=${session.sourceId} room=${roomId} sdkAppId=${sdkAppId} userId=${userId}`);
1595
- await client.enterRoom({
1596
- sdkAppId,
1597
- userId,
1598
- userSig,
1599
- scene: TRTC.TYPE.SCENE_LIVE,
1600
- role: TRTC.TYPE.ROLE_AUDIENCE,
1601
- autoReceiveAudio: true,
1602
- ...isStringRoomId ? { strRoomId: roomId } : { roomId: Number(roomId) }
1603
- });
1595
+ session.remoteVideoAvailableSpan = startIviTelemetrySpan(
1596
+ "sdk.media.trtc.waiting_remote_video_available",
1597
+ this.telemetry,
1598
+ buildTrtcWaitingRemoteVideoTelemetryAttributes(session.sourceId, roomId, sdkAppId, isStringRoomId)
1599
+ );
1600
+ const joinRoomSpan = startIviTelemetrySpan(
1601
+ "sdk.media.trtc.join_room",
1602
+ this.telemetry,
1603
+ buildTrtcJoinRoomTelemetryAttributes(session.sourceId, roomId, userId, sdkAppId, isStringRoomId)
1604
+ );
1605
+ try {
1606
+ await client.enterRoom({
1607
+ sdkAppId,
1608
+ userId,
1609
+ userSig,
1610
+ scene: TRTC.TYPE.SCENE_LIVE,
1611
+ role: TRTC.TYPE.ROLE_AUDIENCE,
1612
+ autoReceiveAudio: true,
1613
+ ...isStringRoomId ? { strRoomId: roomId } : { roomId: Number(roomId) }
1614
+ });
1615
+ endIviTelemetrySpan(joinRoomSpan.span, {
1616
+ "ivi.media.trtc.join_room.result": "connected"
1617
+ });
1618
+ } catch (error) {
1619
+ this.failRemoteVideoAvailableWait(session, error, {
1620
+ "ivi.media.trtc.waiting_remote_video_available.result": "join_failed"
1621
+ });
1622
+ failIviTelemetrySpan(joinRoomSpan.span, error, {
1623
+ "ivi.media.trtc.join_room.result": "failed"
1624
+ });
1625
+ throw error;
1626
+ }
1604
1627
  session.TRTC = TRTC;
1605
1628
  session.client = client;
1606
1629
  session.status = "connected";
@@ -1612,6 +1635,9 @@ var TrtcSourceManager = class {
1612
1635
  });
1613
1636
  await this.applyAudioPolicy(session);
1614
1637
  })().catch((error) => {
1638
+ this.failRemoteVideoAvailableWait(session, error, {
1639
+ "ivi.media.trtc.waiting_remote_video_available.result": "connect_failed"
1640
+ });
1615
1641
  session.status = "error";
1616
1642
  session.error = error instanceof Error ? error.message : String(error);
1617
1643
  this.log("error", `\u8FDE\u63A5\u5931\u8D25 source=${session.sourceId} error=${session.error}`);
@@ -1656,7 +1682,7 @@ var TrtcSourceManager = class {
1656
1682
  streamType
1657
1683
  );
1658
1684
  const telemetrySpan = startIviTelemetrySpan(
1659
- "ivi.media.trtc.start_remote_video",
1685
+ "sdk.media.trtc.start_remote_video",
1660
1686
  this.telemetry,
1661
1687
  telemetryAttributes
1662
1688
  );
@@ -1670,7 +1696,7 @@ var TrtcSourceManager = class {
1670
1696
  });
1671
1697
  endIviTelemetrySpan(telemetrySpan.span);
1672
1698
  recordIviTelemetrySpan(
1673
- "ivi.media.trtc.remote_video_rendered",
1699
+ "sdk.media.trtc.remote_video_rendered",
1674
1700
  this.telemetry,
1675
1701
  telemetryAttributes
1676
1702
  );
@@ -1734,6 +1760,22 @@ var TrtcSourceManager = class {
1734
1760
  this.log("warn", `TRTC AIDenoiser \u5F00\u542F\u5931\u8D25 source=${session.sourceId}`, error);
1735
1761
  }
1736
1762
  }
1763
+ endRemoteVideoAvailableWait(session, attributes) {
1764
+ const waitingSpan = session.remoteVideoAvailableSpan;
1765
+ if (!waitingSpan) {
1766
+ return;
1767
+ }
1768
+ session.remoteVideoAvailableSpan = void 0;
1769
+ endIviTelemetrySpan(waitingSpan.span, attributes);
1770
+ }
1771
+ failRemoteVideoAvailableWait(session, error, attributes) {
1772
+ const waitingSpan = session.remoteVideoAvailableSpan;
1773
+ if (!waitingSpan) {
1774
+ return;
1775
+ }
1776
+ session.remoteVideoAvailableSpan = void 0;
1777
+ failIviTelemetrySpan(waitingSpan.span, error, attributes);
1778
+ }
1737
1779
  /**
1738
1780
  * 销毁单个 source 会话:
1739
1781
  * 解绑事件、停止远端视频、退出房间并销毁客户端。
@@ -1747,6 +1789,9 @@ var TrtcSourceManager = class {
1747
1789
  session.remoteVideoStreams.clear();
1748
1790
  session.status = "idle";
1749
1791
  session.error = void 0;
1792
+ this.endRemoteVideoAvailableWait(session, {
1793
+ "ivi.media.trtc.waiting_remote_video_available.result": "cancelled"
1794
+ });
1750
1795
  for (const waiter of session.remoteVideoWaiters) {
1751
1796
  waiter(false);
1752
1797
  }
@@ -1906,6 +1951,23 @@ function buildTrtcMediaTelemetryAttributes(sourceId, userId, streamType) {
1906
1951
  "ivi.trtc.stream_type": String(streamType)
1907
1952
  };
1908
1953
  }
1954
+ function buildTrtcJoinRoomTelemetryAttributes(sourceId, roomId, userId, sdkAppId, isStringRoomId) {
1955
+ return {
1956
+ "ivi.source.id": sourceId,
1957
+ "ivi.trtc.room_id": roomId,
1958
+ "ivi.trtc.user_id": userId,
1959
+ "ivi.trtc.sdk_app_id": sdkAppId,
1960
+ "ivi.trtc.room_id.is_string": isStringRoomId
1961
+ };
1962
+ }
1963
+ function buildTrtcWaitingRemoteVideoTelemetryAttributes(sourceId, roomId, sdkAppId, isStringRoomId) {
1964
+ return {
1965
+ "ivi.source.id": sourceId,
1966
+ "ivi.trtc.room_id": roomId,
1967
+ "ivi.trtc.sdk_app_id": sdkAppId,
1968
+ "ivi.trtc.room_id.is_string": isStringRoomId
1969
+ };
1970
+ }
1909
1971
  function parseRemoteVideoKey(key) {
1910
1972
  const separatorIndex = key.indexOf("::");
1911
1973
  if (separatorIndex < 0) {
@@ -2194,7 +2256,7 @@ var LivekitSourceManager = class {
2194
2256
  });
2195
2257
  if (kind === "video" && !session.hasEverReceivedRemoteVideo) {
2196
2258
  recordIviTelemetrySpan(
2197
- "ivi.media.livekit.remote_video_available",
2259
+ "sdk.media.livekit.remote_video_available",
2198
2260
  this.telemetry,
2199
2261
  {
2200
2262
  "ivi.source.id": session.sourceId,
@@ -2239,7 +2301,22 @@ var LivekitSourceManager = class {
2239
2301
  "info",
2240
2302
  `\u6B63\u5728\u8FDB\u623F source=${session.sourceId} room=${describeLivekitRoom(session.livekit)} ws=${session.livekit.ws_url}`
2241
2303
  );
2242
- await room.connect(session.livekit.ws_url, session.livekit.token);
2304
+ const joinRoomSpan = startIviTelemetrySpan(
2305
+ "sdk.media.livekit.join_room",
2306
+ this.telemetry,
2307
+ buildLivekitJoinRoomTelemetryAttributes(session)
2308
+ );
2309
+ try {
2310
+ await room.connect(session.livekit.ws_url, session.livekit.token);
2311
+ endIviTelemetrySpan(joinRoomSpan.span, {
2312
+ "ivi.media.livekit.join_room.result": "connected"
2313
+ });
2314
+ } catch (error) {
2315
+ failIviTelemetrySpan(joinRoomSpan.span, error, {
2316
+ "ivi.media.livekit.join_room.result": "failed"
2317
+ });
2318
+ throw error;
2319
+ }
2243
2320
  session.room = room;
2244
2321
  session.livekitModule = livekitModule;
2245
2322
  session.status = "connected";
@@ -2374,6 +2451,13 @@ var LivekitSourceManager = class {
2374
2451
  function buildRemoteTrackKey(identity, trackId) {
2375
2452
  return `${identity}::${trackId}`;
2376
2453
  }
2454
+ function buildLivekitJoinRoomTelemetryAttributes(session) {
2455
+ return {
2456
+ "ivi.source.id": session.sourceId,
2457
+ "ivi.livekit.room": session.livekit.room,
2458
+ "ivi.livekit.identity": session.livekit.identity
2459
+ };
2460
+ }
2377
2461
  function enforceContainMedia2(element) {
2378
2462
  element.style.setProperty("width", "100%", "important");
2379
2463
  element.style.setProperty("height", "100%", "important");
@@ -2469,9 +2553,9 @@ var IviRuntimeCoordinator = class {
2469
2553
  * 启动后状态会从 idle/stopped 进入 connecting,连接成功后由事件驱动进入后续状态。
2470
2554
  */
2471
2555
  async start() {
2472
- const telemetrySpan = startIviTelemetrySpan("ivi.runtime.start", this.config.telemetry, {
2556
+ const telemetrySpan = startIviTelemetrySpan("sdk.runtime.start", this.config.telemetry, {
2473
2557
  "ivi.runtime.status": this.state.status,
2474
- "ivi.session.id": this.state.session?.id
2558
+ "session.id": this.state.session?.id
2475
2559
  });
2476
2560
  try {
2477
2561
  this.setState({
@@ -2482,13 +2566,13 @@ var IviRuntimeCoordinator = class {
2482
2566
  await this.client.connect();
2483
2567
  endIviTelemetrySpan(telemetrySpan.span, {
2484
2568
  "ivi.runtime.status": this.state.status,
2485
- "ivi.session.id": this.state.session?.id
2569
+ "session.id": this.state.session?.id
2486
2570
  });
2487
2571
  } catch (error) {
2488
2572
  this.stop();
2489
2573
  failIviTelemetrySpan(telemetrySpan.span, error, {
2490
2574
  "ivi.runtime.status": this.state.status,
2491
- "ivi.session.id": this.state.session?.id
2575
+ "session.id": this.state.session?.id
2492
2576
  });
2493
2577
  throw error;
2494
2578
  }
@@ -2497,9 +2581,9 @@ var IviRuntimeCoordinator = class {
2497
2581
  * 停止协调器并断开实时连接,同时重置运行态数据为 stopped。
2498
2582
  */
2499
2583
  stop() {
2500
- const telemetrySpan = startIviTelemetrySpan("ivi.runtime.stop", this.config.telemetry, {
2584
+ const telemetrySpan = startIviTelemetrySpan("sdk.runtime.stop", this.config.telemetry, {
2501
2585
  "ivi.runtime.status": this.state.status,
2502
- "ivi.session.id": this.state.session?.id
2586
+ "session.id": this.state.session?.id
2503
2587
  });
2504
2588
  try {
2505
2589
  this.dispatcher.stop();
@@ -2511,7 +2595,7 @@ var IviRuntimeCoordinator = class {
2511
2595
  } catch (error) {
2512
2596
  failIviTelemetrySpan(telemetrySpan.span, error, {
2513
2597
  "ivi.runtime.status": this.state.status,
2514
- "ivi.session.id": this.state.session?.id
2598
+ "session.id": this.state.session?.id
2515
2599
  });
2516
2600
  throw error;
2517
2601
  }
@@ -2812,16 +2896,7 @@ var IviRuntimeCoordinator = class {
2812
2896
  if (this.state.status === composedNextState.status && this.state.session === composedNextState.session && this.state.stage === composedNextState.stage && this.state.tracks === composedNextState.tracks && this.state.sources === composedNextState.sources && this.state.streams === composedNextState.streams && this.state.conversationItems === composedNextState.conversationItems && this.state.conversations === composedNextState.conversations && isSameBootstrapState(this.state.bootstrap, composedNextState.bootstrap)) {
2813
2897
  return;
2814
2898
  }
2815
- const previousState = this.state;
2816
2899
  this.state = composedNextState;
2817
- if (previousState.status !== composedNextState.status) {
2818
- recordIviTelemetrySpan("ivi.runtime.state_change", this.config.telemetry, {
2819
- "ivi.runtime.status.previous": previousState.status,
2820
- "ivi.runtime.status.next": composedNextState.status,
2821
- "ivi.runtime.state_change.reason": "state_update",
2822
- "ivi.session.id": composedNextState.session?.id ?? previousState.session?.id
2823
- });
2824
- }
2825
2900
  this.stateListeners.forEach((listener) => listener(this.state));
2826
2901
  }
2827
2902
  composeBootstrapState(nextState) {
@@ -3105,7 +3180,7 @@ async function createIVISession(request, options) {
3105
3180
  throw new Error("fetch is not available. Pass options.fetch to createIVISession.");
3106
3181
  }
3107
3182
  const telemetrySpan = startIviTelemetrySpan(
3108
- "ivi.session.create",
3183
+ "sdk.session.create",
3109
3184
  options.telemetry,
3110
3185
  buildCreateSessionTelemetryAttributes(request)
3111
3186
  );
@@ -3132,7 +3207,7 @@ async function createIVISession(request, options) {
3132
3207
  const result = normalizeCreateIVISessionResponse(responseBody, request, requestBody);
3133
3208
  endIviTelemetrySpan(telemetrySpan.span, {
3134
3209
  "http.response.status_code": response.status,
3135
- "ivi.session.id": result.iviSessionId,
3210
+ "session.id": result.iviSessionId,
3136
3211
  "ivi.prebuild.playback.kind": result.prebuiltPlayback?.kind
3137
3212
  });
3138
3213
  return result;
@@ -3144,14 +3219,18 @@ async function createIVISession(request, options) {
3144
3219
  }
3145
3220
  }
3146
3221
  function createRuntimeFromSession(session, options = {}) {
3147
- const telemetrySpan = startIviTelemetrySpan("ivi.runtime.create", options.telemetry, {
3148
- "ivi.session.id": session.iviSessionId,
3149
- "ivi.prebuild.playback.kind": session.prebuiltPlayback?.kind
3222
+ const fastStartEnabled = options.fastStart !== false;
3223
+ const fastStartApplied = fastStartEnabled && Boolean(session.prebuiltPlayback);
3224
+ const telemetrySpan = startIviTelemetrySpan("sdk.runtime.create", options.telemetry, {
3225
+ "session.id": session.iviSessionId,
3226
+ "ivi.prebuild.playback.kind": session.prebuiltPlayback?.kind,
3227
+ "ivi.fast_start.enabled": fastStartEnabled,
3228
+ "ivi.fast_start.applied": fastStartApplied
3150
3229
  });
3151
3230
  try {
3152
3231
  const websocketUrl = buildWebSocketUrl(session.endpoint, options.websocket);
3153
3232
  const childTelemetry = withIviTelemetryContext(options.telemetry, telemetrySpan.context, {
3154
- "ivi.session.id": session.iviSessionId
3233
+ "session.id": session.iviSessionId
3155
3234
  });
3156
3235
  const clientTelemetry = mergeIviTelemetryOptions(
3157
3236
  options.clientConfig?.telemetry,
@@ -3175,7 +3254,7 @@ function createRuntimeFromSession(session, options = {}) {
3175
3254
  ...options.runtimeConfig ?? {},
3176
3255
  telemetry: runtimeTelemetry
3177
3256
  });
3178
- if (options.fastStart !== false && session.prebuiltPlayback) {
3257
+ if (fastStartEnabled && session.prebuiltPlayback) {
3179
3258
  runtime.setBootstrapSource(toBootstrapSource(session.prebuiltPlayback, options));
3180
3259
  }
3181
3260
  endIviTelemetrySpan(telemetrySpan.span);
@@ -4803,7 +4882,7 @@ function IVIHlsVideo(props) {
4803
4882
  const onVideoError = () => {
4804
4883
  const el = videoRef.current;
4805
4884
  const mediaErr = el?.error;
4806
- recordVideoTelemetry("ivi.media.video.error", telemetry, sourceId, "hls", mediaErr);
4885
+ recordVideoTelemetry("sdk.media.video.error", telemetry, sourceId, "hls", mediaErr);
4807
4886
  emitHlsLog(onLog, "warn", "<video> \u5143\u7D20\u62A5\u9519", {
4808
4887
  code: mediaErr?.code,
4809
4888
  message: mediaErr?.message,
@@ -4814,7 +4893,7 @@ function IVIHlsVideo(props) {
4814
4893
  };
4815
4894
  const onVideoStalled = () => {
4816
4895
  recordVideoTelemetry(
4817
- "ivi.media.video.stalled",
4896
+ "sdk.media.video.stalled",
4818
4897
  telemetry,
4819
4898
  sourceId,
4820
4899
  "hls",
@@ -5210,7 +5289,7 @@ function SlotVideo(props) {
5210
5289
  }, [props.paused]);
5211
5290
  const onError = (event) => {
5212
5291
  recordPlainVideoTelemetry(
5213
- "ivi.media.video.error",
5292
+ "sdk.media.video.error",
5214
5293
  props.telemetry,
5215
5294
  props.sourceId,
5216
5295
  event.currentTarget.error
@@ -5219,7 +5298,7 @@ function SlotVideo(props) {
5219
5298
  };
5220
5299
  const onStalled = (event) => {
5221
5300
  recordPlainVideoTelemetry(
5222
- "ivi.media.video.stalled",
5301
+ "sdk.media.video.stalled",
5223
5302
  props.telemetry,
5224
5303
  props.sourceId,
5225
5304
  new Error("<video> stalled")