@vivix-ai/ivi-frontend-sdk 0.3.9 → 0.3.11
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 +44 -0
- package/dist/index.cjs +501 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -3
- package/dist/index.d.ts +37 -3
- package/dist/index.js +501 -63
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var iviSdkTs = require('@vivix-ai/ivi-sdk-ts');
|
|
4
|
+
var api = require('@opentelemetry/api');
|
|
4
5
|
var websocket = require('@vivix-ai/ivi-sdk-ts/transports/websocket');
|
|
5
6
|
var react = require('react');
|
|
6
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -1141,6 +1142,94 @@ var ConversationManager = class {
|
|
|
1141
1142
|
];
|
|
1142
1143
|
}
|
|
1143
1144
|
};
|
|
1145
|
+
var DEFAULT_TRACER_NAME = "@vivix-ai/ivi-frontend-sdk";
|
|
1146
|
+
function getIviTelemetryTracer(options) {
|
|
1147
|
+
return options?.tracer ?? api.trace.getTracer(DEFAULT_TRACER_NAME);
|
|
1148
|
+
}
|
|
1149
|
+
function getIviTelemetryContext(options) {
|
|
1150
|
+
return options?.context ?? api.context.active();
|
|
1151
|
+
}
|
|
1152
|
+
function startIviTelemetrySpan(name, options, attributes) {
|
|
1153
|
+
const tracer = getIviTelemetryTracer(options);
|
|
1154
|
+
const parentContext = getIviTelemetryContext(options);
|
|
1155
|
+
const span = tracer.startSpan(
|
|
1156
|
+
name,
|
|
1157
|
+
{
|
|
1158
|
+
kind: api.SpanKind.INTERNAL,
|
|
1159
|
+
attributes: mergeIviTelemetryAttributes(options?.attributes, attributes)
|
|
1160
|
+
},
|
|
1161
|
+
parentContext
|
|
1162
|
+
);
|
|
1163
|
+
return {
|
|
1164
|
+
span,
|
|
1165
|
+
context: api.trace.setSpan(parentContext, span)
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
function endIviTelemetrySpan(span, attributes) {
|
|
1169
|
+
const cleaned = cleanIviTelemetryAttributes(attributes);
|
|
1170
|
+
if (cleaned) {
|
|
1171
|
+
span.setAttributes(cleaned);
|
|
1172
|
+
}
|
|
1173
|
+
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
1174
|
+
span.end();
|
|
1175
|
+
}
|
|
1176
|
+
function failIviTelemetrySpan(span, error, attributes) {
|
|
1177
|
+
const cleaned = cleanIviTelemetryAttributes(attributes);
|
|
1178
|
+
if (cleaned) {
|
|
1179
|
+
span.setAttributes(cleaned);
|
|
1180
|
+
}
|
|
1181
|
+
recordIviTelemetryError(span, error);
|
|
1182
|
+
span.end();
|
|
1183
|
+
}
|
|
1184
|
+
function recordIviTelemetrySpan(name, options, attributes, error) {
|
|
1185
|
+
const { span } = startIviTelemetrySpan(name, options, attributes);
|
|
1186
|
+
if (error === void 0) {
|
|
1187
|
+
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
1188
|
+
} else {
|
|
1189
|
+
recordIviTelemetryError(span, error);
|
|
1190
|
+
}
|
|
1191
|
+
span.end();
|
|
1192
|
+
}
|
|
1193
|
+
function withIviTelemetryContext(options, context, attributes) {
|
|
1194
|
+
return {
|
|
1195
|
+
...options,
|
|
1196
|
+
context,
|
|
1197
|
+
attributes: mergeIviTelemetryAttributes(options?.attributes, attributes)
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
function mergeIviTelemetryAttributes(base, next) {
|
|
1201
|
+
return cleanIviTelemetryAttributes({
|
|
1202
|
+
...base ?? {},
|
|
1203
|
+
...next ?? {}
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
function cleanIviTelemetryAttributes(attributes) {
|
|
1207
|
+
const cleaned = {};
|
|
1208
|
+
Object.entries(attributes ?? {}).forEach(([key, value]) => {
|
|
1209
|
+
if (isIviTelemetryAttributeValue(value)) {
|
|
1210
|
+
cleaned[key] = value;
|
|
1211
|
+
}
|
|
1212
|
+
});
|
|
1213
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
1214
|
+
}
|
|
1215
|
+
function recordIviTelemetryError(span, error) {
|
|
1216
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1217
|
+
span.recordException(error instanceof Error ? error : message);
|
|
1218
|
+
span.setStatus({
|
|
1219
|
+
code: api.SpanStatusCode.ERROR,
|
|
1220
|
+
message
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
function isIviTelemetryAttributeValue(value) {
|
|
1224
|
+
if (typeof value === "string" || typeof value === "boolean") return true;
|
|
1225
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1226
|
+
if (!Array.isArray(value)) return false;
|
|
1227
|
+
const nonNullValues = value.filter((item) => item !== null && item !== void 0);
|
|
1228
|
+
if (nonNullValues.length === 0) return true;
|
|
1229
|
+
const firstType = typeof nonNullValues[0];
|
|
1230
|
+
if (firstType !== "string" && firstType !== "number" && firstType !== "boolean") return false;
|
|
1231
|
+
return nonNullValues.every((item) => typeof item === firstType && (typeof item !== "number" || Number.isFinite(item)));
|
|
1232
|
+
}
|
|
1144
1233
|
|
|
1145
1234
|
// src/runtime/managers/trtc-source-manager.ts
|
|
1146
1235
|
var TAG = "[IVI-TRTC]";
|
|
@@ -1151,10 +1240,11 @@ var DEFAULT_DENOISER_OPTIONS = {
|
|
|
1151
1240
|
mode: "normal"
|
|
1152
1241
|
};
|
|
1153
1242
|
var TrtcSourceManager = class {
|
|
1154
|
-
constructor(onLog, onTrtcEvent, aiDenoiser) {
|
|
1243
|
+
constructor(onLog, onTrtcEvent, aiDenoiser, telemetry) {
|
|
1155
1244
|
this.onLog = onLog;
|
|
1156
1245
|
this.onTrtcEvent = onTrtcEvent;
|
|
1157
1246
|
this.aiDenoiser = aiDenoiser;
|
|
1247
|
+
this.telemetry = telemetry;
|
|
1158
1248
|
this.sessions = /* @__PURE__ */ new Map();
|
|
1159
1249
|
this.sourceSessionKeys = /* @__PURE__ */ new Map();
|
|
1160
1250
|
this.listeners = /* @__PURE__ */ new Map();
|
|
@@ -1450,9 +1540,14 @@ var TrtcSourceManager = class {
|
|
|
1450
1540
|
const client = TRTC.create();
|
|
1451
1541
|
const onRemoteVideoAvailable = (event) => {
|
|
1452
1542
|
this.log("info", `\u8FDC\u7AEF\u89C6\u9891\u53EF\u7528 source=${session.sourceId} userId=${event.userId} streamType=${event.streamType}`);
|
|
1543
|
+
const telemetryAttributes = buildTrtcMediaTelemetryAttributes(session.sourceId, event.userId, event.streamType);
|
|
1453
1544
|
const remoteVideoKey = buildRemoteVideoKey(event.userId, String(event.streamType));
|
|
1454
1545
|
session.remoteVideoStreams.add(remoteVideoKey);
|
|
1455
1546
|
if (!session.hasEverReceivedRemoteVideo) {
|
|
1547
|
+
this.endRemoteVideoAvailableWait(session, {
|
|
1548
|
+
...telemetryAttributes,
|
|
1549
|
+
"ivi.media.trtc.waiting_remote_video_available.result": "available"
|
|
1550
|
+
});
|
|
1456
1551
|
session.hasEverReceivedRemoteVideo = true;
|
|
1457
1552
|
for (const waiter of session.remoteVideoWaiters) {
|
|
1458
1553
|
waiter(true);
|
|
@@ -1499,15 +1594,38 @@ var TrtcSourceManager = class {
|
|
|
1499
1594
|
client.on(TRTC.EVENT.REMOTE_AUDIO_AVAILABLE, onRemoteAudioAvailable);
|
|
1500
1595
|
client.on(TRTC.EVENT.REMOTE_AUDIO_UNAVAILABLE, onRemoteAudioUnavailable);
|
|
1501
1596
|
this.log("info", `\u6B63\u5728\u8FDB\u623F source=${session.sourceId} room=${roomId} sdkAppId=${sdkAppId} userId=${userId}`);
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1597
|
+
session.remoteVideoAvailableSpan = startIviTelemetrySpan(
|
|
1598
|
+
"sdk.media.trtc.waiting_remote_video_available",
|
|
1599
|
+
this.telemetry,
|
|
1600
|
+
buildTrtcWaitingRemoteVideoTelemetryAttributes(session.sourceId, roomId, sdkAppId, isStringRoomId)
|
|
1601
|
+
);
|
|
1602
|
+
const joinRoomSpan = startIviTelemetrySpan(
|
|
1603
|
+
"sdk.media.trtc.join_room",
|
|
1604
|
+
this.telemetry,
|
|
1605
|
+
buildTrtcJoinRoomTelemetryAttributes(session.sourceId, roomId, userId, sdkAppId, isStringRoomId)
|
|
1606
|
+
);
|
|
1607
|
+
try {
|
|
1608
|
+
await client.enterRoom({
|
|
1609
|
+
sdkAppId,
|
|
1610
|
+
userId,
|
|
1611
|
+
userSig,
|
|
1612
|
+
scene: TRTC.TYPE.SCENE_LIVE,
|
|
1613
|
+
role: TRTC.TYPE.ROLE_AUDIENCE,
|
|
1614
|
+
autoReceiveAudio: true,
|
|
1615
|
+
...isStringRoomId ? { strRoomId: roomId } : { roomId: Number(roomId) }
|
|
1616
|
+
});
|
|
1617
|
+
endIviTelemetrySpan(joinRoomSpan.span, {
|
|
1618
|
+
"ivi.media.trtc.join_room.result": "connected"
|
|
1619
|
+
});
|
|
1620
|
+
} catch (error) {
|
|
1621
|
+
this.failRemoteVideoAvailableWait(session, error, {
|
|
1622
|
+
"ivi.media.trtc.waiting_remote_video_available.result": "join_failed"
|
|
1623
|
+
});
|
|
1624
|
+
failIviTelemetrySpan(joinRoomSpan.span, error, {
|
|
1625
|
+
"ivi.media.trtc.join_room.result": "failed"
|
|
1626
|
+
});
|
|
1627
|
+
throw error;
|
|
1628
|
+
}
|
|
1511
1629
|
session.TRTC = TRTC;
|
|
1512
1630
|
session.client = client;
|
|
1513
1631
|
session.status = "connected";
|
|
@@ -1519,6 +1637,9 @@ var TrtcSourceManager = class {
|
|
|
1519
1637
|
});
|
|
1520
1638
|
await this.applyAudioPolicy(session);
|
|
1521
1639
|
})().catch((error) => {
|
|
1640
|
+
this.failRemoteVideoAvailableWait(session, error, {
|
|
1641
|
+
"ivi.media.trtc.waiting_remote_video_available.result": "connect_failed"
|
|
1642
|
+
});
|
|
1522
1643
|
session.status = "error";
|
|
1523
1644
|
session.error = error instanceof Error ? error.message : String(error);
|
|
1524
1645
|
this.log("error", `\u8FDE\u63A5\u5931\u8D25 source=${session.sourceId} error=${session.error}`);
|
|
@@ -1557,6 +1678,16 @@ var TrtcSourceManager = class {
|
|
|
1557
1678
|
return;
|
|
1558
1679
|
}
|
|
1559
1680
|
binding.startingVideoKeys.add(remoteVideoKey);
|
|
1681
|
+
const telemetryAttributes = buildTrtcMediaTelemetryAttributes(
|
|
1682
|
+
binding.sourceId,
|
|
1683
|
+
userId,
|
|
1684
|
+
streamType
|
|
1685
|
+
);
|
|
1686
|
+
const telemetrySpan = startIviTelemetrySpan(
|
|
1687
|
+
"sdk.media.trtc.start_remote_video",
|
|
1688
|
+
this.telemetry,
|
|
1689
|
+
telemetryAttributes
|
|
1690
|
+
);
|
|
1560
1691
|
try {
|
|
1561
1692
|
this.log("info", `\u5F00\u59CB\u6E32\u67D3\u8FDC\u7AEF\u89C6\u9891 source=${binding.sourceId} view=${remoteVideoKey} userId=${userId} streamType=${streamType}`);
|
|
1562
1693
|
await client.startRemoteVideo({
|
|
@@ -1565,14 +1696,24 @@ var TrtcSourceManager = class {
|
|
|
1565
1696
|
view: binding.container,
|
|
1566
1697
|
option: { fillMode: "contain" }
|
|
1567
1698
|
});
|
|
1699
|
+
endIviTelemetrySpan(telemetrySpan.span);
|
|
1700
|
+
recordIviTelemetrySpan(
|
|
1701
|
+
"sdk.media.trtc.remote_video_rendered",
|
|
1702
|
+
this.telemetry,
|
|
1703
|
+
telemetryAttributes
|
|
1704
|
+
);
|
|
1568
1705
|
this.log("info", `\u8FDC\u7AEF\u89C6\u9891\u6E32\u67D3\u5B8C\u6210 source=${binding.sourceId} userId=${userId} streamType=${streamType}`);
|
|
1569
1706
|
binding.startedVideoKeys.add(remoteVideoKey);
|
|
1570
1707
|
enforceContainMedia(binding.container);
|
|
1571
1708
|
} catch (error) {
|
|
1572
1709
|
if (error instanceof Error && /already started|OPERATION_ABORT/i.test(error.message)) {
|
|
1573
1710
|
binding.startedVideoKeys.add(remoteVideoKey);
|
|
1711
|
+
endIviTelemetrySpan(telemetrySpan.span, {
|
|
1712
|
+
"ivi.media.trtc.start_remote_video.result": "already_started"
|
|
1713
|
+
});
|
|
1574
1714
|
return;
|
|
1575
1715
|
}
|
|
1716
|
+
failIviTelemetrySpan(telemetrySpan.span, error);
|
|
1576
1717
|
this.log("warn", `\u8FDC\u7AEF\u89C6\u9891\u6E32\u67D3\u5931\u8D25 userId=${userId} streamType=${streamType}`, error);
|
|
1577
1718
|
} finally {
|
|
1578
1719
|
binding.startingVideoKeys.delete(remoteVideoKey);
|
|
@@ -1621,6 +1762,22 @@ var TrtcSourceManager = class {
|
|
|
1621
1762
|
this.log("warn", `TRTC AIDenoiser \u5F00\u542F\u5931\u8D25 source=${session.sourceId}`, error);
|
|
1622
1763
|
}
|
|
1623
1764
|
}
|
|
1765
|
+
endRemoteVideoAvailableWait(session, attributes) {
|
|
1766
|
+
const waitingSpan = session.remoteVideoAvailableSpan;
|
|
1767
|
+
if (!waitingSpan) {
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1770
|
+
session.remoteVideoAvailableSpan = void 0;
|
|
1771
|
+
endIviTelemetrySpan(waitingSpan.span, attributes);
|
|
1772
|
+
}
|
|
1773
|
+
failRemoteVideoAvailableWait(session, error, attributes) {
|
|
1774
|
+
const waitingSpan = session.remoteVideoAvailableSpan;
|
|
1775
|
+
if (!waitingSpan) {
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
session.remoteVideoAvailableSpan = void 0;
|
|
1779
|
+
failIviTelemetrySpan(waitingSpan.span, error, attributes);
|
|
1780
|
+
}
|
|
1624
1781
|
/**
|
|
1625
1782
|
* 销毁单个 source 会话:
|
|
1626
1783
|
* 解绑事件、停止远端视频、退出房间并销毁客户端。
|
|
@@ -1634,6 +1791,9 @@ var TrtcSourceManager = class {
|
|
|
1634
1791
|
session.remoteVideoStreams.clear();
|
|
1635
1792
|
session.status = "idle";
|
|
1636
1793
|
session.error = void 0;
|
|
1794
|
+
this.endRemoteVideoAvailableWait(session, {
|
|
1795
|
+
"ivi.media.trtc.waiting_remote_video_available.result": "cancelled"
|
|
1796
|
+
});
|
|
1637
1797
|
for (const waiter of session.remoteVideoWaiters) {
|
|
1638
1798
|
waiter(false);
|
|
1639
1799
|
}
|
|
@@ -1786,6 +1946,30 @@ function getAIDenoiserModeValue(mode) {
|
|
|
1786
1946
|
function buildRemoteVideoKey(userId, streamType) {
|
|
1787
1947
|
return `${userId}::${streamType}`;
|
|
1788
1948
|
}
|
|
1949
|
+
function buildTrtcMediaTelemetryAttributes(sourceId, userId, streamType) {
|
|
1950
|
+
return {
|
|
1951
|
+
"ivi.source.id": sourceId,
|
|
1952
|
+
"ivi.trtc.user_id": userId,
|
|
1953
|
+
"ivi.trtc.stream_type": String(streamType)
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
function buildTrtcJoinRoomTelemetryAttributes(sourceId, roomId, userId, sdkAppId, isStringRoomId) {
|
|
1957
|
+
return {
|
|
1958
|
+
"ivi.source.id": sourceId,
|
|
1959
|
+
"ivi.trtc.room_id": roomId,
|
|
1960
|
+
"ivi.trtc.user_id": userId,
|
|
1961
|
+
"ivi.trtc.sdk_app_id": sdkAppId,
|
|
1962
|
+
"ivi.trtc.room_id.is_string": isStringRoomId
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
function buildTrtcWaitingRemoteVideoTelemetryAttributes(sourceId, roomId, sdkAppId, isStringRoomId) {
|
|
1966
|
+
return {
|
|
1967
|
+
"ivi.source.id": sourceId,
|
|
1968
|
+
"ivi.trtc.room_id": roomId,
|
|
1969
|
+
"ivi.trtc.sdk_app_id": sdkAppId,
|
|
1970
|
+
"ivi.trtc.room_id.is_string": isStringRoomId
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1789
1973
|
function parseRemoteVideoKey(key) {
|
|
1790
1974
|
const separatorIndex = key.indexOf("::");
|
|
1791
1975
|
if (separatorIndex < 0) {
|
|
@@ -1848,9 +2032,10 @@ function describeLivekitRoom(livekit) {
|
|
|
1848
2032
|
// src/runtime/managers/livekit-source-manager.ts
|
|
1849
2033
|
var TAG2 = "[IVI-LIVEKIT]";
|
|
1850
2034
|
var LivekitSourceManager = class {
|
|
1851
|
-
constructor(onLog, onRemoteVideoAvailable) {
|
|
2035
|
+
constructor(onLog, onRemoteVideoAvailable, telemetry) {
|
|
1852
2036
|
this.onLog = onLog;
|
|
1853
2037
|
this.onRemoteVideoAvailable = onRemoteVideoAvailable;
|
|
2038
|
+
this.telemetry = telemetry;
|
|
1854
2039
|
this.sessions = /* @__PURE__ */ new Map();
|
|
1855
2040
|
this.listeners = /* @__PURE__ */ new Map();
|
|
1856
2041
|
}
|
|
@@ -2072,6 +2257,15 @@ var LivekitSourceManager = class {
|
|
|
2072
2257
|
kind
|
|
2073
2258
|
});
|
|
2074
2259
|
if (kind === "video" && !session.hasEverReceivedRemoteVideo) {
|
|
2260
|
+
recordIviTelemetrySpan(
|
|
2261
|
+
"sdk.media.livekit.remote_video_available",
|
|
2262
|
+
this.telemetry,
|
|
2263
|
+
{
|
|
2264
|
+
"ivi.source.id": session.sourceId,
|
|
2265
|
+
"ivi.livekit.participant_identity": participant.identity,
|
|
2266
|
+
"ivi.livekit.track_sid": track.sid
|
|
2267
|
+
}
|
|
2268
|
+
);
|
|
2075
2269
|
session.hasEverReceivedRemoteVideo = true;
|
|
2076
2270
|
for (const waiter of session.remoteVideoWaiters) {
|
|
2077
2271
|
waiter(true);
|
|
@@ -2109,7 +2303,22 @@ var LivekitSourceManager = class {
|
|
|
2109
2303
|
"info",
|
|
2110
2304
|
`\u6B63\u5728\u8FDB\u623F source=${session.sourceId} room=${describeLivekitRoom(session.livekit)} ws=${session.livekit.ws_url}`
|
|
2111
2305
|
);
|
|
2112
|
-
|
|
2306
|
+
const joinRoomSpan = startIviTelemetrySpan(
|
|
2307
|
+
"sdk.media.livekit.join_room",
|
|
2308
|
+
this.telemetry,
|
|
2309
|
+
buildLivekitJoinRoomTelemetryAttributes(session)
|
|
2310
|
+
);
|
|
2311
|
+
try {
|
|
2312
|
+
await room.connect(session.livekit.ws_url, session.livekit.token);
|
|
2313
|
+
endIviTelemetrySpan(joinRoomSpan.span, {
|
|
2314
|
+
"ivi.media.livekit.join_room.result": "connected"
|
|
2315
|
+
});
|
|
2316
|
+
} catch (error) {
|
|
2317
|
+
failIviTelemetrySpan(joinRoomSpan.span, error, {
|
|
2318
|
+
"ivi.media.livekit.join_room.result": "failed"
|
|
2319
|
+
});
|
|
2320
|
+
throw error;
|
|
2321
|
+
}
|
|
2113
2322
|
session.room = room;
|
|
2114
2323
|
session.livekitModule = livekitModule;
|
|
2115
2324
|
session.status = "connected";
|
|
@@ -2244,6 +2453,13 @@ var LivekitSourceManager = class {
|
|
|
2244
2453
|
function buildRemoteTrackKey(identity, trackId) {
|
|
2245
2454
|
return `${identity}::${trackId}`;
|
|
2246
2455
|
}
|
|
2456
|
+
function buildLivekitJoinRoomTelemetryAttributes(session) {
|
|
2457
|
+
return {
|
|
2458
|
+
"ivi.source.id": session.sourceId,
|
|
2459
|
+
"ivi.livekit.room": session.livekit.room,
|
|
2460
|
+
"ivi.livekit.identity": session.livekit.identity
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2247
2463
|
function enforceContainMedia2(element) {
|
|
2248
2464
|
element.style.setProperty("width", "100%", "important");
|
|
2249
2465
|
element.style.setProperty("height", "100%", "important");
|
|
@@ -2293,11 +2509,16 @@ var IviRuntimeCoordinator = class {
|
|
|
2293
2509
|
this.trtcSourceManager = new TrtcSourceManager(
|
|
2294
2510
|
this.config.onLog,
|
|
2295
2511
|
(event) => this.onTrtcManagerEvent(event),
|
|
2296
|
-
this.config.trtcAIDenoiser
|
|
2512
|
+
this.config.trtcAIDenoiser,
|
|
2513
|
+
this.config.telemetry
|
|
2514
|
+
);
|
|
2515
|
+
this.livekitSourceManager = new LivekitSourceManager(
|
|
2516
|
+
this.config.onLog,
|
|
2517
|
+
() => {
|
|
2518
|
+
this.recomposeBootstrapState();
|
|
2519
|
+
},
|
|
2520
|
+
this.config.telemetry
|
|
2297
2521
|
);
|
|
2298
|
-
this.livekitSourceManager = new LivekitSourceManager(this.config.onLog, () => {
|
|
2299
|
-
this.recomposeBootstrapState();
|
|
2300
|
-
});
|
|
2301
2522
|
this.sessionHandler = new SessionEventHandler(this.sessionManager, {
|
|
2302
2523
|
onSessionCreated: (event) => this.onSessionCreated(event),
|
|
2303
2524
|
onSessionEnded: (event) => this.onSessionEnded(event)
|
|
@@ -2334,15 +2555,27 @@ var IviRuntimeCoordinator = class {
|
|
|
2334
2555
|
* 启动后状态会从 idle/stopped 进入 connecting,连接成功后由事件驱动进入后续状态。
|
|
2335
2556
|
*/
|
|
2336
2557
|
async start() {
|
|
2337
|
-
this.
|
|
2338
|
-
|
|
2339
|
-
|
|
2558
|
+
const telemetrySpan = startIviTelemetrySpan("sdk.runtime.start", this.config.telemetry, {
|
|
2559
|
+
"ivi.runtime.status": this.state.status,
|
|
2560
|
+
"ivi.session.id": this.state.session?.id
|
|
2340
2561
|
});
|
|
2341
|
-
this.dispatcher.start();
|
|
2342
2562
|
try {
|
|
2563
|
+
this.setState({
|
|
2564
|
+
...this.state,
|
|
2565
|
+
status: "connecting"
|
|
2566
|
+
});
|
|
2567
|
+
this.dispatcher.start();
|
|
2343
2568
|
await this.client.connect();
|
|
2569
|
+
endIviTelemetrySpan(telemetrySpan.span, {
|
|
2570
|
+
"ivi.runtime.status": this.state.status,
|
|
2571
|
+
"ivi.session.id": this.state.session?.id
|
|
2572
|
+
});
|
|
2344
2573
|
} catch (error) {
|
|
2345
2574
|
this.stop();
|
|
2575
|
+
failIviTelemetrySpan(telemetrySpan.span, error, {
|
|
2576
|
+
"ivi.runtime.status": this.state.status,
|
|
2577
|
+
"ivi.session.id": this.state.session?.id
|
|
2578
|
+
});
|
|
2346
2579
|
throw error;
|
|
2347
2580
|
}
|
|
2348
2581
|
}
|
|
@@ -2350,13 +2583,31 @@ var IviRuntimeCoordinator = class {
|
|
|
2350
2583
|
* 停止协调器并断开实时连接,同时重置运行态数据为 stopped。
|
|
2351
2584
|
*/
|
|
2352
2585
|
stop() {
|
|
2353
|
-
this.
|
|
2354
|
-
|
|
2355
|
-
|
|
2586
|
+
const telemetrySpan = startIviTelemetrySpan("sdk.runtime.stop", this.config.telemetry, {
|
|
2587
|
+
"ivi.runtime.status": this.state.status,
|
|
2588
|
+
"ivi.session.id": this.state.session?.id
|
|
2589
|
+
});
|
|
2590
|
+
try {
|
|
2591
|
+
this.dispatcher.stop();
|
|
2592
|
+
this.client.disconnect();
|
|
2593
|
+
this.resetStoppedState();
|
|
2594
|
+
endIviTelemetrySpan(telemetrySpan.span, {
|
|
2595
|
+
"ivi.runtime.status": this.state.status
|
|
2596
|
+
});
|
|
2597
|
+
} catch (error) {
|
|
2598
|
+
failIviTelemetrySpan(telemetrySpan.span, error, {
|
|
2599
|
+
"ivi.runtime.status": this.state.status,
|
|
2600
|
+
"ivi.session.id": this.state.session?.id
|
|
2601
|
+
});
|
|
2602
|
+
throw error;
|
|
2603
|
+
}
|
|
2356
2604
|
}
|
|
2357
2605
|
getState() {
|
|
2358
2606
|
return this.state;
|
|
2359
2607
|
}
|
|
2608
|
+
getTelemetryOptions() {
|
|
2609
|
+
return this.config.telemetry;
|
|
2610
|
+
}
|
|
2360
2611
|
onStateChange(listener) {
|
|
2361
2612
|
this.stateListeners.add(listener);
|
|
2362
2613
|
return () => {
|
|
@@ -2930,44 +3181,101 @@ async function createIVISession(request, options) {
|
|
|
2930
3181
|
if (!fetchImpl) {
|
|
2931
3182
|
throw new Error("fetch is not available. Pass options.fetch to createIVISession.");
|
|
2932
3183
|
}
|
|
2933
|
-
const
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3184
|
+
const telemetrySpan = startIviTelemetrySpan(
|
|
3185
|
+
"sdk.session.create",
|
|
3186
|
+
options.telemetry,
|
|
3187
|
+
buildCreateSessionTelemetryAttributes(request)
|
|
3188
|
+
);
|
|
3189
|
+
try {
|
|
3190
|
+
const requestBody = toCpCreateIVISessionRequestBody(request);
|
|
3191
|
+
const headers = await buildHeaders(options.headers);
|
|
3192
|
+
injectIviTelemetryHeaders(headers, telemetrySpan.context);
|
|
3193
|
+
const response = await fetchImpl(resolveCreateIVISessionUrl(options), {
|
|
3194
|
+
method: "POST",
|
|
3195
|
+
headers,
|
|
3196
|
+
body: JSON.stringify(requestBody),
|
|
3197
|
+
credentials: options.credentials,
|
|
3198
|
+
signal: options.signal
|
|
3199
|
+
});
|
|
3200
|
+
const responseBody = await readJsonResponse(response);
|
|
3201
|
+
if (!response.ok) {
|
|
3202
|
+
const error = new IviCreateIVISessionError(response, responseBody);
|
|
3203
|
+
failIviTelemetrySpan(telemetrySpan.span, error, {
|
|
3204
|
+
"http.response.status_code": response.status,
|
|
3205
|
+
"http.response.status_text": response.statusText
|
|
3206
|
+
});
|
|
3207
|
+
throw error;
|
|
3208
|
+
}
|
|
3209
|
+
const result = normalizeCreateIVISessionResponse(responseBody, request, requestBody);
|
|
3210
|
+
endIviTelemetrySpan(telemetrySpan.span, {
|
|
3211
|
+
"http.response.status_code": response.status,
|
|
3212
|
+
"ivi.session.id": result.iviSessionId,
|
|
3213
|
+
"ivi.prebuild.playback.kind": result.prebuiltPlayback?.kind
|
|
3214
|
+
});
|
|
3215
|
+
return result;
|
|
3216
|
+
} catch (error) {
|
|
3217
|
+
if (!(error instanceof IviCreateIVISessionError)) {
|
|
3218
|
+
failIviTelemetrySpan(telemetrySpan.span, error);
|
|
3219
|
+
}
|
|
3220
|
+
throw error;
|
|
2944
3221
|
}
|
|
2945
|
-
return normalizeCreateIVISessionResponse(responseBody, request, requestBody);
|
|
2946
3222
|
}
|
|
2947
3223
|
function createRuntimeFromSession(session, options = {}) {
|
|
2948
|
-
const
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
transport: new websocket.WebSocketTransport({
|
|
2952
|
-
url: websocketUrl,
|
|
2953
|
-
sessionId: session.iviSessionId,
|
|
2954
|
-
protocols: options.websocket?.protocols,
|
|
2955
|
-
socketFactory: options.websocket?.socketFactory
|
|
2956
|
-
})
|
|
3224
|
+
const telemetrySpan = startIviTelemetrySpan("sdk.runtime.create", options.telemetry, {
|
|
3225
|
+
"ivi.session.id": session.iviSessionId,
|
|
3226
|
+
"ivi.prebuild.playback.kind": session.prebuiltPlayback?.kind
|
|
2957
3227
|
});
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3228
|
+
try {
|
|
3229
|
+
const websocketUrl = buildWebSocketUrl(session.endpoint, options.websocket);
|
|
3230
|
+
const childTelemetry = withIviTelemetryContext(options.telemetry, telemetrySpan.context, {
|
|
3231
|
+
"ivi.session.id": session.iviSessionId
|
|
3232
|
+
});
|
|
3233
|
+
const clientTelemetry = mergeIviTelemetryOptions(
|
|
3234
|
+
options.clientConfig?.telemetry,
|
|
3235
|
+
childTelemetry
|
|
3236
|
+
);
|
|
3237
|
+
const runtimeTelemetry = mergeIviTelemetryOptions(
|
|
3238
|
+
options.runtimeConfig?.telemetry,
|
|
3239
|
+
childTelemetry
|
|
3240
|
+
);
|
|
3241
|
+
const client = new iviSdkTs.IviClient({
|
|
3242
|
+
...options.clientConfig ?? {},
|
|
3243
|
+
telemetry: clientTelemetry,
|
|
3244
|
+
transport: new websocket.WebSocketTransport({
|
|
3245
|
+
url: websocketUrl,
|
|
3246
|
+
sessionId: session.iviSessionId,
|
|
3247
|
+
protocols: options.websocket?.protocols,
|
|
3248
|
+
socketFactory: options.websocket?.socketFactory
|
|
3249
|
+
})
|
|
3250
|
+
});
|
|
3251
|
+
const runtime = new IviRuntimeCoordinator(client, {
|
|
3252
|
+
...options.runtimeConfig ?? {},
|
|
3253
|
+
telemetry: runtimeTelemetry
|
|
3254
|
+
});
|
|
3255
|
+
if (options.fastStart !== false && session.prebuiltPlayback) {
|
|
3256
|
+
runtime.setBootstrapSource(toBootstrapSource(session.prebuiltPlayback, options));
|
|
3257
|
+
}
|
|
3258
|
+
endIviTelemetrySpan(telemetrySpan.span);
|
|
3259
|
+
return {
|
|
3260
|
+
session,
|
|
3261
|
+
client,
|
|
3262
|
+
runtime
|
|
3263
|
+
};
|
|
3264
|
+
} catch (error) {
|
|
3265
|
+
failIviTelemetrySpan(telemetrySpan.span, error);
|
|
3266
|
+
throw error;
|
|
2961
3267
|
}
|
|
2962
|
-
return {
|
|
2963
|
-
session,
|
|
2964
|
-
client,
|
|
2965
|
-
runtime
|
|
2966
|
-
};
|
|
2967
3268
|
}
|
|
2968
3269
|
async function createIVISessionRuntime(request, options) {
|
|
2969
|
-
const
|
|
2970
|
-
|
|
3270
|
+
const telemetry = mergeIviTelemetryOptions(options.telemetry, options.http.telemetry);
|
|
3271
|
+
const session = await createIVISession(request, {
|
|
3272
|
+
...options.http,
|
|
3273
|
+
telemetry
|
|
3274
|
+
});
|
|
3275
|
+
return createRuntimeFromSession(session, {
|
|
3276
|
+
...options,
|
|
3277
|
+
telemetry
|
|
3278
|
+
});
|
|
2971
3279
|
}
|
|
2972
3280
|
function toCpCreateIVISessionRequestBody(request) {
|
|
2973
3281
|
const body = { ...request };
|
|
@@ -3053,6 +3361,25 @@ function resolveCreateIVISessionUrl(options) {
|
|
|
3053
3361
|
const path = options.path ?? "/v1/ivi/sessions";
|
|
3054
3362
|
return new URL(path, ensureTrailingSlash(options.baseUrl)).toString();
|
|
3055
3363
|
}
|
|
3364
|
+
function buildCreateSessionTelemetryAttributes(request) {
|
|
3365
|
+
return {
|
|
3366
|
+
"ivi.version": request.iviVersion,
|
|
3367
|
+
"ivi.stream.type": request.streamType,
|
|
3368
|
+
"ivi.prebuild.enabled": Boolean(
|
|
3369
|
+
request.prebuiltStream || request.prebuiltCharacters && request.prebuiltCharacters.length > 0
|
|
3370
|
+
)
|
|
3371
|
+
};
|
|
3372
|
+
}
|
|
3373
|
+
function mergeIviTelemetryOptions(explicit, inherited) {
|
|
3374
|
+
if (!explicit && !inherited) {
|
|
3375
|
+
return void 0;
|
|
3376
|
+
}
|
|
3377
|
+
return {
|
|
3378
|
+
tracer: explicit?.tracer ?? inherited?.tracer,
|
|
3379
|
+
context: explicit?.context ?? inherited?.context,
|
|
3380
|
+
attributes: mergeIviTelemetryAttributes(inherited?.attributes, explicit?.attributes)
|
|
3381
|
+
};
|
|
3382
|
+
}
|
|
3056
3383
|
async function buildHeaders(headers) {
|
|
3057
3384
|
const resolvedHeaders = typeof headers === "function" ? await headers() : headers;
|
|
3058
3385
|
const next = new Headers(resolvedHeaders);
|
|
@@ -3061,6 +3388,14 @@ async function buildHeaders(headers) {
|
|
|
3061
3388
|
}
|
|
3062
3389
|
return next;
|
|
3063
3390
|
}
|
|
3391
|
+
var headersTextMapSetter = {
|
|
3392
|
+
set(carrier, key, value) {
|
|
3393
|
+
carrier.set(key, value);
|
|
3394
|
+
}
|
|
3395
|
+
};
|
|
3396
|
+
function injectIviTelemetryHeaders(headers, context) {
|
|
3397
|
+
api.propagation.inject(context, headers, headersTextMapSetter);
|
|
3398
|
+
}
|
|
3064
3399
|
async function readJsonResponse(response) {
|
|
3065
3400
|
const text = await response.text();
|
|
3066
3401
|
if (!text) {
|
|
@@ -3234,32 +3569,71 @@ var IviFrontendSdk = class {
|
|
|
3234
3569
|
this.config = config;
|
|
3235
3570
|
}
|
|
3236
3571
|
createClient(config) {
|
|
3237
|
-
return new iviSdkTs.IviClient(
|
|
3572
|
+
return new iviSdkTs.IviClient({
|
|
3573
|
+
...config,
|
|
3574
|
+
telemetry: mergeSdkTelemetryOptions(config.telemetry, this.config.telemetry)
|
|
3575
|
+
});
|
|
3238
3576
|
}
|
|
3239
3577
|
createRuntimeCoordinator(clientConfig, runtimeConfig) {
|
|
3240
3578
|
const client = this.createClient(clientConfig);
|
|
3241
|
-
return new IviRuntimeCoordinator(client,
|
|
3579
|
+
return new IviRuntimeCoordinator(client, {
|
|
3580
|
+
...runtimeConfig ?? {},
|
|
3581
|
+
telemetry: mergeSdkTelemetryOptions(runtimeConfig?.telemetry, this.config.telemetry)
|
|
3582
|
+
});
|
|
3242
3583
|
}
|
|
3243
3584
|
createIVISession(request, options) {
|
|
3585
|
+
const telemetry = mergeSdkTelemetryChain(
|
|
3586
|
+
this.config.telemetry,
|
|
3587
|
+
this.config.http?.telemetry,
|
|
3588
|
+
options?.telemetry
|
|
3589
|
+
);
|
|
3244
3590
|
return createIVISession(request, {
|
|
3245
3591
|
...this.config.http ?? {},
|
|
3246
|
-
...options ?? {}
|
|
3592
|
+
...options ?? {},
|
|
3593
|
+
telemetry
|
|
3247
3594
|
});
|
|
3248
3595
|
}
|
|
3249
3596
|
createRuntimeFromSession(session, options) {
|
|
3250
|
-
return createRuntimeFromSession(session,
|
|
3597
|
+
return createRuntimeFromSession(session, {
|
|
3598
|
+
...options ?? {},
|
|
3599
|
+
telemetry: mergeSdkTelemetryChain(this.config.telemetry, options?.telemetry)
|
|
3600
|
+
});
|
|
3251
3601
|
}
|
|
3252
3602
|
createIVISessionRuntime(request, options) {
|
|
3603
|
+
const telemetry = mergeSdkTelemetryChain(
|
|
3604
|
+
this.config.telemetry,
|
|
3605
|
+
this.config.http?.telemetry,
|
|
3606
|
+
options?.http?.telemetry,
|
|
3607
|
+
options?.telemetry
|
|
3608
|
+
);
|
|
3253
3609
|
const http = {
|
|
3254
3610
|
...this.config.http ?? {},
|
|
3255
|
-
...options?.http ?? {}
|
|
3611
|
+
...options?.http ?? {},
|
|
3612
|
+
telemetry
|
|
3256
3613
|
};
|
|
3257
3614
|
return createIVISessionRuntime(request, {
|
|
3258
3615
|
...options ?? {},
|
|
3616
|
+
telemetry,
|
|
3259
3617
|
http
|
|
3260
3618
|
});
|
|
3261
3619
|
}
|
|
3262
3620
|
};
|
|
3621
|
+
function mergeSdkTelemetryChain(...items) {
|
|
3622
|
+
return items.reduce(
|
|
3623
|
+
(merged, item) => mergeSdkTelemetryOptions(item, merged),
|
|
3624
|
+
void 0
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
function mergeSdkTelemetryOptions(explicit, inherited) {
|
|
3628
|
+
if (!explicit && !inherited) {
|
|
3629
|
+
return void 0;
|
|
3630
|
+
}
|
|
3631
|
+
return {
|
|
3632
|
+
tracer: explicit?.tracer ?? inherited?.tracer,
|
|
3633
|
+
context: explicit?.context ?? inherited?.context,
|
|
3634
|
+
attributes: mergeIviTelemetryAttributes(inherited?.attributes, explicit?.attributes)
|
|
3635
|
+
};
|
|
3636
|
+
}
|
|
3263
3637
|
var IviStageViewContext = react.createContext(null);
|
|
3264
3638
|
var EMPTY_RUNTIME_STATE = {
|
|
3265
3639
|
status: "idle",
|
|
@@ -4460,7 +4834,16 @@ function makeLoadPolicy(label, onLog) {
|
|
|
4460
4834
|
};
|
|
4461
4835
|
}
|
|
4462
4836
|
function IVIHlsVideo(props) {
|
|
4463
|
-
const {
|
|
4837
|
+
const {
|
|
4838
|
+
url,
|
|
4839
|
+
sourceId,
|
|
4840
|
+
videoProps,
|
|
4841
|
+
style,
|
|
4842
|
+
aggressivePreload = false,
|
|
4843
|
+
paused = false,
|
|
4844
|
+
onLog,
|
|
4845
|
+
telemetry
|
|
4846
|
+
} = props;
|
|
4464
4847
|
const videoRef = react.useRef(null);
|
|
4465
4848
|
const pausedRef = react.useRef(paused);
|
|
4466
4849
|
react.useEffect(() => {
|
|
@@ -4497,6 +4880,7 @@ function IVIHlsVideo(props) {
|
|
|
4497
4880
|
const onVideoError = () => {
|
|
4498
4881
|
const el = videoRef.current;
|
|
4499
4882
|
const mediaErr = el?.error;
|
|
4883
|
+
recordVideoTelemetry("sdk.media.video.error", telemetry, sourceId, "hls", mediaErr);
|
|
4500
4884
|
emitHlsLog(onLog, "warn", "<video> \u5143\u7D20\u62A5\u9519", {
|
|
4501
4885
|
code: mediaErr?.code,
|
|
4502
4886
|
message: mediaErr?.message,
|
|
@@ -4506,6 +4890,13 @@ function IVIHlsVideo(props) {
|
|
|
4506
4890
|
});
|
|
4507
4891
|
};
|
|
4508
4892
|
const onVideoStalled = () => {
|
|
4893
|
+
recordVideoTelemetry(
|
|
4894
|
+
"sdk.media.video.stalled",
|
|
4895
|
+
telemetry,
|
|
4896
|
+
sourceId,
|
|
4897
|
+
"hls",
|
|
4898
|
+
new Error("<video> stalled")
|
|
4899
|
+
);
|
|
4509
4900
|
emitHlsLog(onLog, "warn", "<video> stalled\uFF08\u7F13\u51B2\u505C\u6EDE\uFF09", {
|
|
4510
4901
|
currentTime: videoRef.current?.currentTime,
|
|
4511
4902
|
readyState: videoRef.current?.readyState
|
|
@@ -4648,7 +5039,7 @@ function IVIHlsVideo(props) {
|
|
|
4648
5039
|
hlsInstance?.destroy();
|
|
4649
5040
|
hlsInstance = null;
|
|
4650
5041
|
};
|
|
4651
|
-
}, [url, aggressivePreload, onLog]);
|
|
5042
|
+
}, [url, sourceId, aggressivePreload, onLog, telemetry]);
|
|
4652
5043
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4653
5044
|
"video",
|
|
4654
5045
|
{
|
|
@@ -4661,6 +5052,17 @@ function IVIHlsVideo(props) {
|
|
|
4661
5052
|
}
|
|
4662
5053
|
);
|
|
4663
5054
|
}
|
|
5055
|
+
function recordVideoTelemetry(name, telemetry, sourceId, kind, error) {
|
|
5056
|
+
recordIviTelemetrySpan(
|
|
5057
|
+
name,
|
|
5058
|
+
telemetry,
|
|
5059
|
+
{
|
|
5060
|
+
"ivi.source.id": sourceId,
|
|
5061
|
+
"ivi.media.kind": kind
|
|
5062
|
+
},
|
|
5063
|
+
error
|
|
5064
|
+
);
|
|
5065
|
+
}
|
|
4664
5066
|
function isM3u8Url(url) {
|
|
4665
5067
|
return /\.m3u8(?:$|[?#])/i.test(url);
|
|
4666
5068
|
}
|
|
@@ -4726,6 +5128,7 @@ function TrackSlotMediaContent(props) {
|
|
|
4726
5128
|
source,
|
|
4727
5129
|
isPreloading: !isActive
|
|
4728
5130
|
};
|
|
5131
|
+
const telemetry = runtime?.getTelemetryOptions();
|
|
4729
5132
|
const mediaStyle = buildAdaptiveMediaStyle(adaptToSourceSize, fitStrategy);
|
|
4730
5133
|
const shouldMute = !isActive;
|
|
4731
5134
|
if (renderMedia) return renderMedia(renderContext);
|
|
@@ -4797,9 +5200,11 @@ function TrackSlotMediaContent(props) {
|
|
|
4797
5200
|
IVIHlsVideo,
|
|
4798
5201
|
{
|
|
4799
5202
|
url: playbackUrl,
|
|
5203
|
+
sourceId: slotSourceId,
|
|
4800
5204
|
videoProps: mergedVideoProps,
|
|
4801
5205
|
style: videoStyle,
|
|
4802
|
-
paused: shouldPause
|
|
5206
|
+
paused: shouldPause,
|
|
5207
|
+
telemetry
|
|
4803
5208
|
}
|
|
4804
5209
|
);
|
|
4805
5210
|
}
|
|
@@ -4821,6 +5226,7 @@ function TrackSlotMediaContent(props) {
|
|
|
4821
5226
|
SlotVideo,
|
|
4822
5227
|
{
|
|
4823
5228
|
src: playbackUrl,
|
|
5229
|
+
sourceId: slotSourceId,
|
|
4824
5230
|
paused: shouldPause,
|
|
4825
5231
|
videoProps: {
|
|
4826
5232
|
...mergedVideoProps,
|
|
@@ -4828,7 +5234,8 @@ function TrackSlotMediaContent(props) {
|
|
|
4828
5234
|
playsInline: videoProps?.playsInline ?? true,
|
|
4829
5235
|
controls: isActive ? videoProps?.controls ?? true : false
|
|
4830
5236
|
},
|
|
4831
|
-
style: videoStyle
|
|
5237
|
+
style: videoStyle,
|
|
5238
|
+
telemetry
|
|
4832
5239
|
}
|
|
4833
5240
|
);
|
|
4834
5241
|
}
|
|
@@ -4878,17 +5285,48 @@ function SlotVideo(props) {
|
|
|
4878
5285
|
video.play().catch(() => void 0);
|
|
4879
5286
|
}
|
|
4880
5287
|
}, [props.paused]);
|
|
5288
|
+
const onError = (event) => {
|
|
5289
|
+
recordPlainVideoTelemetry(
|
|
5290
|
+
"sdk.media.video.error",
|
|
5291
|
+
props.telemetry,
|
|
5292
|
+
props.sourceId,
|
|
5293
|
+
event.currentTarget.error
|
|
5294
|
+
);
|
|
5295
|
+
props.videoProps.onError?.(event);
|
|
5296
|
+
};
|
|
5297
|
+
const onStalled = (event) => {
|
|
5298
|
+
recordPlainVideoTelemetry(
|
|
5299
|
+
"sdk.media.video.stalled",
|
|
5300
|
+
props.telemetry,
|
|
5301
|
+
props.sourceId,
|
|
5302
|
+
new Error("<video> stalled")
|
|
5303
|
+
);
|
|
5304
|
+
props.videoProps.onStalled?.(event);
|
|
5305
|
+
};
|
|
4881
5306
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4882
5307
|
"video",
|
|
4883
5308
|
{
|
|
4884
5309
|
ref: videoRef,
|
|
4885
5310
|
src: props.src,
|
|
4886
5311
|
...props.videoProps,
|
|
5312
|
+
onError,
|
|
5313
|
+
onStalled,
|
|
4887
5314
|
autoPlay: props.paused ? false : props.videoProps.autoPlay ?? true,
|
|
4888
5315
|
style: props.style
|
|
4889
5316
|
}
|
|
4890
5317
|
);
|
|
4891
5318
|
}
|
|
5319
|
+
function recordPlainVideoTelemetry(name, telemetry, sourceId, error) {
|
|
5320
|
+
recordIviTelemetrySpan(
|
|
5321
|
+
name,
|
|
5322
|
+
telemetry,
|
|
5323
|
+
{
|
|
5324
|
+
"ivi.source.id": sourceId,
|
|
5325
|
+
"ivi.media.kind": "video"
|
|
5326
|
+
},
|
|
5327
|
+
error
|
|
5328
|
+
);
|
|
5329
|
+
}
|
|
4892
5330
|
|
|
4893
5331
|
// src/react/internal/use-multi-preload-sources.ts
|
|
4894
5332
|
function useMultiPreloadSources(sources, activeSourceId) {
|