@camstack/ui-library 1.2.181 → 1.2.182
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/composites/camera-stream-player.d.ts +15 -2
- package/dist/composites/index.d.ts +4 -0
- package/dist/composites/stream-debug/stream-debug-overlay.d.ts +34 -0
- package/dist/composites/stream-debug/webrtc-debug-stats.d.ts +129 -0
- package/dist/generated/system-hooks.d.ts +2 -0
- package/dist/hooks/use-device-webrtc.d.ts +15 -1
- package/dist/index.cjs +649 -36
- package/dist/index.js +646 -37
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7213,6 +7213,8 @@ var useWebrtcSessionCloseSession = trpc.webrtcSession.closeSession.useMutation;
|
|
|
7213
7213
|
var useWebrtcSessionHasAdaptiveBitrate = trpc.webrtcSession.hasAdaptiveBitrate.useQuery;
|
|
7214
7214
|
/** Generated alias around `trpc.webrtcSession.getSessionState.useQuery`. */
|
|
7215
7215
|
var useWebrtcSessionGetSessionState = trpc.webrtcSession.getSessionState.useQuery;
|
|
7216
|
+
/** Generated alias around `trpc.webrtcSession.getSessionDebug.useQuery`. */
|
|
7217
|
+
var useWebrtcSessionGetSessionDebug = trpc.webrtcSession.getSessionDebug.useQuery;
|
|
7216
7218
|
/** Generated alias around `trpc.zoneAnalytics.getCurrentSnapshot.useQuery`. */
|
|
7217
7219
|
var useZoneAnalyticsGetCurrentSnapshot = trpc.zoneAnalytics.getCurrentSnapshot.useQuery;
|
|
7218
7220
|
/** Generated alias around `trpc.zoneAnalytics.getCurrentSnapshotBatch.useQuery`. */
|
|
@@ -26976,6 +26978,580 @@ async function measureDownlinkMbps(origin, deps) {
|
|
|
26976
26978
|
}
|
|
26977
26979
|
}
|
|
26978
26980
|
//#endregion
|
|
26981
|
+
//#region src/composites/stream-debug/webrtc-debug-stats.ts
|
|
26982
|
+
/** Beyond this the log is a scroll, not a signal. */
|
|
26983
|
+
var RESOLUTION_LOG_MAX = 8;
|
|
26984
|
+
function num(value) {
|
|
26985
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
26986
|
+
}
|
|
26987
|
+
function str(value) {
|
|
26988
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
26989
|
+
}
|
|
26990
|
+
/** Δ of two cumulative counters. Null unless BOTH ends were measured; a
|
|
26991
|
+
* counter that went backwards (a reset) yields null rather than a negative. */
|
|
26992
|
+
function delta(now, before) {
|
|
26993
|
+
if (now === null || before === null) return null;
|
|
26994
|
+
const d = now - before;
|
|
26995
|
+
return d < 0 ? null : d;
|
|
26996
|
+
}
|
|
26997
|
+
function lossPercentOf(lost, received) {
|
|
26998
|
+
if (lost === null || received === null) return null;
|
|
26999
|
+
const total = lost + received;
|
|
27000
|
+
if (total <= 0) return null;
|
|
27001
|
+
return lost / total * 100;
|
|
27002
|
+
}
|
|
27003
|
+
function profileLevelIdOf(fmtp) {
|
|
27004
|
+
if (fmtp === null) return null;
|
|
27005
|
+
return /profile-level-id=([0-9a-fA-F]+)/.exec(fmtp)?.[1] ?? null;
|
|
27006
|
+
}
|
|
27007
|
+
function collect(report) {
|
|
27008
|
+
const out = {
|
|
27009
|
+
inbound: null,
|
|
27010
|
+
codecs: /* @__PURE__ */ new Map(),
|
|
27011
|
+
candidates: /* @__PURE__ */ new Map(),
|
|
27012
|
+
pair: null,
|
|
27013
|
+
selectedPairId: null
|
|
27014
|
+
};
|
|
27015
|
+
const pairs = [];
|
|
27016
|
+
report.forEach((raw) => {
|
|
27017
|
+
const s = raw;
|
|
27018
|
+
const id = str(s.id);
|
|
27019
|
+
switch (s.type) {
|
|
27020
|
+
case "inbound-rtp":
|
|
27021
|
+
if ((s.kind ?? s.mediaType) === "video") out.inbound = s;
|
|
27022
|
+
break;
|
|
27023
|
+
case "codec":
|
|
27024
|
+
if (id !== null) out.codecs.set(id, s);
|
|
27025
|
+
break;
|
|
27026
|
+
case "local-candidate":
|
|
27027
|
+
case "remote-candidate":
|
|
27028
|
+
if (id !== null) out.candidates.set(id, s);
|
|
27029
|
+
break;
|
|
27030
|
+
case "candidate-pair":
|
|
27031
|
+
pairs.push(s);
|
|
27032
|
+
break;
|
|
27033
|
+
case "transport":
|
|
27034
|
+
out.selectedPairId = str(s.selectedCandidatePairId);
|
|
27035
|
+
break;
|
|
27036
|
+
default: break;
|
|
27037
|
+
}
|
|
27038
|
+
});
|
|
27039
|
+
const byId = out.selectedPairId;
|
|
27040
|
+
out.pair = pairs.find((p) => str(p.id) === byId) ?? pairs.find((p) => p.selected === true) ?? pairs.find((p) => p.nominated === true && p.state === "succeeded") ?? pairs.find((p) => p.nominated === true) ?? pairs.find((p) => p.state === "succeeded") ?? null;
|
|
27041
|
+
return out;
|
|
27042
|
+
}
|
|
27043
|
+
function readCounters(inbound) {
|
|
27044
|
+
if (inbound === null) return {
|
|
27045
|
+
timestamp: null,
|
|
27046
|
+
bytesReceived: null,
|
|
27047
|
+
packetsReceived: null,
|
|
27048
|
+
packetsLost: null,
|
|
27049
|
+
framesDecoded: null,
|
|
27050
|
+
framesDropped: null,
|
|
27051
|
+
freezeCount: null,
|
|
27052
|
+
totalFreezesDurationS: null,
|
|
27053
|
+
totalDecodeTimeS: null,
|
|
27054
|
+
nackCount: null,
|
|
27055
|
+
pliCount: null
|
|
27056
|
+
};
|
|
27057
|
+
return {
|
|
27058
|
+
timestamp: num(inbound.timestamp),
|
|
27059
|
+
bytesReceived: num(inbound.bytesReceived),
|
|
27060
|
+
packetsReceived: num(inbound.packetsReceived),
|
|
27061
|
+
packetsLost: num(inbound.packetsLost),
|
|
27062
|
+
framesDecoded: num(inbound.framesDecoded),
|
|
27063
|
+
framesDropped: num(inbound.framesDropped),
|
|
27064
|
+
freezeCount: num(inbound.freezeCount),
|
|
27065
|
+
totalFreezesDurationS: num(inbound.totalFreezesDuration),
|
|
27066
|
+
totalDecodeTimeS: num(inbound.totalDecodeTime),
|
|
27067
|
+
nackCount: num(inbound.nackCount),
|
|
27068
|
+
pliCount: num(inbound.pliCount)
|
|
27069
|
+
};
|
|
27070
|
+
}
|
|
27071
|
+
var EMPTY_WINDOW = {
|
|
27072
|
+
spanMs: null,
|
|
27073
|
+
kbps: null,
|
|
27074
|
+
packetsReceived: null,
|
|
27075
|
+
packetsLost: null,
|
|
27076
|
+
lossPercent: null,
|
|
27077
|
+
framesDecoded: null,
|
|
27078
|
+
framesDropped: null,
|
|
27079
|
+
freezeCount: null,
|
|
27080
|
+
freezeMs: null,
|
|
27081
|
+
nackCount: null,
|
|
27082
|
+
pliCount: null,
|
|
27083
|
+
decodeMs: null
|
|
27084
|
+
};
|
|
27085
|
+
function windowOf(now, before) {
|
|
27086
|
+
if (before === null) return EMPTY_WINDOW;
|
|
27087
|
+
const spanMs = delta(now.timestamp, before.timestamp);
|
|
27088
|
+
if (spanMs === null || spanMs <= 0) return EMPTY_WINDOW;
|
|
27089
|
+
const bytes = delta(now.bytesReceived, before.bytesReceived);
|
|
27090
|
+
const lost = delta(now.packetsLost, before.packetsLost);
|
|
27091
|
+
const received = delta(now.packetsReceived, before.packetsReceived);
|
|
27092
|
+
const decoded = delta(now.framesDecoded, before.framesDecoded);
|
|
27093
|
+
const decodeS = delta(now.totalDecodeTimeS, before.totalDecodeTimeS);
|
|
27094
|
+
const freezeS = delta(now.totalFreezesDurationS, before.totalFreezesDurationS);
|
|
27095
|
+
return {
|
|
27096
|
+
spanMs,
|
|
27097
|
+
kbps: bytes === null ? null : Math.round(bytes * 8 / spanMs),
|
|
27098
|
+
packetsReceived: received,
|
|
27099
|
+
packetsLost: lost,
|
|
27100
|
+
lossPercent: lossPercentOf(lost, received),
|
|
27101
|
+
framesDecoded: decoded,
|
|
27102
|
+
framesDropped: delta(now.framesDropped, before.framesDropped),
|
|
27103
|
+
freezeCount: delta(now.freezeCount, before.freezeCount),
|
|
27104
|
+
freezeMs: freezeS === null ? null : Math.round(freezeS * 1e3),
|
|
27105
|
+
nackCount: delta(now.nackCount, before.nackCount),
|
|
27106
|
+
pliCount: delta(now.pliCount, before.pliCount),
|
|
27107
|
+
decodeMs: decodeS === null || decoded === null || decoded <= 0 ? null : decodeS / decoded * 1e3
|
|
27108
|
+
};
|
|
27109
|
+
}
|
|
27110
|
+
function resolutionLogOf(prev, width, height, at) {
|
|
27111
|
+
if (width === null || height === null) return prev;
|
|
27112
|
+
const last = prev.at(-1);
|
|
27113
|
+
if (last !== void 0 && last.width === width && last.height === height) return prev;
|
|
27114
|
+
const next = [...prev, {
|
|
27115
|
+
width,
|
|
27116
|
+
height,
|
|
27117
|
+
at
|
|
27118
|
+
}];
|
|
27119
|
+
return next.length > RESOLUTION_LOG_MAX ? next.slice(next.length - RESOLUTION_LOG_MAX) : next;
|
|
27120
|
+
}
|
|
27121
|
+
/**
|
|
27122
|
+
* Derive one debug sample. Immutable: `prev` is read, never mutated, and the
|
|
27123
|
+
* returned object is the input for the next call.
|
|
27124
|
+
*/
|
|
27125
|
+
function deriveWebrtcDebugStats(input) {
|
|
27126
|
+
const { inbound, codecs, candidates, pair } = collect(input.report);
|
|
27127
|
+
const raw = readCounters(inbound);
|
|
27128
|
+
const codecStat = inbound !== null ? codecs.get(str(inbound.codecId) ?? "") : void 0;
|
|
27129
|
+
const mime = str(codecStat?.mimeType);
|
|
27130
|
+
const fmtp = str(codecStat?.sdpFmtpLine);
|
|
27131
|
+
const localCand = pair !== null ? candidates.get(str(pair.localCandidateId) ?? "") : void 0;
|
|
27132
|
+
const remoteCand = pair !== null ? candidates.get(str(pair.remoteCandidateId) ?? "") : void 0;
|
|
27133
|
+
const localType = str(localCand?.candidateType);
|
|
27134
|
+
const remoteType = str(remoteCand?.candidateType);
|
|
27135
|
+
const width = num(inbound?.frameWidth);
|
|
27136
|
+
const height = num(inbound?.frameHeight);
|
|
27137
|
+
const totalFreezeS = raw.totalFreezesDurationS;
|
|
27138
|
+
const decodeS = raw.totalDecodeTimeS;
|
|
27139
|
+
const decodedTotal = raw.framesDecoded;
|
|
27140
|
+
return {
|
|
27141
|
+
at: input.now,
|
|
27142
|
+
hasInboundVideo: inbound !== null,
|
|
27143
|
+
width,
|
|
27144
|
+
height,
|
|
27145
|
+
fps: num(inbound?.framesPerSecond),
|
|
27146
|
+
codec: mime === null ? null : mime.split("/")[1] ?? mime,
|
|
27147
|
+
codecProfileLevelId: profileLevelIdOf(fmtp),
|
|
27148
|
+
jitterMs: jitterMsOf(inbound),
|
|
27149
|
+
packetsReceived: raw.packetsReceived,
|
|
27150
|
+
packetsLost: raw.packetsLost,
|
|
27151
|
+
lossPercent: lossPercentOf(raw.packetsLost, raw.packetsReceived),
|
|
27152
|
+
nackCount: raw.nackCount,
|
|
27153
|
+
pliCount: raw.pliCount,
|
|
27154
|
+
framesDecoded: decodedTotal,
|
|
27155
|
+
framesDropped: raw.framesDropped,
|
|
27156
|
+
freezeCount: raw.freezeCount,
|
|
27157
|
+
totalFreezeMs: totalFreezeS === null ? null : Math.round(totalFreezeS * 1e3),
|
|
27158
|
+
avgDecodeMs: decodeS === null || decodedTotal === null || decodedTotal <= 0 ? null : decodeS / decodedTotal * 1e3,
|
|
27159
|
+
rttMs: rttMsOf(pair),
|
|
27160
|
+
availableIncomingKbps: availableKbpsOf(pair),
|
|
27161
|
+
localCandidateType: localType,
|
|
27162
|
+
remoteCandidateType: remoteType,
|
|
27163
|
+
candidatePairType: localType === null && remoteType === null ? null : `${localType ?? "?"}/${remoteType ?? "?"}`,
|
|
27164
|
+
candidateProtocol: str(localCand?.protocol),
|
|
27165
|
+
iceConnectionState: input.iceConnectionState,
|
|
27166
|
+
dtlsState: input.dtlsState,
|
|
27167
|
+
window: windowOf(raw, input.prev?.raw ?? null),
|
|
27168
|
+
resolutionLog: resolutionLogOf(input.prev?.resolutionLog ?? [], width, height, input.now),
|
|
27169
|
+
raw
|
|
27170
|
+
};
|
|
27171
|
+
}
|
|
27172
|
+
function jitterMsOf(inbound) {
|
|
27173
|
+
const jitter = num(inbound?.jitter);
|
|
27174
|
+
return jitter === null ? null : jitter * 1e3;
|
|
27175
|
+
}
|
|
27176
|
+
function rttMsOf(pair) {
|
|
27177
|
+
const rtt = num(pair?.currentRoundTripTime);
|
|
27178
|
+
return rtt === null ? null : rtt * 1e3;
|
|
27179
|
+
}
|
|
27180
|
+
function availableKbpsOf(pair) {
|
|
27181
|
+
const bps = num(pair?.availableIncomingBitrate);
|
|
27182
|
+
return bps === null ? null : Math.round(bps / 1e3);
|
|
27183
|
+
}
|
|
27184
|
+
var VERDICTS = {
|
|
27185
|
+
unknown: "no window yet",
|
|
27186
|
+
decoding: "decoding",
|
|
27187
|
+
"decoder-stall": "DECODER STALL — bytes arriving, no frames out",
|
|
27188
|
+
"transport-stall": "TRANSPORT STALL — nothing arriving",
|
|
27189
|
+
"frozen-unknown": "frames stopped — byte rate unknown"
|
|
27190
|
+
};
|
|
27191
|
+
function freezeVerdict(stats) {
|
|
27192
|
+
const kind = freezeVerdictKind(stats);
|
|
27193
|
+
return {
|
|
27194
|
+
kind,
|
|
27195
|
+
label: VERDICTS[kind]
|
|
27196
|
+
};
|
|
27197
|
+
}
|
|
27198
|
+
function freezeVerdictKind(stats) {
|
|
27199
|
+
if (stats === null || !stats.hasInboundVideo) return "unknown";
|
|
27200
|
+
const decoded = stats.window.framesDecoded;
|
|
27201
|
+
if (decoded === null) return "unknown";
|
|
27202
|
+
if (decoded > 0) return "decoding";
|
|
27203
|
+
const kbps = stats.window.kbps;
|
|
27204
|
+
if (kbps === null) return "frozen-unknown";
|
|
27205
|
+
return kbps > 0 ? "decoder-stall" : "transport-stall";
|
|
27206
|
+
}
|
|
27207
|
+
//#endregion
|
|
27208
|
+
//#region src/composites/stream-debug/stream-debug-overlay.tsx
|
|
27209
|
+
/** `—` is the ONLY rendering of unknown. Never an empty cell, never 0. */
|
|
27210
|
+
var UNKNOWN = "—";
|
|
27211
|
+
function n(value, opts) {
|
|
27212
|
+
if (value === null || value === void 0 || !Number.isFinite(value)) return UNKNOWN;
|
|
27213
|
+
const digits = opts?.digits ?? 0;
|
|
27214
|
+
return `${value.toFixed(digits)}${opts?.suffix ?? ""}`;
|
|
27215
|
+
}
|
|
27216
|
+
function s(value) {
|
|
27217
|
+
return value === null || value === void 0 || value === "" ? UNKNOWN : value;
|
|
27218
|
+
}
|
|
27219
|
+
function b(value) {
|
|
27220
|
+
return value === null || value === void 0 ? UNKNOWN : value ? "yes" : "no";
|
|
27221
|
+
}
|
|
27222
|
+
/** Age of a measurement, in the form an operator reads at a glance. */
|
|
27223
|
+
function age(at, now) {
|
|
27224
|
+
if (at === null) return UNKNOWN;
|
|
27225
|
+
const ms = Math.max(0, now - at);
|
|
27226
|
+
if (ms < 1e3) return `${ms}ms ago`;
|
|
27227
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s ago`;
|
|
27228
|
+
return `${Math.floor(ms / 6e4)}m${Math.floor(ms % 6e4 / 1e3)}s ago`;
|
|
27229
|
+
}
|
|
27230
|
+
/** A measurement older than this is NOT live, and is said to be. */
|
|
27231
|
+
var STALE_AFTER_MS = 3e3;
|
|
27232
|
+
var VERDICT_CLASS = {
|
|
27233
|
+
unknown: "bg-white/15 text-white/70",
|
|
27234
|
+
decoding: "bg-emerald-500/25 text-emerald-200",
|
|
27235
|
+
"decoder-stall": "bg-amber-500/30 text-amber-100",
|
|
27236
|
+
"transport-stall": "bg-rose-500/30 text-rose-100",
|
|
27237
|
+
"frozen-unknown": "bg-white/15 text-white/70"
|
|
27238
|
+
};
|
|
27239
|
+
function Row({ label, value, strong = false }) {
|
|
27240
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
27241
|
+
className: "flex items-baseline justify-between gap-3 leading-tight",
|
|
27242
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
27243
|
+
className: "text-white/55 shrink-0",
|
|
27244
|
+
children: label
|
|
27245
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
27246
|
+
className: strong ? "text-white font-semibold tabular-nums" : "text-white/90 tabular-nums",
|
|
27247
|
+
children: value
|
|
27248
|
+
})]
|
|
27249
|
+
});
|
|
27250
|
+
}
|
|
27251
|
+
function SectionHeader({ title, measuredAt, now }) {
|
|
27252
|
+
const stale = measuredAt !== null && now - measuredAt > STALE_AFTER_MS;
|
|
27253
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
27254
|
+
className: "flex items-baseline justify-between gap-3 mt-2 first:mt-0 pb-0.5 border-b border-white/20",
|
|
27255
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
27256
|
+
className: "text-white/80 font-semibold tracking-wide uppercase text-[9px]",
|
|
27257
|
+
children: title
|
|
27258
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
27259
|
+
className: stale ? "text-amber-300 text-[9px]" : "text-white/45 text-[9px]",
|
|
27260
|
+
children: [stale ? "STALE · " : "", age(measuredAt, now)]
|
|
27261
|
+
})]
|
|
27262
|
+
});
|
|
27263
|
+
}
|
|
27264
|
+
function StreamDebugOverlay(props) {
|
|
27265
|
+
const { stats, server, serverError, serverWired, now, sessionId } = props;
|
|
27266
|
+
const verdict = freezeVerdict(stats);
|
|
27267
|
+
const win = stats?.window;
|
|
27268
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
27269
|
+
className: "absolute top-2 right-2 z-20 transform-gpu w-[15.5rem] max-h-[calc(100%-1rem)] overflow-y-auto rounded-md bg-neutral-950/95 ring-1 ring-white/25 shadow-lg px-2 py-1.5 text-[10px] font-mono text-white/90 select-text",
|
|
27270
|
+
"data-testid": "stream-debug-overlay",
|
|
27271
|
+
children: [
|
|
27272
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27273
|
+
className: `rounded px-1.5 py-1 mb-1 text-[10px] font-semibold ${VERDICT_CLASS[verdict.kind]}`,
|
|
27274
|
+
children: verdict.label
|
|
27275
|
+
}),
|
|
27276
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeader, {
|
|
27277
|
+
title: "decode",
|
|
27278
|
+
measuredAt: stats?.at ?? null,
|
|
27279
|
+
now
|
|
27280
|
+
}),
|
|
27281
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27282
|
+
label: "framesDecoded",
|
|
27283
|
+
value: n(stats?.framesDecoded),
|
|
27284
|
+
strong: true
|
|
27285
|
+
}),
|
|
27286
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27287
|
+
label: "· this window",
|
|
27288
|
+
value: n(win?.framesDecoded),
|
|
27289
|
+
strong: true
|
|
27290
|
+
}),
|
|
27291
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27292
|
+
label: "freezeCount",
|
|
27293
|
+
value: n(stats?.freezeCount),
|
|
27294
|
+
strong: true
|
|
27295
|
+
}),
|
|
27296
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27297
|
+
label: "· total frozen",
|
|
27298
|
+
value: n(stats?.totalFreezeMs, { suffix: "ms" }),
|
|
27299
|
+
strong: true
|
|
27300
|
+
}),
|
|
27301
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27302
|
+
label: "· this window",
|
|
27303
|
+
value: n(win?.freezeMs, { suffix: "ms" })
|
|
27304
|
+
}),
|
|
27305
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27306
|
+
label: "pliCount",
|
|
27307
|
+
value: n(stats?.pliCount),
|
|
27308
|
+
strong: true
|
|
27309
|
+
}),
|
|
27310
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27311
|
+
label: "· this window",
|
|
27312
|
+
value: n(win?.pliCount)
|
|
27313
|
+
}),
|
|
27314
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27315
|
+
label: "framesDropped",
|
|
27316
|
+
value: n(stats?.framesDropped)
|
|
27317
|
+
}),
|
|
27318
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27319
|
+
label: "decode time",
|
|
27320
|
+
value: n(stats?.avgDecodeMs, {
|
|
27321
|
+
digits: 1,
|
|
27322
|
+
suffix: "ms"
|
|
27323
|
+
})
|
|
27324
|
+
}),
|
|
27325
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27326
|
+
label: "· this window",
|
|
27327
|
+
value: n(win?.decodeMs, {
|
|
27328
|
+
digits: 1,
|
|
27329
|
+
suffix: "ms"
|
|
27330
|
+
})
|
|
27331
|
+
}),
|
|
27332
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeader, {
|
|
27333
|
+
title: "picture",
|
|
27334
|
+
measuredAt: stats?.at ?? null,
|
|
27335
|
+
now
|
|
27336
|
+
}),
|
|
27337
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27338
|
+
label: "resolution",
|
|
27339
|
+
value: stats?.width !== null && stats?.width !== void 0 && stats.height !== null ? `${stats.width}×${stats.height}` : UNKNOWN
|
|
27340
|
+
}),
|
|
27341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27342
|
+
label: "fps",
|
|
27343
|
+
value: n(stats?.fps)
|
|
27344
|
+
}),
|
|
27345
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27346
|
+
label: "codec",
|
|
27347
|
+
value: stats?.codec === null || stats?.codec === void 0 ? UNKNOWN : `${stats.codec}${stats.codecProfileLevelId !== null ? ` ${stats.codecProfileLevelId}` : ""}`
|
|
27348
|
+
}),
|
|
27349
|
+
(stats?.resolutionLog.length ?? 0) > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27350
|
+
className: "mt-0.5 text-white/60 leading-tight",
|
|
27351
|
+
children: stats?.resolutionLog.map((mark) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
27352
|
+
className: "flex justify-between",
|
|
27353
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
27354
|
+
mark.width,
|
|
27355
|
+
"×",
|
|
27356
|
+
mark.height
|
|
27357
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
27358
|
+
className: "text-white/40",
|
|
27359
|
+
children: age(mark.at, now)
|
|
27360
|
+
})]
|
|
27361
|
+
}, `${mark.at}-${mark.width}x${mark.height}`))
|
|
27362
|
+
}),
|
|
27363
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeader, {
|
|
27364
|
+
title: "transport",
|
|
27365
|
+
measuredAt: stats?.at ?? null,
|
|
27366
|
+
now
|
|
27367
|
+
}),
|
|
27368
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27369
|
+
label: "bitrate",
|
|
27370
|
+
value: n(win?.kbps, { suffix: " kbps" })
|
|
27371
|
+
}),
|
|
27372
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27373
|
+
label: "rtt",
|
|
27374
|
+
value: n(stats?.rttMs, {
|
|
27375
|
+
digits: 0,
|
|
27376
|
+
suffix: "ms"
|
|
27377
|
+
})
|
|
27378
|
+
}),
|
|
27379
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27380
|
+
label: "jitter",
|
|
27381
|
+
value: n(stats?.jitterMs, {
|
|
27382
|
+
digits: 1,
|
|
27383
|
+
suffix: "ms"
|
|
27384
|
+
})
|
|
27385
|
+
}),
|
|
27386
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27387
|
+
label: "packetsLost",
|
|
27388
|
+
value: n(stats?.packetsLost)
|
|
27389
|
+
}),
|
|
27390
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27391
|
+
label: "· this window",
|
|
27392
|
+
value: n(win?.packetsLost)
|
|
27393
|
+
}),
|
|
27394
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27395
|
+
label: "loss",
|
|
27396
|
+
value: n(stats?.lossPercent, {
|
|
27397
|
+
digits: 2,
|
|
27398
|
+
suffix: "%"
|
|
27399
|
+
})
|
|
27400
|
+
}),
|
|
27401
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27402
|
+
label: "· this window",
|
|
27403
|
+
value: n(win?.lossPercent, {
|
|
27404
|
+
digits: 2,
|
|
27405
|
+
suffix: "%"
|
|
27406
|
+
})
|
|
27407
|
+
}),
|
|
27408
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27409
|
+
label: "nackCount",
|
|
27410
|
+
value: n(stats?.nackCount)
|
|
27411
|
+
}),
|
|
27412
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27413
|
+
label: "· this window",
|
|
27414
|
+
value: n(win?.nackCount)
|
|
27415
|
+
}),
|
|
27416
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27417
|
+
label: "candidate pair",
|
|
27418
|
+
value: s(stats?.candidatePairType)
|
|
27419
|
+
}),
|
|
27420
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27421
|
+
label: "protocol",
|
|
27422
|
+
value: s(stats?.candidateProtocol)
|
|
27423
|
+
}),
|
|
27424
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27425
|
+
label: "ice",
|
|
27426
|
+
value: s(stats?.iceConnectionState)
|
|
27427
|
+
}),
|
|
27428
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27429
|
+
label: "dtls",
|
|
27430
|
+
value: s(stats?.dtlsState)
|
|
27431
|
+
}),
|
|
27432
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionHeader, {
|
|
27433
|
+
title: "server",
|
|
27434
|
+
measuredAt: server?.observedAt ?? null,
|
|
27435
|
+
now
|
|
27436
|
+
}),
|
|
27437
|
+
!serverWired ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27438
|
+
className: "text-white/50 leading-tight py-0.5",
|
|
27439
|
+
children: "not wired on this host"
|
|
27440
|
+
}) : serverError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27441
|
+
className: "text-rose-300 leading-tight py-0.5 break-words",
|
|
27442
|
+
children: serverError
|
|
27443
|
+
}) : server === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27444
|
+
className: "text-white/50 leading-tight py-0.5",
|
|
27445
|
+
children: "waiting for the first answer…"
|
|
27446
|
+
}) : !server.alive ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27447
|
+
className: "text-amber-300 leading-tight py-0.5",
|
|
27448
|
+
children: "session not found on the server — it ended, or this node never had it"
|
|
27449
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
27450
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27451
|
+
label: "served rung",
|
|
27452
|
+
value: s(server.servedTier),
|
|
27453
|
+
strong: true
|
|
27454
|
+
}),
|
|
27455
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27456
|
+
label: "adaptive",
|
|
27457
|
+
value: b(server.adaptive)
|
|
27458
|
+
}),
|
|
27459
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27460
|
+
label: "source",
|
|
27461
|
+
value: s(server.camStreamId)
|
|
27462
|
+
}),
|
|
27463
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27464
|
+
label: "source kind",
|
|
27465
|
+
value: server.sourceKind
|
|
27466
|
+
}),
|
|
27467
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27468
|
+
label: "ingest node",
|
|
27469
|
+
value: s(server.ingestNodeId)
|
|
27470
|
+
}),
|
|
27471
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27472
|
+
label: "· remote",
|
|
27473
|
+
value: b(server.ingestIsRemote)
|
|
27474
|
+
}),
|
|
27475
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27476
|
+
label: "egress leg",
|
|
27477
|
+
value: server.egressLeg,
|
|
27478
|
+
strong: true
|
|
27479
|
+
}),
|
|
27480
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27481
|
+
label: "codec src→out",
|
|
27482
|
+
value: `${s(server.sourceCodec)}→${s(server.negotiatedCodec)}`
|
|
27483
|
+
}),
|
|
27484
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27485
|
+
label: "broker",
|
|
27486
|
+
value: s(server.brokerStatus)
|
|
27487
|
+
}),
|
|
27488
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27489
|
+
label: "· bitrate",
|
|
27490
|
+
value: n(server.brokerBitrateKbps, { suffix: " kbps" })
|
|
27491
|
+
}),
|
|
27492
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27493
|
+
label: "· input fps",
|
|
27494
|
+
value: n(server.brokerInputFps)
|
|
27495
|
+
}),
|
|
27496
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27497
|
+
label: "rtp sent",
|
|
27498
|
+
value: n(server.rtpPacketsSent)
|
|
27499
|
+
}),
|
|
27500
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27501
|
+
label: "track mode",
|
|
27502
|
+
value: s(server.trackMode)
|
|
27503
|
+
}),
|
|
27504
|
+
server.lastDecision === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27505
|
+
label: "ladder",
|
|
27506
|
+
value: "never moved"
|
|
27507
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
27508
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27509
|
+
label: "ladder move",
|
|
27510
|
+
value: `${server.lastDecision.cause}${server.lastDecision.tier !== null ? ` → ${server.lastDecision.tier}` : ""}`,
|
|
27511
|
+
strong: true
|
|
27512
|
+
}),
|
|
27513
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27514
|
+
label: "· when",
|
|
27515
|
+
value: age(server.lastDecision.at, now)
|
|
27516
|
+
}),
|
|
27517
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27518
|
+
label: "· lossRatio",
|
|
27519
|
+
value: n(server.lastDecision.lossRatio, { digits: 4 })
|
|
27520
|
+
}),
|
|
27521
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27522
|
+
label: "· clientKbps",
|
|
27523
|
+
value: n(server.lastDecision.clientKbps, { suffix: " kbps" })
|
|
27524
|
+
}),
|
|
27525
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27526
|
+
label: "· stalledFor",
|
|
27527
|
+
value: n(server.lastDecision.stalledForMs, { suffix: "ms" })
|
|
27528
|
+
}),
|
|
27529
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27530
|
+
label: "· serverSending",
|
|
27531
|
+
value: b(server.lastDecision.serverSending)
|
|
27532
|
+
}),
|
|
27533
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27534
|
+
label: "· transcode-down",
|
|
27535
|
+
value: b(server.lastDecision.forcedTranscodeDown)
|
|
27536
|
+
})
|
|
27537
|
+
] }),
|
|
27538
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27539
|
+
label: "promotions",
|
|
27540
|
+
value: n(server.upgradeCount)
|
|
27541
|
+
}),
|
|
27542
|
+
server.tierFailures.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
|
|
27543
|
+
label: "tier failures",
|
|
27544
|
+
value: server.tierFailures.map((f) => `${f.tier}:${f.failures}`).join(" ")
|
|
27545
|
+
})
|
|
27546
|
+
] }),
|
|
27547
|
+
sessionId !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
27548
|
+
className: "mt-1 pt-0.5 border-t border-white/15 text-white/40 break-all leading-tight",
|
|
27549
|
+
children: sessionId
|
|
27550
|
+
})
|
|
27551
|
+
]
|
|
27552
|
+
});
|
|
27553
|
+
}
|
|
27554
|
+
//#endregion
|
|
26979
27555
|
//#region src/composites/camera-stream-player.tsx
|
|
26980
27556
|
/**
|
|
26981
27557
|
* Silence (or restore) a live WebRTC stream FOR REAL.
|
|
@@ -27074,7 +27650,7 @@ function mergePlayerHints(autoHints, override, downlinkMbps, coldStart) {
|
|
|
27074
27650
|
return coldStart ? stripDownlinkForColdStart(merged) : merged;
|
|
27075
27651
|
}
|
|
27076
27652
|
var FIRST_FRAME_TIMEOUT_MS = 8e3;
|
|
27077
|
-
function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, muted: initialMuted = true, showControls = true, showStats = false, onPlaybackStats, onClientNetworkSample, onConnectTiming, className = "", onStateChange, onError, onReconnectAttempt, overlay, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, reoffer, posterUrl, hintsOverride, onAdaptiveHints, reconnectSignal, onControlChannel, onVideoElement }) {
|
|
27653
|
+
function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, muted: initialMuted = true, showControls = true, showStats = false, onPlaybackStats, onClientNetworkSample, onConnectTiming, className = "", onStateChange, onError, onReconnectAttempt, overlay, createSession, sendAnswer, handleOffer, getIceServers, addIceCandidate, getIceCandidates, closeSession, getSessionState, getSessionDebug, reoffer, posterUrl, hintsOverride, onAdaptiveHints, reconnectSignal, onControlChannel, onVideoElement }) {
|
|
27078
27654
|
const videoRef = (0, react$1.useRef)(null);
|
|
27079
27655
|
const containerRef = (0, react$1.useRef)(null);
|
|
27080
27656
|
const pcRef = (0, react$1.useRef)(null);
|
|
@@ -27971,55 +28547,77 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
27971
28547
|
const webkit = video !== null && typeof video.webkitSetPresentationMode === "function";
|
|
27972
28548
|
setIsPipSupported(standard || webkit);
|
|
27973
28549
|
}, []);
|
|
27974
|
-
const [
|
|
27975
|
-
const
|
|
28550
|
+
const [debugStats, setDebugStats] = (0, react$1.useState)(null);
|
|
28551
|
+
const [serverDebug, setServerDebug] = (0, react$1.useState)(null);
|
|
28552
|
+
const [serverDebugError, setServerDebugError] = (0, react$1.useState)(null);
|
|
28553
|
+
const [debugNow, setDebugNow] = (0, react$1.useState)(() => Date.now());
|
|
28554
|
+
(0, react$1.useEffect)(() => {
|
|
28555
|
+
if (!showStats) return;
|
|
28556
|
+
const id = setInterval(() => setDebugNow(Date.now()), 500);
|
|
28557
|
+
return () => clearInterval(id);
|
|
28558
|
+
}, [showStats]);
|
|
27976
28559
|
(0, react$1.useEffect)(() => {
|
|
27977
28560
|
if (!showStats) {
|
|
27978
|
-
|
|
27979
|
-
statsPrev.current = null;
|
|
28561
|
+
setDebugStats(null);
|
|
27980
28562
|
return;
|
|
27981
28563
|
}
|
|
28564
|
+
const prev = { current: null };
|
|
28565
|
+
let cancelled = false;
|
|
27982
28566
|
const tick = async () => {
|
|
27983
28567
|
const pc = pcRef.current;
|
|
27984
28568
|
if (!pc) return;
|
|
27985
28569
|
try {
|
|
27986
28570
|
const report = await pc.getStats();
|
|
27987
|
-
|
|
27988
|
-
|
|
27989
|
-
|
|
27990
|
-
|
|
27991
|
-
|
|
27992
|
-
|
|
27993
|
-
|
|
27994
|
-
const s = raw;
|
|
27995
|
-
if (s.type === "inbound-rtp" && (s.kind ?? s.mediaType) === "video") {
|
|
27996
|
-
bytes = s.bytesReceived ?? 0;
|
|
27997
|
-
ts = s.timestamp;
|
|
27998
|
-
fps = s.framesPerSecond ?? 0;
|
|
27999
|
-
w = s.frameWidth ?? 0;
|
|
28000
|
-
h = s.frameHeight ?? 0;
|
|
28001
|
-
} else if (s.type === "candidate-pair" && s.nominated && typeof s.currentRoundTripTime === "number") rtt = s.currentRoundTripTime;
|
|
28571
|
+
if (cancelled) return;
|
|
28572
|
+
const next = deriveWebrtcDebugStats({
|
|
28573
|
+
report,
|
|
28574
|
+
prev: prev.current,
|
|
28575
|
+
now: Date.now(),
|
|
28576
|
+
iceConnectionState: pc.iceConnectionState,
|
|
28577
|
+
dtlsState: pc.connectionState
|
|
28002
28578
|
});
|
|
28003
|
-
|
|
28004
|
-
|
|
28005
|
-
statsPrev.current = {
|
|
28006
|
-
bytes,
|
|
28007
|
-
ts
|
|
28008
|
-
};
|
|
28009
|
-
const parts = [];
|
|
28010
|
-
if (w && h) parts.push(`${w}×${h}`);
|
|
28011
|
-
if (fps) parts.push(`${Math.round(fps)}fps`);
|
|
28012
|
-
if (kbps > 0) parts.push(`${kbps} kbps`);
|
|
28013
|
-
if (rtt) parts.push(`${Math.round(rtt * 1e3)}ms`);
|
|
28014
|
-
setStatsText(parts.join(" · "));
|
|
28579
|
+
prev.current = next;
|
|
28580
|
+
setDebugStats(next);
|
|
28015
28581
|
} catch {}
|
|
28016
28582
|
};
|
|
28017
28583
|
tick();
|
|
28018
28584
|
const id = setInterval(() => {
|
|
28019
28585
|
tick();
|
|
28020
28586
|
}, 1e3);
|
|
28021
|
-
return () =>
|
|
28587
|
+
return () => {
|
|
28588
|
+
cancelled = true;
|
|
28589
|
+
clearInterval(id);
|
|
28590
|
+
};
|
|
28022
28591
|
}, [showStats]);
|
|
28592
|
+
(0, react$1.useEffect)(() => {
|
|
28593
|
+
if (!showStats || !getSessionDebug) {
|
|
28594
|
+
setServerDebug(null);
|
|
28595
|
+
setServerDebugError(null);
|
|
28596
|
+
return;
|
|
28597
|
+
}
|
|
28598
|
+
let cancelled = false;
|
|
28599
|
+
const tick = async () => {
|
|
28600
|
+
const sid = activeSessionIdRef.current;
|
|
28601
|
+
if (sid === null) return;
|
|
28602
|
+
try {
|
|
28603
|
+
const answer = await getSessionDebug(sid);
|
|
28604
|
+
if (cancelled) return;
|
|
28605
|
+
setServerDebug(answer);
|
|
28606
|
+
setServerDebugError(null);
|
|
28607
|
+
} catch (err) {
|
|
28608
|
+
if (cancelled) return;
|
|
28609
|
+
setServerDebugError(err instanceof Error ? err.message : String(err));
|
|
28610
|
+
}
|
|
28611
|
+
};
|
|
28612
|
+
tick();
|
|
28613
|
+
const id = setInterval(() => {
|
|
28614
|
+
tick();
|
|
28615
|
+
}, 1e3);
|
|
28616
|
+
return () => {
|
|
28617
|
+
cancelled = true;
|
|
28618
|
+
clearInterval(id);
|
|
28619
|
+
};
|
|
28620
|
+
}, [showStats, getSessionDebug]);
|
|
28023
28621
|
const netPrev = (0, react$1.useRef)(null);
|
|
28024
28622
|
(0, react$1.useEffect)(() => {
|
|
28025
28623
|
if (!onClientNetworkSample) {
|
|
@@ -28206,9 +28804,13 @@ function CameraStreamPlayer({ serverUrl, streamKey, label, autoPlay = true, mute
|
|
|
28206
28804
|
className: "absolute top-2 left-2 z-10 transform-gpu px-2 py-0.5 rounded bg-black/60 text-[10px] text-white font-medium",
|
|
28207
28805
|
children: label
|
|
28208
28806
|
}),
|
|
28209
|
-
showStats &&
|
|
28210
|
-
|
|
28211
|
-
|
|
28807
|
+
showStats && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamDebugOverlay, {
|
|
28808
|
+
stats: debugStats,
|
|
28809
|
+
server: serverDebug,
|
|
28810
|
+
serverError: serverDebugError,
|
|
28811
|
+
serverWired: getSessionDebug !== void 0,
|
|
28812
|
+
now: debugNow,
|
|
28813
|
+
sessionId: activeSessionIdRef.current
|
|
28212
28814
|
}),
|
|
28213
28815
|
overlay,
|
|
28214
28816
|
showControls && !stillImg && state === "connecting" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -51561,6 +52163,13 @@ function useDeviceWebrtc(trpc, deviceId, pollIntervalMs = 5e3) {
|
|
|
51561
52163
|
} catch {
|
|
51562
52164
|
return { pendingRenegotiation: null };
|
|
51563
52165
|
}
|
|
52166
|
+
}, [trpc, deviceId]),
|
|
52167
|
+
getSessionDebug: (0, react$1.useCallback)(async (sessionId) => {
|
|
52168
|
+
if (deviceId === null) throw new Error("getSessionDebug: no device bound to this player");
|
|
52169
|
+
return trpc.webrtcSession.getSessionDebug.query({
|
|
52170
|
+
deviceId,
|
|
52171
|
+
sessionId
|
|
52172
|
+
});
|
|
51564
52173
|
}, [trpc, deviceId])
|
|
51565
52174
|
};
|
|
51566
52175
|
}
|
|
@@ -52077,6 +52686,7 @@ exports.StepTimings = StepTimings;
|
|
|
52077
52686
|
exports.StepTreeMaster = StepTreeMaster;
|
|
52078
52687
|
exports.Stepper = Stepper;
|
|
52079
52688
|
exports.StreamBrokerSelector = StreamBrokerSelector;
|
|
52689
|
+
exports.StreamDebugOverlay = StreamDebugOverlay;
|
|
52080
52690
|
exports.StreamPanel = StreamPanel;
|
|
52081
52691
|
exports.Switch = Switch;
|
|
52082
52692
|
exports.SwitchHeroCard = SwitchHeroCard;
|
|
@@ -52142,6 +52752,7 @@ exports.cursorFractionFor = cursorFractionFor;
|
|
|
52142
52752
|
exports.darkColors = require_theme_index.darkColors$1;
|
|
52143
52753
|
exports.defaultTheme = require_theme_index.defaultTheme$1;
|
|
52144
52754
|
exports.deriveDeviceKind = deriveDeviceKind;
|
|
52755
|
+
exports.deriveWebrtcDebugStats = deriveWebrtcDebugStats;
|
|
52145
52756
|
exports.describeDeviceSelector = describeDeviceSelector;
|
|
52146
52757
|
exports.deviceMatchesFilter = deviceMatchesFilter;
|
|
52147
52758
|
exports.deviceOptionLabel = deviceOptionLabel;
|
|
@@ -52158,6 +52769,7 @@ exports.findTimezone = _camstack_types.findTimezone;
|
|
|
52158
52769
|
exports.formatControlDateTime = formatControlDateTime;
|
|
52159
52770
|
exports.formatLastSeen = formatLastSeen;
|
|
52160
52771
|
exports.formatNumeric = formatNumeric;
|
|
52772
|
+
exports.freezeVerdict = freezeVerdict;
|
|
52161
52773
|
exports.fuzzyMatch = fuzzyMatch;
|
|
52162
52774
|
exports.getClassColor = getClassColor;
|
|
52163
52775
|
exports.getPhaseVisual = getPhaseVisual;
|
|
@@ -53327,6 +53939,7 @@ exports.useWebrtcSessionAddIceCandidate = useWebrtcSessionAddIceCandidate;
|
|
|
53327
53939
|
exports.useWebrtcSessionCloseSession = useWebrtcSessionCloseSession;
|
|
53328
53940
|
exports.useWebrtcSessionCreateSession = useWebrtcSessionCreateSession;
|
|
53329
53941
|
exports.useWebrtcSessionGetIceCandidates = useWebrtcSessionGetIceCandidates;
|
|
53942
|
+
exports.useWebrtcSessionGetSessionDebug = useWebrtcSessionGetSessionDebug;
|
|
53330
53943
|
exports.useWebrtcSessionGetSessionState = useWebrtcSessionGetSessionState;
|
|
53331
53944
|
exports.useWebrtcSessionHandleAnswer = useWebrtcSessionHandleAnswer;
|
|
53332
53945
|
exports.useWebrtcSessionHandleOffer = useWebrtcSessionHandleOffer;
|