@vpalmisano/webrtcperf 4.5.1 → 4.6.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plot.js","sourceRoot":"","sources":["../../src/plot.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs'\n\nimport { logger } from './utils'\nimport json5 from 'json5'\nimport { formatThrottleRule, parseStatsFile, parseThrottleRule, StatsRow } from './scenarios'\nimport path from 'path'\n\nconst log = logger('webrtcperf:plot')\n\nexport type PlotOptions = {\n type?: string\n title?: string\n xLabel?: string\n yLabel?: string\n yMin?: number\n yMax?: number\n labels?: (string | number)[]\n filePath?: string\n}\n\nexport type PlotData = {\n label: string\n data: { x: number | string; y: number; yMin?: number; yMax?: number }[]\n}\n\nconst SERIES_COLORS = [\n 'rgba(33, 150, 243, 1)',\n 'rgba(244, 67, 54, 1)',\n 'rgba(76, 175, 80, 1)',\n 'rgba(255, 193, 7, 1)',\n 'rgba(156, 39, 176, 1)',\n]\n\nexport function plotConfig(options: PlotOptions, series: PlotData[]) {\n log.debug('plotConfig')\n\n return {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type: (options.type || 'line') as any,\n options: {\n plugins: {\n title: options.title\n ? {\n display: true,\n text: options.title,\n }\n : undefined,\n zoom: {\n pan: {\n enabled: true,\n mode: 'x',\n modifierKey: 'ctrl',\n },\n zoom: {\n drag: {\n enabled: true,\n },\n mode: 'x',\n },\n },\n },\n scales: {\n x: {\n type: 'category',\n title: options.xLabel\n ? {\n display: true,\n text: options.xLabel,\n }\n : undefined,\n },\n y: {\n type: 'linear',\n title: options.yLabel\n ? {\n display: true,\n text: options.yLabel,\n }\n : undefined,\n min: options.yMin,\n max: options.yMax,\n },\n },\n },\n data: {\n labels: options.labels,\n datasets: series.map((s, i) => ({\n fill: false,\n backgroundColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderWidth: 1,\n pointRadius: 0,\n ...s,\n })),\n },\n }\n}\n\nexport async function plot(options: PlotOptions, series: PlotData[]) {\n const {\n CategoryScale,\n Chart,\n LinearScale,\n LineController,\n BarController,\n LineElement,\n BarElement,\n PointElement,\n Legend,\n Title,\n } = await import('chart.js')\n const { BarWithErrorBar, BarWithErrorBarsController } = await import('chartjs-chart-error-bars')\n Chart.register(\n CategoryScale,\n LineController,\n LineElement,\n BarController,\n LinearScale,\n BarElement,\n PointElement,\n Legend,\n Title,\n BarWithErrorBar,\n BarWithErrorBarsController,\n )\n const { Canvas } = await import('skia-canvas')\n\n log.debug('plot')\n const config = plotConfig(options, series)\n const canvas = new Canvas(1280, 720)\n const chart = new Chart(canvas as unknown as HTMLCanvasElement, config)\n await canvas.toFile(options.filePath || 'plot.png', { format: 'png', matte: 'white' })\n chart.destroy()\n}\n\nexport async function plotHtml(options: PlotOptions, series: PlotData[]) {\n log.debug('plotHtml')\n const config = plotConfig(options, series)\n\n const data = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${options.title || 'Plot'}</title>\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-chart-error-bars\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/hammerjs\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom\"></script>\n</head>\n<body>\n <div>\n <canvas id=\"chart\"></canvas>\n </div>\n <script>\n const ctx = document.getElementById('chart');\n const chart = new Chart(ctx, ${json5.stringify(config)});\n chart.options.onClick = e => e.chart.resetZoom();\n addEventListener('resize', () => chart.resize());\n </script>\n</body>\n</html>`\n await fs.promises.writeFile(options.filePath || 'plot.html', data)\n}\n\nfunction groupByParticipant(rows: StatsRow[]) {\n const m = new Map<string, StatsRow[]>()\n for (const r of rows) {\n if (!r.participantName) continue\n const p = r.participantName as string\n if (!m.has(p)) m.set(p, [])\n m.get(p)!.push(r)\n }\n return m\n}\n\nexport async function plotDetailedStatsDashboard(statsFile: string, outFile = 'plot.html') {\n const rows = await parseStatsFile(statsFile)\n if (rows.length === 0) {\n log.warn('No stats found')\n return\n }\n\n const byParticipant = groupByParticipant(rows)\n const participants = Array.from(byParticipant.keys()).sort()\n\n type ChartSpec = { id: string; title?: string; yLabel?: string; datasets?: PlotData[]; width?: number }\n const charts: ChartSpec[] = []\n\n const build = (\n id: string,\n title?: string,\n yLabel?: string,\n processValue?: (value: number) => number,\n width?: number,\n ) => {\n const series: PlotData[] = []\n if (!id.startsWith('_')) {\n for (const [participant, rows] of byParticipant.entries()) {\n const dataPerTrack = new Map<string, { x: number; y: number }[]>()\n for (const r of rows) {\n const trackId = (r.trackId as string) || ''\n if (!dataPerTrack.has(trackId)) dataPerTrack.set(trackId, [])\n const data = dataPerTrack.get(trackId)!\n const v = r[id] as number\n if (v !== undefined) data.push({ x: r.datetime as number, y: processValue ? processValue(v) : v })\n }\n dataPerTrack.forEach((data, trackId) => {\n if (data.length) series.push({ label: `${participant}${trackId ? ` (${trackId})` : ''}`, data: data })\n })\n }\n }\n charts.push({ id, title, yLabel, datasets: series, width })\n }\n\n const kbps = (v: number) => v / 1000\n const percent = (v: number) => v * 100\n const ms = (v: number) => v * 1000\n\n ;[\n { id: '_throttle', title: 'Throttle settings' },\n { id: 'throttleUpRate', title: 'Throttle up rate', yLabel: 'Kbps', processValue: kbps, width: 2 },\n { id: 'throttleUpDelay', title: 'Throttle up delay', yLabel: 'ms', width: 2 },\n { id: 'throttleUpLoss', title: 'Throttle up loss', yLabel: '%', width: 2 },\n { id: 'throttleDownRate', title: 'Throttle down rate', yLabel: 'Kbps', processValue: kbps, width: 2 },\n { id: 'throttleDownDelay', title: 'Throttle down delay', yLabel: 'ms', width: 2 },\n { id: 'throttleDownLoss', title: 'Throttle down loss', yLabel: '%', width: 2 },\n // Performance / Connectivity\n { id: '_performance', title: 'Performance / Connectivity' },\n { id: 'pageCpu', title: 'Page CPU', yLabel: '%' },\n { id: 'pageMemory', title: 'Page memory', yLabel: 'MB' },\n { id: 'peerConnectionConnectionTime', title: 'Peer connection connection time', yLabel: 's' },\n { id: 'peerConnectionDisconnectionTime', title: 'Peer connection disconnection time', yLabel: 's' },\n // Sent audio\n { id: '_sentAudio', title: 'Sent audio' },\n { id: 'audioSentBitrates', title: 'Sent audio bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'audioSentPacketsLossRate', title: 'Send audio loss', yLabel: '%', processValue: percent },\n { id: 'audioSentRoundTripTime', title: 'Send audio RTT', yLabel: 'ms', processValue: ms },\n { id: 'audioSentJitter', title: 'Send audio jitter', yLabel: 'ms', processValue: ms },\n // Sent video\n { id: '_sentVideo', title: 'Sent video' },\n { id: 'videoSentBitrates', title: 'Sent video bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'videoSentPacketsLossRate', title: 'Send video loss', yLabel: '%', processValue: percent },\n { id: 'videoSentRoundTripTime', title: 'Send video RTT', yLabel: 'ms', processValue: ms },\n { id: 'videoSentJitter', title: 'Send video jitter', yLabel: 'ms', processValue: ms },\n { id: 'videoSentWidth', title: 'Send video width', yLabel: 'px' },\n { id: 'videoSentHeight', title: 'Send video height', yLabel: 'px' },\n { id: 'videoSentFps', title: 'Send video framerate', yLabel: 'fps' },\n {\n id: 'transportSentAvailableOutgoingBitrate',\n title: 'Send available bitrate',\n yLabel: 'Kbps',\n processValue: kbps,\n },\n { id: 'videoQualityLimitationCpu', title: 'Send video CPU limitation', yLabel: '%' },\n { id: 'videoQualityLimitationBandwidth', title: 'Send video bandwidth limitation', yLabel: '%' },\n { id: 'videoFirCountReceived', title: 'Send video FIR count', yLabel: 'count' },\n { id: 'videoPliCountReceived', title: 'Send video PLI count', yLabel: 'count' },\n // Sent screen\n { id: '_sentScreen', title: 'Sent screen' },\n { id: 'screenSentBitrates', title: 'Sent screen bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'screenSentPacketsLossRate', title: 'Send screen loss', yLabel: '%', processValue: percent },\n { id: 'screenSentRoundTripTime', title: 'Send screen RTT', yLabel: 'ms', processValue: ms },\n { id: 'screenSentJitter', title: 'Send screen jitter', yLabel: 'ms', processValue: ms },\n { id: 'screenSentWidth', title: 'Send screen width', yLabel: 'px' },\n { id: 'screenSentHeight', title: 'Send screen height', yLabel: 'px' },\n { id: 'screenSentFps', title: 'Send screen framerate', yLabel: 'fps' },\n { id: '' },\n { id: 'screenQualityLimitationCpu', title: 'Send screen CPU limitation', yLabel: '%' },\n { id: 'screenQualityLimitationBandwidth', title: 'Send screen bandwidth limitation', yLabel: '%' },\n { id: 'screenFirCountReceived', title: 'Send screen FIR count', yLabel: 'count' },\n { id: 'screenPliCountReceived', title: 'Send screen PLI count', yLabel: 'count' },\n // Recv audio\n { id: '_recvAudio', title: 'Recv audio' },\n { id: 'audioRecvBitrates', title: 'Recv audio bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'audioRecvPacketsLossRate', title: 'Recv audio loss', yLabel: '%', processValue: percent },\n { id: 'audioRecvJitter', title: 'Recv audio jitter', yLabel: 'ms', processValue: ms },\n { id: 'audioRecvAvgJitterBufferDelay', title: 'Recv audio jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'audioRecvLevel', title: 'Recv audio level', yLabel: 'db' },\n { id: 'audioRecvConcealmentEvents', title: 'Recv audio concealment events', yLabel: 'count' },\n {\n id: 'audioRecvInsertedSamplesForDeceleration',\n title: 'Recv audio inserted samples',\n yLabel: 'count',\n },\n {\n id: 'audioRecvRemovedSamplesForAcceleration',\n title: 'Recv audio removed samples',\n yLabel: 'count',\n },\n { id: 'audioRecvEndToEndDelay', title: 'Recv audio end to end delay', yLabel: 'ms', processValue: ms },\n // Recv video\n { id: '_recvVideo', title: 'Recv video' },\n { id: 'videoRecvBitrates', title: 'Recv video bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'videoRecvPacketsLossRate', title: 'Recv video loss', yLabel: '%', processValue: percent },\n { id: 'videoRecvJitter', title: 'Recv video jitter', yLabel: 'ms', processValue: ms },\n { id: 'videoRecvAvgJitterBufferDelay', title: 'Recv video jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'videoRecvWidth', title: 'Recv video width', yLabel: 'px' },\n { id: 'videoRecvHeight', title: 'Recv video height', yLabel: 'px' },\n { id: 'videoRecvFps', title: 'Recv video framerate', yLabel: 'fps' },\n { id: 'videoTotalFreezesDuration', title: 'Recv video freezes', yLabel: 'count' },\n { id: 'videoFirCountSent', title: 'Recv video FIR sent', yLabel: 'count' },\n { id: 'videoPliCountSent', title: 'Recv video PLI sent', yLabel: 'count' },\n { id: 'videoRecvEndToEndDelay', title: 'Recv video end to end delay', yLabel: 'ms', processValue: ms },\n { id: '' },\n // Recv screen\n { id: '_recvScreen', title: 'Recv screen' },\n { id: 'screenRecvBitrates', title: 'Recv screen bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'screenRecvPacketsLossRate', title: 'Recv screen loss', yLabel: '%', processValue: percent },\n { id: 'screenRecvJitter', title: 'Recv screen jitter', yLabel: 'ms', processValue: ms },\n { id: 'screenRecvAvgJitterBufferDelay', title: 'Recv screen jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'screenRecvWidth', title: 'Recv screen width', yLabel: 'px' },\n { id: 'screenRecvHeight', title: 'Recv screen height', yLabel: 'px' },\n { id: 'screenRecvFps', title: 'Recv screen framerate', yLabel: 'fps' },\n { id: 'screenTotalFreezesDuration', title: 'Recv screen freezes', yLabel: 'count' },\n { id: 'screenFirCountSent', title: 'Recv screen FIR sent', yLabel: 'count' },\n { id: 'screenPliCountSent', title: 'Recv screen PLI sent', yLabel: 'count' },\n { id: 'screenRecvEndToEndDelay', title: 'Recv screen end to end delay', yLabel: 'ms', processValue: ms },\n { id: '' },\n ].forEach(graph => {\n build(graph.id, graph.title, graph.yLabel, graph.processValue, graph.width)\n })\n\n const [_, id, scenario] = path.basename(path.dirname(statsFile)).split('_')\n const description = formatThrottleRule(parseThrottleRule(scenario), true, false)\n\n const data = `\\\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${id} (${description})</title>\n <link rel=\"icon\" href=\"https://raw.githubusercontent.com/vpalmisano/webrtcperf/devel/media/logo.svg\">\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-chart-error-bars\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/hammerjs\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom\"></script>\n <script src=\"https://unpkg.com/vue@3/dist/vue.global.prod.js\"></script>\n <link href=\"https://cdn.jsdelivr.net/npm/@mdi/font@7.x/css/materialdesignicons.min.css\" rel=\"stylesheet\">\n <link href=\"https://cdn.jsdelivr.net/npm/vuetify@3.7.2/dist/vuetify.min.css\" rel=\"stylesheet\">\n <script src=\"https://cdn.jsdelivr.net/npm/vuetify@3.7.2/dist/vuetify.min.js\"></script>\n</head>\n<body>\n <div id=\"app\">\n <v-app>\n <v-main>\n <v-app-bar color=\"primary\" density=\"compact\">\n <v-app-bar-title><b>${id}</b> (${description})</v-app-bar-title>\n <template v-slot:append>\n <v-select color=\"primary\" :items=\"participants\" v-model=\"selected\" density=\"compact\" variant=\"solo\" hide-details=\"auto\"></v-select>\n </template>\n </v-app-bar>\n <v-container fluid>\n <v-row dense>\n <v-col v-for=\"c in charts\" :key=\"c.id\" cols=\"12\" :md=\"isExpanded(c.id) ? 12 : c.width || 3\">\n <template v-if=\"c.id\">\n <v-card color=\"primary\" :variant=\"c.id.startsWith('_') ? 'tonal' : 'text'\">\n <v-card-title class=\"text-subtitle-1 d-flex align-center flex-nowrap\" @click=\"toggleExpanded(c)\" style=\"cursor: pointer;\">\n <span class=\"text-truncate\">{{ c.title }}</span>\n </v-card-title>\n <v-card-text v-if=\"!c.id.startsWith('_')\" style=\"min-height: 250px;\">\n <canvas :id=\"c.id\"></canvas>\n </v-card-text>\n </v-card>\n </template>\n <template v-else>\n <div class=\"empty-slot\"></div>\n </template>\n </v-col>\n </v-row>\n </v-container>\n <v-footer color=\"primary\" density=\"compact\">\n <v-btn class=\"text-none\" variant=\"text\" density=\"compact\" size=\"small\" href=\"https://github.com/vpalmisano/webrtcperf\" target=\"_blank\">Generated with webrtcperf</v-btn>\n </v-footer>\n </v-main>\n </v-app>\n </div>\n\n <script>\n const { createApp, onMounted, nextTick, watch, ref } = Vue;\n const vuetify = Vuetify.createVuetify();\n const PARTICIPANTS = ${json5.stringify(['All', ...participants])};\n const CHARTS = ${json5.stringify(charts)};\n const SERIES_COLORS = ${json5.stringify(SERIES_COLORS)};\n\n function fmtTime(v) {\n const d = new Date(Number(v));\n if (!isFinite(d.getTime())) return v;\n const pad = n => String(n).padStart(2, '0');\n return pad(d.getHours()) + ':' + pad(d.getMinutes())\n }\n\n function buildDatasets(datasets, selected) {\n const filtered = selected === 'All' ? datasets : datasets.filter(d => d.label.startsWith(selected));\n return filtered.map((s, i) => ({\n label: s.label,\n data: s.data,\n fill: false,\n backgroundColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderWidth: 1,\n pointRadius: 0,\n }));\n }\n\n createApp({\n setup() {\n const participants = ref(PARTICIPANTS);\n const selected = ref('All');\n const charts = ref(CHARTS);\n const chartInstances = new Map();\n const expanded = ref(new Set());\n\n function onPanZoom({ chart }) {\n const x = chart.scales.x;\n if (!x) return;\n // Sync zoom level across all charts\n for (const { chart: otherChart } of chartInstances.values()) {\n if (otherChart !== chart) {\n const otherX = otherChart.scales.x;\n if (otherX) {\n otherX.options.min = x.min;\n otherX.options.max = x.max;\n otherChart.update('none');\n }\n }\n }\n }\n\n function createPanel(chartSpec) {\n const canvas = document.getElementById(chartSpec.id);\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n const chart = new Chart(ctx, {\n type: 'line',\n options: {\n maintainAspectRatio: false,\n animation: false,\n layout: {\n padding: 0,\n },\n interaction: {\n intersect: false,\n mode: 'x',\n },\n plugins: {\n tooltip: {\n callbacks: {\n title: (context) => {\n if (context[0].parsed.x !== null) {\n return fmtTime(context[0].parsed.x);\n }\n return '';\n },\n label: (context) => {\n return context.parsed.y;\n }\n },\n },\n legend: { \n display: true,\n position: 'bottom',\n align: 'start',\n maxHeight: 50,\n labels: {\n boxWidth: 8,\n boxHeight: 8,\n font: {\n size: 8,\n lineHeight: 1,\n },\n },\n },\n zoom: {\n pan: {\n enabled: true,\n mode: 'x',\n modifierKey: 'ctrl',\n onPan: onPanZoom,\n },\n zoom: {\n drag: { enabled: true },\n mode: 'x',\n onZoom: onPanZoom,\n },\n },\n },\n scales: {\n x: { \n type: 'linear',\n title: { display: false, text: 'Time' },\n ticks: { display: true, callback: (value) => fmtTime(value) },\n },\n y: {\n type: 'linear',\n title: { display: true, text: chartSpec.yLabel },\n min: 0,\n },\n },\n },\n data: { datasets: buildDatasets(chartSpec.datasets, selected.value) },\n });\n chartInstances.set(chartSpec.id, { chart, spec: chartSpec });\n\n canvas.addEventListener('contextmenu', e => {\n e.preventDefault();\n resetZoom();\n });\n }\n\n function rebuildCharts() {\n for (const { chart } of chartInstances.values()) chart.destroy();\n chartInstances.clear();\n nextTick(() => charts.value.forEach(createPanel));\n }\n\n function applyFilter() {\n for (const { chart, spec } of chartInstances.values()) {\n chart.data.datasets = buildDatasets(spec.datasets, selected.value);\n chart.update();\n }\n }\n\n function resetZoom() {\n for (const { chart } of chartInstances.values()) {\n chart.resetZoom('none');\n if (chart.scales.x) {\n chart.scales.x.options.min = undefined;\n chart.scales.x.options.max = undefined;\n }\n chart.update('none');\n }\n }\n\n function toggleExpanded(c) {\n const id = c.id;\n const s = new Set(expanded.value);\n if (s.has(id)) s.delete(id); else s.add(id);\n expanded.value = s;\n nextTick(() => { const entry = chartInstances.get(id); entry?.chart?.resize(); });\n }\n\n function isExpanded(id) {\n return id.startsWith('_') || expanded.value.has(id);\n }\n\n onMounted(() => {\n nextTick(() => charts.value.forEach(createPanel));\n window.addEventListener('resize', () => { for (const { chart } of chartInstances.values()) chart.resize(); });\n });\n\n watch(selected, () => applyFilter());\n\n return { participants, selected, charts, resetZoom, toggleExpanded, isExpanded };\n }\n }).use(vuetify).mount('#app');\n </script>\n</body>\n</html>`\n\n await fs.promises.writeFile(outFile, data)\n}\n"]}
1
+ {"version":3,"file":"plot.js","sourceRoot":"","sources":["../../src/plot.ts"],"names":[],"mappings":";;;;;AAiCA,gCA+DC;AAED,oBAmCC;AAED,4BA6BC;AAuBD,gEA4YC;AAvkBD,4CAAmB;AAEnB,mCAAgC;AAChC,kDAAyB;AACzB,2CAA6F;AAC7F,gDAAuB;AAEvB,MAAM,GAAG,GAAG,IAAA,cAAM,EAAC,iBAAiB,CAAC,CAAA;AAkBrC,MAAM,aAAa,GAAG;IACpB,uBAAuB;IACvB,sBAAsB;IACtB,sBAAsB;IACtB,sBAAsB;IACtB,uBAAuB;CACxB,CAAA;AAED,SAAgB,UAAU,CAAC,OAAoB,EAAE,MAAkB;IACjE,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAEvB,OAAO;QACL,8DAA8D;QAC9D,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAQ;QACrC,OAAO,EAAE;YACP,OAAO,EAAE;gBACP,KAAK,EAAE,OAAO,CAAC,KAAK;oBAClB,CAAC,CAAC;wBACE,OAAO,EAAE,IAAI;wBACb,IAAI,EAAE,OAAO,CAAC,KAAK;qBACpB;oBACH,CAAC,CAAC,SAAS;gBACb,IAAI,EAAE;oBACJ,GAAG,EAAE;wBACH,OAAO,EAAE,IAAI;wBACb,IAAI,EAAE,GAAG;wBACT,WAAW,EAAE,MAAM;qBACpB;oBACD,IAAI,EAAE;wBACJ,IAAI,EAAE;4BACJ,OAAO,EAAE,IAAI;yBACd;wBACD,IAAI,EAAE,GAAG;qBACV;iBACF;aACF;YACD,MAAM,EAAE;gBACN,CAAC,EAAE;oBACD,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,OAAO,CAAC,MAAM;wBACnB,CAAC,CAAC;4BACE,OAAO,EAAE,IAAI;4BACb,IAAI,EAAE,OAAO,CAAC,MAAM;yBACrB;wBACH,CAAC,CAAC,SAAS;iBACd;gBACD,CAAC,EAAE;oBACD,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,OAAO,CAAC,MAAM;wBACnB,CAAC,CAAC;4BACE,OAAO,EAAE,IAAI;4BACb,IAAI,EAAE,OAAO,CAAC,MAAM;yBACrB;wBACH,CAAC,CAAC,SAAS;oBACb,GAAG,EAAE,OAAO,CAAC,IAAI;oBACjB,GAAG,EAAE,OAAO,CAAC,IAAI;iBAClB;aACF;SACF;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9B,IAAI,EAAE,KAAK;gBACX,eAAe,EAAE,aAAa,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC;gBACxD,WAAW,EAAE,aAAa,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC;gBACpD,WAAW,EAAE,CAAC;gBACd,WAAW,EAAE,CAAC;gBACd,GAAG,CAAC;aACL,CAAC,CAAC;SACJ;KACF,CAAA;AACH,CAAC;AAEM,KAAK,UAAU,IAAI,CAAC,OAAoB,EAAE,MAAkB;IACjE,MAAM,EACJ,aAAa,EACb,KAAK,EACL,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,UAAU,EACV,YAAY,EACZ,MAAM,EACN,KAAK,GACN,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;IAC5B,MAAM,EAAE,eAAe,EAAE,0BAA0B,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAA;IAChG,KAAK,CAAC,QAAQ,CACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,YAAY,EACZ,MAAM,EACN,KAAK,EACL,eAAe,EACf,0BAA0B,CAC3B,CAAA;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAE9C,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACjB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,MAAsC,EAAE,MAAM,CAAC,CAAA;IACvE,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,IAAI,UAAU,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;IACtF,KAAK,CAAC,OAAO,EAAE,CAAA;AACjB,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,OAAoB,EAAE,MAAkB;IACrE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACrB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAE1C,MAAM,IAAI,GAAG;;;;;;WAMJ,OAAO,CAAC,KAAK,IAAI,MAAM;;;;;;;;;;;;mCAYC,eAAK,CAAC,SAAS,CAAC,MAAM,CAAC;;;;;QAKlD,CAAA;IACN,MAAM,YAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,IAAI,WAAW,EAAE,IAAI,CAAC,CAAA;AACpE,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAgB;IAC1C,MAAM,CAAC,GAAG,IAAI,GAAG,EAAsB,CAAA;IACvC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,eAAe;YAAE,SAAQ;QAChC,MAAM,CAAC,GAAG,CAAC,CAAC,eAAyB,CAAA;QACrC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC3B,CAAC,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED;;;;;;;;;GASG;AACI,KAAK,UAAU,0BAA0B,CAAC,SAAiB,EAAE,OAAO,GAAG,WAAW;IACvF,GAAG,CAAC,IAAI,CAAC,gCAAgC,SAAS,OAAO,OAAO,EAAE,CAAC,CAAA;IAEnE,MAAM,IAAI,GAAG,MAAM,IAAA,0BAAc,EAAC,SAAS,CAAC,CAAA;IAC5C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAC1B,OAAM;IACR,CAAC;IAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAA;IAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAG5D,MAAM,MAAM,GAAgB,EAAE,CAAA;IAE9B,MAAM,KAAK,GAAG,CACZ,EAAU,EACV,KAAc,EACd,MAAe,EACf,YAAwC,EACxC,KAAc,EACd,EAAE;QACF,MAAM,MAAM,GAAe,EAAE,CAAA;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,KAAK,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC1D,MAAM,YAAY,GAAG,IAAI,GAAG,EAAsC,CAAA;gBAClE,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;oBACrB,MAAM,OAAO,GAAI,CAAC,CAAC,OAAkB,IAAI,EAAE,CAAA;oBAC3C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC;wBAAE,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;oBAC7D,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAE,CAAA;oBACvC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAW,CAAA;oBACzB,IAAI,CAAC,KAAK,SAAS;wBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,QAAkB,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;gBACpG,CAAC;gBACD,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;oBACrC,IAAI,IAAI,CAAC,MAAM;wBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;gBACxG,CAAC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IAC7D,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAA;IACpC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAA;IACtC,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAEjC;IAAA;QACC,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE;QAC/C,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;QACjG,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;QAC7E,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE;QAC1E,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;QACrG,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE;QACjF,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE;QAC9E,6BAA6B;QAC7B,EAAE,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,4BAA4B,EAAE;QAC3D,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE;QACjD,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE;QACxD,EAAE,EAAE,EAAE,8BAA8B,EAAE,KAAK,EAAE,iCAAiC,EAAE,MAAM,EAAE,GAAG,EAAE;QAC7F,EAAE,EAAE,EAAE,iCAAiC,EAAE,KAAK,EAAE,oCAAoC,EAAE,MAAM,EAAE,GAAG,EAAE;QACnG,aAAa;QACb,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;QACzC,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC5F,EAAE,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAChG,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACzF,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACrF,aAAa;QACb,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;QACzC,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC5F,EAAE,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAChG,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACzF,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACrF,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE;QACjE,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE;QACnE,EAAE,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,KAAK,EAAE;QACpE;YACE,EAAE,EAAE,uCAAuC;YAC3C,KAAK,EAAE,wBAAwB;YAC/B,MAAM,EAAE,MAAM;YACd,YAAY,EAAE,IAAI;SACnB;QACD,EAAE,EAAE,EAAE,2BAA2B,EAAE,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,GAAG,EAAE;QACpF,EAAE,EAAE,EAAE,iCAAiC,EAAE,KAAK,EAAE,iCAAiC,EAAE,MAAM,EAAE,GAAG,EAAE;QAChG,EAAE,EAAE,EAAE,uBAAuB,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/E,EAAE,EAAE,EAAE,uBAAuB,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/E,cAAc;QACd,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;QAC3C,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC9F,EAAE,EAAE,EAAE,2BAA2B,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAClG,EAAE,EAAE,EAAE,yBAAyB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QAC3F,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACvF,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE;QACnE,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE;QACrE,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,KAAK,EAAE;QACtE,EAAE,EAAE,EAAE,EAAE,EAAE;QACV,EAAE,EAAE,EAAE,4BAA4B,EAAE,KAAK,EAAE,4BAA4B,EAAE,MAAM,EAAE,GAAG,EAAE;QACtF,EAAE,EAAE,EAAE,kCAAkC,EAAE,KAAK,EAAE,kCAAkC,EAAE,MAAM,EAAE,GAAG,EAAE;QAClG,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,OAAO,EAAE;QACjF,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,OAAO,EAAE;QACjF,aAAa;QACb,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;QACzC,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC5F,EAAE,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAChG,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACrF,EAAE,EAAE,EAAE,+BAA+B,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QAC1G,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE;QACjE,EAAE,EAAE,EAAE,4BAA4B,EAAE,KAAK,EAAE,+BAA+B,EAAE,MAAM,EAAE,OAAO,EAAE;QAC7F;YACE,EAAE,EAAE,yCAAyC;YAC7C,KAAK,EAAE,6BAA6B;YACpC,MAAM,EAAE,OAAO;SAChB;QACD;YACE,EAAE,EAAE,wCAAwC;YAC5C,KAAK,EAAE,4BAA4B;YACnC,MAAM,EAAE,OAAO;SAChB;QACD,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,6BAA6B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACtG,aAAa;QACb,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;QACzC,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC5F,EAAE,EAAE,EAAE,0BAA0B,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAChG,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACrF,EAAE,EAAE,EAAE,+BAA+B,EAAE,KAAK,EAAE,0BAA0B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QAC1G,EAAE,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE;QACjE,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE;QACnE,EAAE,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,KAAK,EAAE;QACpE,EAAE,EAAE,EAAE,2BAA2B,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,OAAO,EAAE;QACjF,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC1E,EAAE,EAAE,EAAE,mBAAmB,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC1E,EAAE,EAAE,EAAE,wBAAwB,EAAE,KAAK,EAAE,6BAA6B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACtG,EAAE,EAAE,EAAE,EAAE,EAAE;QACV,cAAc;QACd,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;QAC3C,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE;QAC9F,EAAE,EAAE,EAAE,2BAA2B,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE;QAClG,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACvF,EAAE,EAAE,EAAE,gCAAgC,EAAE,KAAK,EAAE,2BAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QAC5G,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE;QACnE,EAAE,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE;QACrE,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,KAAK,EAAE;QACtE,EAAE,EAAE,EAAE,4BAA4B,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,OAAO,EAAE;QACnF,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC5E,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,OAAO,EAAE;QAC5E,EAAE,EAAE,EAAE,yBAAyB,EAAE,KAAK,EAAE,8BAA8B,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE;QACxG,EAAE,EAAE,EAAE,EAAE,EAAE;KACX,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QAChB,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IAC7E,CAAC,CAAC,CAAA;IAEF,MAAM,OAAO,GAAG,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;IACtD,IAAI,KAAK,GAAG,OAAO,CAAA;IACnB,IAAI,WAAW,GAAG,EAAE,CAAA;IACpB,IAAI,CAAC;QACH,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5C,KAAK,GAAG,EAAE,CAAA;QACV,WAAW,GAAG,IAAA,8BAAkB,EAAC,IAAA,6BAAiB,EAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,KAAK,CAAC,2BAA2B,OAAO,EAAE,EAAE,KAAK,CAAC,CAAA;IACxD,CAAC;IAED,MAAM,IAAI,GAAG;;;;;;WAMJ,KAAK,KAAK,WAAW;;;;;;;;;;;;;;;;gCAgBA,KAAK,OAAO,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAkCvD,eAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,GAAG,YAAY,CAAC,CAAC;qBAC/C,eAAK,CAAC,SAAS,CAAC,MAAM,CAAC;4BAChB,eAAK,CAAC,SAAS,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+KlD,CAAA;IAEN,MAAM,YAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import fs from 'fs'\n\nimport { logger } from './utils'\nimport json5 from 'json5'\nimport { formatThrottleRule, parseStatsFile, parseThrottleRule, StatsRow } from './scenarios'\nimport path from 'path'\n\nconst log = logger('webrtcperf:plot')\n\nexport type PlotOptions = {\n type?: string\n title?: string\n xLabel?: string\n yLabel?: string\n yMin?: number\n yMax?: number\n labels?: (string | number)[]\n filePath?: string\n}\n\nexport type PlotData = {\n label: string\n data: { x: number | string; y: number; yMin?: number; yMax?: number }[]\n}\n\nconst SERIES_COLORS = [\n 'rgba(33, 150, 243, 1)',\n 'rgba(244, 67, 54, 1)',\n 'rgba(76, 175, 80, 1)',\n 'rgba(255, 193, 7, 1)',\n 'rgba(156, 39, 176, 1)',\n]\n\nexport function plotConfig(options: PlotOptions, series: PlotData[]) {\n log.debug('plotConfig')\n\n return {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n type: (options.type || 'line') as any,\n options: {\n plugins: {\n title: options.title\n ? {\n display: true,\n text: options.title,\n }\n : undefined,\n zoom: {\n pan: {\n enabled: true,\n mode: 'x',\n modifierKey: 'ctrl',\n },\n zoom: {\n drag: {\n enabled: true,\n },\n mode: 'x',\n },\n },\n },\n scales: {\n x: {\n type: 'category',\n title: options.xLabel\n ? {\n display: true,\n text: options.xLabel,\n }\n : undefined,\n },\n y: {\n type: 'linear',\n title: options.yLabel\n ? {\n display: true,\n text: options.yLabel,\n }\n : undefined,\n min: options.yMin,\n max: options.yMax,\n },\n },\n },\n data: {\n labels: options.labels,\n datasets: series.map((s, i) => ({\n fill: false,\n backgroundColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderWidth: 1,\n pointRadius: 0,\n ...s,\n })),\n },\n }\n}\n\nexport async function plot(options: PlotOptions, series: PlotData[]) {\n const {\n CategoryScale,\n Chart,\n LinearScale,\n LineController,\n BarController,\n LineElement,\n BarElement,\n PointElement,\n Legend,\n Title,\n } = await import('chart.js')\n const { BarWithErrorBar, BarWithErrorBarsController } = await import('chartjs-chart-error-bars')\n Chart.register(\n CategoryScale,\n LineController,\n LineElement,\n BarController,\n LinearScale,\n BarElement,\n PointElement,\n Legend,\n Title,\n BarWithErrorBar,\n BarWithErrorBarsController,\n )\n const { Canvas } = await import('skia-canvas')\n\n log.debug('plot')\n const config = plotConfig(options, series)\n const canvas = new Canvas(1280, 720)\n const chart = new Chart(canvas as unknown as HTMLCanvasElement, config)\n await canvas.toFile(options.filePath || 'plot.png', { format: 'png', matte: 'white' })\n chart.destroy()\n}\n\nexport async function plotHtml(options: PlotOptions, series: PlotData[]) {\n log.debug('plotHtml')\n const config = plotConfig(options, series)\n\n const data = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${options.title || 'Plot'}</title>\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-chart-error-bars\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/hammerjs\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom\"></script>\n</head>\n<body>\n <div>\n <canvas id=\"chart\"></canvas>\n </div>\n <script>\n const ctx = document.getElementById('chart');\n const chart = new Chart(ctx, ${json5.stringify(config)});\n chart.options.onClick = e => e.chart.resetZoom();\n addEventListener('resize', () => chart.resize());\n </script>\n</body>\n</html>`\n await fs.promises.writeFile(options.filePath || 'plot.html', data)\n}\n\nfunction groupByParticipant(rows: StatsRow[]) {\n const m = new Map<string, StatsRow[]>()\n for (const r of rows) {\n if (!r.participantName) continue\n const p = r.participantName as string\n if (!m.has(p)) m.set(p, [])\n m.get(p)!.push(r)\n }\n return m\n}\n\n/**\n * It plots a detailed stats dashboard from a CSV file.\n * @param statsFile The path to the CSV file containing the detailed stats.\n * @param outFile The path to the output HTML file.\n * @returns A promise that resolves when the plot is complete.\n * @example\n * ```bash\n * webrtcperf --plot logs/detailed-stats.csv plot.html\n * ```\n */\nexport async function plotDetailedStatsDashboard(statsFile: string, outFile = 'plot.html') {\n log.info(`Plotting detailed stats from ${statsFile} to ${outFile}`)\n\n const rows = await parseStatsFile(statsFile)\n if (rows.length === 0) {\n log.warn('No stats found')\n return\n }\n\n const byParticipant = groupByParticipant(rows)\n const participants = Array.from(byParticipant.keys()).sort()\n\n type ChartSpec = { id: string; title?: string; yLabel?: string; datasets?: PlotData[]; width?: number }\n const charts: ChartSpec[] = []\n\n const build = (\n id: string,\n title?: string,\n yLabel?: string,\n processValue?: (value: number) => number,\n width?: number,\n ) => {\n const series: PlotData[] = []\n if (!id.startsWith('_')) {\n for (const [participant, rows] of byParticipant.entries()) {\n const dataPerTrack = new Map<string, { x: number; y: number }[]>()\n for (const r of rows) {\n const trackId = (r.trackId as string) || ''\n if (!dataPerTrack.has(trackId)) dataPerTrack.set(trackId, [])\n const data = dataPerTrack.get(trackId)!\n const v = r[id] as number\n if (v !== undefined) data.push({ x: r.datetime as number, y: processValue ? processValue(v) : v })\n }\n dataPerTrack.forEach((data, trackId) => {\n if (data.length) series.push({ label: `${participant}${trackId ? ` (${trackId})` : ''}`, data: data })\n })\n }\n }\n charts.push({ id, title, yLabel, datasets: series, width })\n }\n\n const kbps = (v: number) => v / 1000\n const percent = (v: number) => v * 100\n const ms = (v: number) => v * 1000\n\n ;[\n { id: '_throttle', title: 'Throttle settings' },\n { id: 'throttleUpRate', title: 'Throttle up rate', yLabel: 'Kbps', processValue: kbps, width: 2 },\n { id: 'throttleUpDelay', title: 'Throttle up delay', yLabel: 'ms', width: 2 },\n { id: 'throttleUpLoss', title: 'Throttle up loss', yLabel: '%', width: 2 },\n { id: 'throttleDownRate', title: 'Throttle down rate', yLabel: 'Kbps', processValue: kbps, width: 2 },\n { id: 'throttleDownDelay', title: 'Throttle down delay', yLabel: 'ms', width: 2 },\n { id: 'throttleDownLoss', title: 'Throttle down loss', yLabel: '%', width: 2 },\n // Performance / Connectivity\n { id: '_performance', title: 'Performance / Connectivity' },\n { id: 'pageCpu', title: 'Page CPU', yLabel: '%' },\n { id: 'pageMemory', title: 'Page memory', yLabel: 'MB' },\n { id: 'peerConnectionConnectionTime', title: 'Peer connection connection time', yLabel: 's' },\n { id: 'peerConnectionDisconnectionTime', title: 'Peer connection disconnection time', yLabel: 's' },\n // Sent audio\n { id: '_sentAudio', title: 'Sent audio' },\n { id: 'audioSentBitrates', title: 'Sent audio bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'audioSentPacketsLossRate', title: 'Send audio loss', yLabel: '%', processValue: percent },\n { id: 'audioSentRoundTripTime', title: 'Send audio RTT', yLabel: 'ms', processValue: ms },\n { id: 'audioSentJitter', title: 'Send audio jitter', yLabel: 'ms', processValue: ms },\n // Sent video\n { id: '_sentVideo', title: 'Sent video' },\n { id: 'videoSentBitrates', title: 'Sent video bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'videoSentPacketsLossRate', title: 'Send video loss', yLabel: '%', processValue: percent },\n { id: 'videoSentRoundTripTime', title: 'Send video RTT', yLabel: 'ms', processValue: ms },\n { id: 'videoSentJitter', title: 'Send video jitter', yLabel: 'ms', processValue: ms },\n { id: 'videoSentWidth', title: 'Send video width', yLabel: 'px' },\n { id: 'videoSentHeight', title: 'Send video height', yLabel: 'px' },\n { id: 'videoSentFps', title: 'Send video framerate', yLabel: 'fps' },\n {\n id: 'transportSentAvailableOutgoingBitrate',\n title: 'Send available bitrate',\n yLabel: 'Kbps',\n processValue: kbps,\n },\n { id: 'videoQualityLimitationCpu', title: 'Send video CPU limitation', yLabel: '%' },\n { id: 'videoQualityLimitationBandwidth', title: 'Send video bandwidth limitation', yLabel: '%' },\n { id: 'videoFirCountReceived', title: 'Send video FIR count', yLabel: 'count' },\n { id: 'videoPliCountReceived', title: 'Send video PLI count', yLabel: 'count' },\n // Sent screen\n { id: '_sentScreen', title: 'Sent screen' },\n { id: 'screenSentBitrates', title: 'Sent screen bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'screenSentPacketsLossRate', title: 'Send screen loss', yLabel: '%', processValue: percent },\n { id: 'screenSentRoundTripTime', title: 'Send screen RTT', yLabel: 'ms', processValue: ms },\n { id: 'screenSentJitter', title: 'Send screen jitter', yLabel: 'ms', processValue: ms },\n { id: 'screenSentWidth', title: 'Send screen width', yLabel: 'px' },\n { id: 'screenSentHeight', title: 'Send screen height', yLabel: 'px' },\n { id: 'screenSentFps', title: 'Send screen framerate', yLabel: 'fps' },\n { id: '' },\n { id: 'screenQualityLimitationCpu', title: 'Send screen CPU limitation', yLabel: '%' },\n { id: 'screenQualityLimitationBandwidth', title: 'Send screen bandwidth limitation', yLabel: '%' },\n { id: 'screenFirCountReceived', title: 'Send screen FIR count', yLabel: 'count' },\n { id: 'screenPliCountReceived', title: 'Send screen PLI count', yLabel: 'count' },\n // Recv audio\n { id: '_recvAudio', title: 'Recv audio' },\n { id: 'audioRecvBitrates', title: 'Recv audio bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'audioRecvPacketsLossRate', title: 'Recv audio loss', yLabel: '%', processValue: percent },\n { id: 'audioRecvJitter', title: 'Recv audio jitter', yLabel: 'ms', processValue: ms },\n { id: 'audioRecvAvgJitterBufferDelay', title: 'Recv audio jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'audioRecvLevel', title: 'Recv audio level', yLabel: 'db' },\n { id: 'audioRecvConcealmentEvents', title: 'Recv audio concealment events', yLabel: 'count' },\n {\n id: 'audioRecvInsertedSamplesForDeceleration',\n title: 'Recv audio inserted samples',\n yLabel: 'count',\n },\n {\n id: 'audioRecvRemovedSamplesForAcceleration',\n title: 'Recv audio removed samples',\n yLabel: 'count',\n },\n { id: 'audioRecvEndToEndDelay', title: 'Recv audio end to end delay', yLabel: 'ms', processValue: ms },\n // Recv video\n { id: '_recvVideo', title: 'Recv video' },\n { id: 'videoRecvBitrates', title: 'Recv video bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'videoRecvPacketsLossRate', title: 'Recv video loss', yLabel: '%', processValue: percent },\n { id: 'videoRecvJitter', title: 'Recv video jitter', yLabel: 'ms', processValue: ms },\n { id: 'videoRecvAvgJitterBufferDelay', title: 'Recv video jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'videoRecvWidth', title: 'Recv video width', yLabel: 'px' },\n { id: 'videoRecvHeight', title: 'Recv video height', yLabel: 'px' },\n { id: 'videoRecvFps', title: 'Recv video framerate', yLabel: 'fps' },\n { id: 'videoTotalFreezesDuration', title: 'Recv video freezes', yLabel: 'count' },\n { id: 'videoFirCountSent', title: 'Recv video FIR sent', yLabel: 'count' },\n { id: 'videoPliCountSent', title: 'Recv video PLI sent', yLabel: 'count' },\n { id: 'videoRecvEndToEndDelay', title: 'Recv video end to end delay', yLabel: 'ms', processValue: ms },\n { id: '' },\n // Recv screen\n { id: '_recvScreen', title: 'Recv screen' },\n { id: 'screenRecvBitrates', title: 'Recv screen bitrate', yLabel: 'Kbps', processValue: kbps },\n { id: 'screenRecvPacketsLossRate', title: 'Recv screen loss', yLabel: '%', processValue: percent },\n { id: 'screenRecvJitter', title: 'Recv screen jitter', yLabel: 'ms', processValue: ms },\n { id: 'screenRecvAvgJitterBufferDelay', title: 'Recv screen jitter buffer', yLabel: 'ms', processValue: ms },\n { id: 'screenRecvWidth', title: 'Recv screen width', yLabel: 'px' },\n { id: 'screenRecvHeight', title: 'Recv screen height', yLabel: 'px' },\n { id: 'screenRecvFps', title: 'Recv screen framerate', yLabel: 'fps' },\n { id: 'screenTotalFreezesDuration', title: 'Recv screen freezes', yLabel: 'count' },\n { id: 'screenFirCountSent', title: 'Recv screen FIR sent', yLabel: 'count' },\n { id: 'screenPliCountSent', title: 'Recv screen PLI sent', yLabel: 'count' },\n { id: 'screenRecvEndToEndDelay', title: 'Recv screen end to end delay', yLabel: 'ms', processValue: ms },\n { id: '' },\n ].forEach(graph => {\n build(graph.id, graph.title, graph.yLabel, graph.processValue, graph.width)\n })\n\n const dirName = path.basename(path.dirname(statsFile))\n let title = dirName\n let description = ''\n try {\n const [_, id, scenario] = dirName.split('_')\n title = id\n description = formatThrottleRule(parseThrottleRule(scenario), true, false)\n } catch (error) {\n log.debug(`Invalid directory name: ${dirName}`, error)\n }\n\n const data = `\\\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title} (${description})</title>\n <link rel=\"icon\" href=\"https://raw.githubusercontent.com/vpalmisano/webrtcperf/devel/media/logo.svg\">\n <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-chart-error-bars\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/hammerjs\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom\"></script>\n <script src=\"https://unpkg.com/vue@3/dist/vue.global.prod.js\"></script>\n <link href=\"https://cdn.jsdelivr.net/npm/@mdi/font@7.x/css/materialdesignicons.min.css\" rel=\"stylesheet\">\n <link href=\"https://cdn.jsdelivr.net/npm/vuetify@3.7.2/dist/vuetify.min.css\" rel=\"stylesheet\">\n <script src=\"https://cdn.jsdelivr.net/npm/vuetify@3.7.2/dist/vuetify.min.js\"></script>\n</head>\n<body>\n <div id=\"app\">\n <v-app>\n <v-main>\n <v-app-bar color=\"primary\" density=\"compact\">\n <v-app-bar-title><b>${title}</b>${description ? ` (${description})` : ''}</v-app-bar-title>\n <template v-slot:append>\n <v-select color=\"primary\" :items=\"participants\" v-model=\"selected\" density=\"compact\" variant=\"solo\" hide-details=\"auto\"></v-select>\n </template>\n </v-app-bar>\n <v-container fluid>\n <v-row dense>\n <v-col v-for=\"c in charts\" :key=\"c.id\" cols=\"12\" :md=\"isExpanded(c.id) ? 12 : c.width || 3\">\n <template v-if=\"c.id\">\n <v-card color=\"primary\" :variant=\"c.id.startsWith('_') ? 'tonal' : 'text'\">\n <v-card-title class=\"text-subtitle-1 d-flex align-center flex-nowrap\" @click=\"toggleExpanded(c)\" style=\"cursor: pointer;\">\n <span class=\"text-truncate\">{{ c.title }}</span>\n </v-card-title>\n <v-card-text v-if=\"!c.id.startsWith('_')\" style=\"min-height: 250px;\">\n <canvas :id=\"c.id\"></canvas>\n </v-card-text>\n </v-card>\n </template>\n <template v-else>\n <div class=\"empty-slot\"></div>\n </template>\n </v-col>\n </v-row>\n </v-container>\n <v-footer color=\"primary\" density=\"compact\">\n <v-btn class=\"text-none\" variant=\"text\" density=\"compact\" size=\"small\" href=\"https://github.com/vpalmisano/webrtcperf\" target=\"_blank\">Generated with webrtcperf</v-btn>\n </v-footer>\n </v-main>\n </v-app>\n </div>\n\n <script>\n const { createApp, onMounted, nextTick, watch, ref } = Vue;\n const vuetify = Vuetify.createVuetify();\n const PARTICIPANTS = ${json5.stringify(['All', ...participants])};\n const CHARTS = ${json5.stringify(charts)};\n const SERIES_COLORS = ${json5.stringify(SERIES_COLORS)};\n\n function fmtTime(v) {\n const d = new Date(Number(v));\n if (!isFinite(d.getTime())) return v;\n const pad = n => String(n).padStart(2, '0');\n return pad(d.getHours()) + ':' + pad(d.getMinutes())\n }\n\n function buildDatasets(datasets, selected) {\n const filtered = selected === 'All' ? datasets : datasets.filter(d => d.label.startsWith(selected));\n return filtered.map((s, i) => ({\n label: s.label,\n data: s.data,\n fill: false,\n backgroundColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderColor: SERIES_COLORS[i % SERIES_COLORS.length],\n borderWidth: 1,\n pointRadius: 0,\n }));\n }\n\n createApp({\n setup() {\n const participants = ref(PARTICIPANTS);\n const selected = ref('All');\n const charts = ref(CHARTS);\n const chartInstances = new Map();\n const expanded = ref(new Set());\n\n function onPanZoom({ chart }) {\n const x = chart.scales.x;\n if (!x) return;\n // Sync zoom level across all charts\n for (const { chart: otherChart } of chartInstances.values()) {\n if (otherChart !== chart) {\n const otherX = otherChart.scales.x;\n if (otherX) {\n otherX.options.min = x.min;\n otherX.options.max = x.max;\n otherChart.update('none');\n }\n }\n }\n }\n\n function createPanel(chartSpec) {\n const canvas = document.getElementById(chartSpec.id);\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n const chart = new Chart(ctx, {\n type: 'line',\n options: {\n maintainAspectRatio: false,\n animation: false,\n layout: {\n padding: 0,\n },\n interaction: {\n intersect: false,\n mode: 'x',\n },\n plugins: {\n tooltip: {\n callbacks: {\n title: (context) => {\n if (context[0].parsed.x !== null) {\n return fmtTime(context[0].parsed.x);\n }\n return '';\n },\n label: (context) => {\n return context.parsed.y;\n }\n },\n },\n legend: { \n display: true,\n position: 'bottom',\n align: 'start',\n maxHeight: 50,\n labels: {\n boxWidth: 8,\n boxHeight: 8,\n font: {\n size: 8,\n lineHeight: 1,\n },\n },\n },\n zoom: {\n pan: {\n enabled: true,\n mode: 'x',\n modifierKey: 'ctrl',\n onPan: onPanZoom,\n },\n zoom: {\n drag: { enabled: true },\n mode: 'x',\n onZoom: onPanZoom,\n },\n },\n },\n scales: {\n x: { \n type: 'linear',\n title: { display: false, text: 'Time' },\n ticks: { display: true, callback: (value) => fmtTime(value) },\n },\n y: {\n type: 'linear',\n title: { display: true, text: chartSpec.yLabel },\n min: 0,\n },\n },\n },\n data: { datasets: buildDatasets(chartSpec.datasets, selected.value) },\n });\n chartInstances.set(chartSpec.id, { chart, spec: chartSpec });\n\n canvas.addEventListener('contextmenu', e => {\n e.preventDefault();\n resetZoom();\n });\n }\n\n function rebuildCharts() {\n for (const { chart } of chartInstances.values()) chart.destroy();\n chartInstances.clear();\n nextTick(() => charts.value.forEach(createPanel));\n }\n\n function applyFilter() {\n for (const { chart, spec } of chartInstances.values()) {\n chart.data.datasets = buildDatasets(spec.datasets, selected.value);\n chart.update();\n }\n }\n\n function resetZoom() {\n for (const { chart } of chartInstances.values()) {\n chart.resetZoom('none');\n if (chart.scales.x) {\n chart.scales.x.options.min = undefined;\n chart.scales.x.options.max = undefined;\n }\n chart.update('none');\n }\n }\n\n function toggleExpanded(c) {\n const id = c.id;\n const s = new Set(expanded.value);\n if (s.has(id)) s.delete(id); else s.add(id);\n expanded.value = s;\n nextTick(() => { const entry = chartInstances.get(id); entry?.chart?.resize(); });\n }\n\n function isExpanded(id) {\n return id.startsWith('_') || expanded.value.has(id);\n }\n\n onMounted(() => {\n nextTick(() => charts.value.forEach(createPanel));\n window.addEventListener('resize', () => { for (const { chart } of chartInstances.values()) chart.resize(); });\n });\n\n watch(selected, () => applyFilter());\n\n return { participants, selected, charts, resetZoom, toggleExpanded, isExpanded };\n }\n }).use(vuetify).mount('#app');\n </script>\n</body>\n</html>`\n\n await fs.promises.writeFile(outFile, data)\n}\n"]}
@@ -234,6 +234,8 @@ export declare enum RtcStatsMetricNames {
234
234
  videoFirCountSent = "videoFirCountSent",
235
235
  videoPliCountSent = "videoPliCountSent",
236
236
  videoDecodeLatency = "videoDecodeLatency",
237
+ videoFramesDecoded = "videoFramesDecoded",
238
+ videoFramesDropped = "videoFramesDropped",
237
239
  videoRecvFrames = "videoRecvFrames",
238
240
  videoRecvFps = "videoRecvFps",
239
241
  videoRecvAvgJitterBufferDelay = "videoRecvAvgJitterBufferDelay",
@@ -256,6 +258,8 @@ export declare enum RtcStatsMetricNames {
256
258
  screenFirCountSent = "screenFirCountSent",
257
259
  screenPliCountSent = "screenPliCountSent",
258
260
  screenDecodeLatency = "screenDecodeLatency",
261
+ screenFramesDecoded = "screenFramesDecoded",
262
+ screenFramesDropped = "screenFramesDropped",
259
263
  screenRecvFrames = "screenRecvFrames",
260
264
  screenRecvFps = "screenRecvFps",
261
265
  screenRecvAvgJitterBufferDelay = "screenRecvAvgJitterBufferDelay",
@@ -254,7 +254,8 @@ var RtcStatsMetricNames;
254
254
  RtcStatsMetricNames["videoFirCountSent"] = "videoFirCountSent";
255
255
  RtcStatsMetricNames["videoPliCountSent"] = "videoPliCountSent";
256
256
  RtcStatsMetricNames["videoDecodeLatency"] = "videoDecodeLatency";
257
- //'videoFramesDecoded',
257
+ RtcStatsMetricNames["videoFramesDecoded"] = "videoFramesDecoded";
258
+ RtcStatsMetricNames["videoFramesDropped"] = "videoFramesDropped";
258
259
  RtcStatsMetricNames["videoRecvFrames"] = "videoRecvFrames";
259
260
  RtcStatsMetricNames["videoRecvFps"] = "videoRecvFps";
260
261
  RtcStatsMetricNames["videoRecvAvgJitterBufferDelay"] = "videoRecvAvgJitterBufferDelay";
@@ -279,7 +280,8 @@ var RtcStatsMetricNames;
279
280
  RtcStatsMetricNames["screenFirCountSent"] = "screenFirCountSent";
280
281
  RtcStatsMetricNames["screenPliCountSent"] = "screenPliCountSent";
281
282
  RtcStatsMetricNames["screenDecodeLatency"] = "screenDecodeLatency";
282
- //'screenFramesDecoded',
283
+ RtcStatsMetricNames["screenFramesDecoded"] = "screenFramesDecoded";
284
+ RtcStatsMetricNames["screenFramesDropped"] = "screenFramesDropped";
283
285
  RtcStatsMetricNames["screenRecvFrames"] = "screenRecvFrames";
284
286
  RtcStatsMetricNames["screenRecvFps"] = "screenRecvFps";
285
287
  RtcStatsMetricNames["screenRecvAvgJitterBufferDelay"] = "screenRecvAvgJitterBufferDelay";
@@ -373,7 +375,8 @@ value, signalingHost, participantName) {
373
375
  });
374
376
  }
375
377
  if (inboundRtp.kind === 'video' && inboundRtp.keyFramesDecoded > 0) {
376
- //setStats(stats, prefix + 'FramesDecoded', key, inboundRtp.framesDecoded
378
+ setStats(stats, (prefix + 'FramesDecoded'), key, inboundRtp.framesDecoded);
379
+ setStats(stats, (prefix + 'FramesDropped'), key, inboundRtp.framesDropped);
377
380
  setStats(stats, (prefix + 'RecvFrames'), key, inboundRtp.framesReceived);
378
381
  setStats(stats, (prefix + 'RecvFps'), key, inboundRtp.framesPerSecond);
379
382
  setStats(stats, (prefix + 'RecvHeight'), key, inboundRtp.frameHeight);
@@ -1 +1 @@
1
- {"version":3,"file":"rtcstats.js","sourceRoot":"","sources":["../../src/rtcstats.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert'\n\nimport { toTitleCase } from './utils'\n\n/**\n * Page stats metric names.\n */\nexport enum PageStatsNames {\n /** The browser processes CPU usage (per page). */\n cpu = 'cpu',\n /** The browser processes memory usage (per page). */\n memory = 'memory',\n /** The tool nodejs CPU usage. */\n nodeCpu = 'nodeCpu',\n /** The tool nodejs memory usage. */\n nodeMemory = 'nodeMemory',\n /** The system total CPU usage. */\n usedCpu = 'usedCpu',\n /** The system total memory usage. */\n usedMemory = 'usedMemory',\n /** The system total GPU usage. */\n usedGpu = 'usedGpu',\n /** The page CPU usage. */\n pageCpu = 'pageCpu',\n /** The page memory usage. */\n pageMemory = 'pageMemory',\n\n /** The opened pages count. */\n pages = 'pages',\n /** The current opened PeerConnections. */\n peerConnections = 'peerConnections',\n /** The maximum PeerConnections connected duration. */\n peerConnectionConnectionTime = 'peerConnectionConnectionTime',\n /** The maximum PeerConnections disconnection duration. */\n peerConnectionDisconnectionTime = 'peerConnectionDisconnectionTime',\n /** The total created PeerConnections. */\n peerConnectionsCreated = 'peerConnectionsCreated',\n /** The total connected PeerConnections. */\n peerConnectionsConnected = 'peerConnectionsConnected',\n /** The total closed PeerConnections. */\n peerConnectionsClosed = 'peerConnectionsClosed',\n /** The total disconnected PeerConnections. */\n peerConnectionsDisconnected = 'peerConnectionsDisconnected',\n /** The total failed PeerConnections. */\n peerConnectionsFailed = 'peerConnectionsFailed',\n /** The total delay from PeerConnections creation to connection. */\n peerConnectionsDelay = 'peerConnectionsDelay',\n\n /** The page errors count. */\n errors = 'errors',\n /** The page warnings count. */\n warnings = 'warnings',\n\n /** The page total HTTP sent bytes. */\n httpSentBytes = 'httpSentBytes',\n /** The page total HTTP received bytes. */\n httpRecvBytes = 'httpRecvBytes',\n /** The page HTTP receive latency. */\n httpRecvLatency = 'httpRecvLatency',\n\n /** The page total WebSocket sent bytes. */\n wsSentBytes = 'wsSentBytes',\n /** The page total WebSocket received bytes. */\n wsRecvBytes = 'wsRecvBytes',\n /** The page WebSocket receive latency. */\n wsRecvLatency = 'wsRecvLatency',\n\n /** The audio end to end total delay. */\n audioEndToEndDelay = 'audioEndToEndDelay',\n /** The audio start frame delay. */\n audioStartFrameDelay = 'audioStartFrameDelay',\n\n /** The video end to end total delay. */\n videoEndToEndDelay = 'videoEndToEndDelay',\n /** The video start frame delay. */\n videoStartFrameDelay = 'videoStartFrameDelay',\n\n /** The screen end to end total delay. */\n screenEndToEndDelay = 'screenEndToEndDelay',\n /** The screen start frame delay. */\n screenStartFrameDelay = 'screenStartFrameDelay',\n\n cpuPressure = 'cpuPressure',\n\n videoWidth = 'videoWidth',\n videoHeight = 'videoHeight',\n videoBufferedTime = 'videoBufferedTime',\n videoPlayingTime = 'videoPlayingTime',\n videoBufferingTime = 'videoBufferingTime',\n videoBufferingEvents = 'videoBufferingEvents',\n\n /** The throttle upload rate limitation. */\n throttleUpRate = 'throttleUpRate',\n /** The throttle upload delay. */\n throttleUpDelay = 'throttleUpDelay',\n /** The throttle upload packet loss. */\n throttleUpLoss = 'throttleUpLoss',\n /** The throttle upload packet queue. */\n throttleUpQueue = 'throttleUpQueue',\n\n /** The throttle download rate limitation. */\n throttleDownRate = 'throttleDownRate',\n /** The throttle download delay. */\n throttleDownDelay = 'throttleDownDelay',\n /** The throttle download packet loss. */\n throttleDownLoss = 'throttleDownLoss',\n /** The throttle download packet queue. */\n throttleDownQueue = 'throttleDownQueue',\n}\n\n/**\n * RTC metrics collected by the page helper scripts and related to each\n * track object created by PeerConnections.\n */\nexport enum RtcStatsMetricNames {\n /** The sent audio codec. */\n audioSentCodec = 'audioSentCodec',\n /** The total sent audio bytes. */\n audioSentBytes = 'audioSentBytes',\n /** The sent audio packets. */\n audioSentPackets = 'audioSentPackets',\n /** The sent audio bitrates. */\n audioSentBitrates = 'audioSentBitrates',\n /** The send audio lost packets. */\n audioSentPacketsLost = 'audioSentPacketsLost',\n //'audioSentPacketsLostCount',\n /** The total audio NACK received by the sender. */\n audioSentNackCountRecv = 'audioSentNackCountRecv',\n /** The sent audio round trip time. */\n audioSentRoundTripTime = 'audioSentRoundTripTime',\n /** The sent audio jitter. */\n audioSentJitter = 'audioSentJitter',\n /** The audio RTC transport round trip time. */\n audioSentTransportRoundTripTime = 'audioSentTransportRoundTripTime',\n /** The sent audio encoding max bitrate. */\n audioSentMaxBitrate = 'audioSentMaxBitrate',\n /** The sent audio RTX packets. */\n audioSentRetransmittedPackets = 'audioSentRetransmittedPackets',\n\n /** The sent video codec. */\n videoSentCodec = 'videoSentCodec',\n /** The FIR requests received by the video sender. */\n videoFirCountReceived = 'videoFirCountReceived',\n /** The PLI requests received by the video sender. */\n videoPliCountReceived = 'videoPliCountReceived',\n /** The sent video encode latency. */\n videoEncodeLatency = 'videoEncodeLatency',\n /** The sent video latency. */\n videoSentLatency = 'videoSentLatency',\n /** The sent video bandwidth quality limitations. */\n videoQualityLimitationBandwidth = 'videoQualityLimitationBandwidth',\n /** The sent video cpu quality limitations. */\n videoQualityLimitationCpu = 'videoQualityLimitationCpu',\n /** The sent video total resolution changes for quality limitations. */\n videoQualityLimitationResolutionChanges = 'videoQualityLimitationResolutionChanges',\n /** The sent video Simulcast active spatial layers. */\n videoSentActiveEncodings = 'videoSentActiveEncodings',\n /** The sent video bitrates. */\n videoSentBitrates = 'videoSentBitrates',\n /** The sent video bytes. */\n videoSentBytes = 'videoSentBytes',\n /** The sent video packets. */\n videoSentPackets = 'videoSentPackets',\n /** The sent video frames. */\n videoSentFrames = 'videoSentFrames',\n /** The sent video framerate. */\n videoSentFps = 'videoSentFps',\n /** The sent video width. */\n videoSentWidth = 'videoSentWidth',\n /** The sent video height. */\n videoSentHeight = 'videoSentHeight',\n /** The sent video encoding max bitrate. */\n videoSentMaxBitrate = 'videoSentMaxBitrate',\n //'videoSentPackets',\n /** The sent video lost packets. */\n videoSentPacketsLost = 'videoSentPacketsLost',\n //'videoSentPacketsLostCount',\n /** The NACK count received by video sender. */\n videoSentNackCountRecv = 'videoSentNackCountRecv',\n /** The sent video round trip time. */\n videoSentRoundTripTime = 'videoSentRoundTripTime',\n /** The transport send video round trip time. */\n videoSentTransportRoundTripTime = 'videoSentTransportRoundTripTime',\n /** The video sent jitter. */\n videoSentJitter = 'videoSentJitter',\n /** The sent video RTX packets. */\n videoSentRetransmittedPackets = 'videoSentRetransmittedPackets',\n\n /** The sent screen codec. */\n screenSentCodec = 'screenSentCodec',\n /** The received FIR from screen sender. */\n screenFirCountReceived = 'screenFirCountReceived',\n /** The received PLI from screen sender. */\n screenPliCountReceived = 'screenPliCountReceived',\n /** The sent screen encode latency. */\n screenEncodeLatency = 'screenEncodeLatency',\n /** The sent screen latency. */\n screenSentLatency = 'screenSentLatency',\n /** The sent screen bandwidth quality limitation. */\n screenQualityLimitationBandwidth = 'screenQualityLimitationBandwidth',\n /** The sent screen cpu quality limitation. */\n screenQualityLimitationCpu = 'screenQualityLimitationCpu',\n /** The sent screen resolustion changes caused by quality limitation. */\n screenQualityLimitationResolutionChanges = 'screenQualityLimitationResolutionChanges',\n /** The sent screen active Simulcast spatial layers. */\n screenSentActiveEncodings = 'screenSentActiveEncodings',\n /** The sent screen bitrates. */\n screenSentBitrates = 'screenSentBitrates',\n /** The sent screen bytes. */\n screenSentBytes = 'screenSentBytes',\n /** The sent screen packets. */\n screenSentPackets = 'screenSentPackets',\n /** The sent screen frames. */\n screenSentFrames = 'screenSentFrames',\n /** The sent screen framerate. */\n screenSentFps = 'screenSentFps',\n /** The sent screen width. */\n screenSentWidth = 'screenSentWidth',\n /** The sent screen height. */\n screenSentHeight = 'screenSentHeight',\n /** The sent screen encoding max bitrate. */\n screenSentMaxBitrate = 'screenSentMaxBitrate',\n //'screenSentPackets',\n /** The sent screen lost packets. */\n screenSentPacketsLost = 'screenSentPacketsLost',\n //'screenSentPacketsLostCount',\n /** The NACK count received by screen sender. */\n screenSentNackCountRecv = 'screenSentNackCountRecv',\n /** The sent screen round trip time. */\n screenSentRoundTripTime = 'screenSentRoundTripTime',\n /** The transport sent screen round trip time. */\n screenSentTransportRoundTripTime = 'screenSentTransportRoundTripTime',\n /** The screen sent jitter. */\n screenSentJitter = 'screenSentJitter',\n /** The screen audio RTX packets. */\n screenSentRetransmittedPackets = 'screenSentRetransmittedPackets',\n\n // inbound audio,\n audioRecvCodec = 'audioRecvCodec',\n audioRecvBytes = 'audioRecvBytes',\n audioRecvAvgJitterBufferDelay = 'audioRecvAvgJitterBufferDelay',\n audioRecvBitrates = 'audioRecvBitrates',\n audioRecvJitter = 'audioRecvJitter',\n audioRecvRoundTripTime = 'audioRecvRoundTripTime',\n audioRecvPackets = 'audioRecvPackets',\n audioRecvPacketsLost = 'audioRecvPacketsLost', // TODO: remove this.\n audioRecvLostPackets = 'audioRecvLostPackets',\n audioRecvPacketsLossRate = 'audioRecvPacketsLossRate',\n audioRecvRetransmittedPackets = 'audioRecvRetransmittedPackets',\n audioRecvNackCountSent = 'audioRecvNackCountSent',\n audioRecvLevel = 'audioRecvLevel',\n audioRecvTotalSamplesReceived = 'audioRecvTotalSamplesReceived',\n audioRecvConcealedSamples = 'audioRecvConcealedSamples',\n audioRecvConcealmentEvents = 'audioRecvConcealmentEvents',\n audioRecvInsertedSamplesForDeceleration = 'audioRecvInsertedSamplesForDeceleration',\n audioRecvRemovedSamplesForAcceleration = 'audioRecvRemovedSamplesForAcceleration',\n audioRecvEndToEndDelay = 'audioRecvEndToEndDelay',\n // inbound video,\n videoRecvCodec = 'videoRecvCodec',\n videoFirCountSent = 'videoFirCountSent',\n videoPliCountSent = 'videoPliCountSent',\n videoDecodeLatency = 'videoDecodeLatency',\n //'videoFramesDecoded',\n videoRecvFrames = 'videoRecvFrames',\n videoRecvFps = 'videoRecvFps',\n videoRecvAvgJitterBufferDelay = 'videoRecvAvgJitterBufferDelay',\n videoRecvBitrates = 'videoRecvBitrates',\n videoRecvBytes = 'videoRecvBytes',\n videoRecvHeight = 'videoRecvHeight',\n videoRecvJitter = 'videoRecvJitter',\n videoRecvRoundTripTime = 'videoRecvRoundTripTime',\n videoRecvPackets = 'videoRecvPackets',\n videoRecvLostPackets = 'videoRecvLostPackets',\n videoRecvPacketsLost = 'videoRecvPacketsLost', // TODO: remove this.\n videoRecvPacketsLossRate = 'videoRecvPacketsLossRate',\n videoRecvRetransmittedPackets = 'videoRecvRetransmittedPackets',\n videoRecvNackCountSent = 'videoRecvNackCountSent',\n videoRecvWidth = 'videoRecvWidth',\n videoRecvFrameRate = 'videoRecvFrameRate',\n //'videoTotalDecodeTime',\n videoTotalFreezesDuration = 'videoTotalFreezesDuration',\n videoRecvEndToEndDelay = 'videoRecvEndToEndDelay',\n // inbound screen,\n screenRecvCodec = 'screenRecvCodec',\n screenFirCountSent = 'screenFirCountSent',\n screenPliCountSent = 'screenPliCountSent',\n screenDecodeLatency = 'screenDecodeLatency',\n //'screenFramesDecoded',\n screenRecvFrames = 'screenRecvFrames',\n screenRecvFps = 'screenRecvFps',\n screenRecvAvgJitterBufferDelay = 'screenRecvAvgJitterBufferDelay',\n screenRecvBitrates = 'screenRecvBitrates',\n screenRecvBytes = 'screenRecvBytes',\n screenRecvHeight = 'screenRecvHeight',\n screenRecvJitter = 'screenRecvJitter',\n screenRecvRoundTripTime = 'screenRecvRoundTripTime',\n screenRecvPackets = 'screenRecvPackets',\n screenRecvLostPackets = 'screenRecvLostPackets',\n screenRecvPacketsLost = 'screenRecvPacketsLost', // TODO: remove this.\n screenRecvPacketsLossRate = 'screenRecvPacketsLossRate',\n screenRecvRetransmittedPackets = 'screenRecvRetransmittedPackets',\n screenRecvNackCountSent = 'screenRecvNackCountSent',\n screenRecvWidth = 'screenRecvWidth',\n screenRecvFrameRate = 'screenRecvFrameRate',\n //'screenTotalDecodeTime',\n screenTotalFreezesDuration = 'screenTotalFreezesDuration',\n screenRecvEndToEndDelay = 'screenRecvEndToEndDelay',\n /** The transport availableOutgoingBitrate stat. */\n transportSentAvailableOutgoingBitrate = 'transportSentAvailableOutgoingBitrate',\n}\n\n/**\n * The RTC stats collection indexed by {@link RtcStatsMetricNames}.\n *\n * Each {@link RtcStatsMetricNames} record points to an object indexed by\n * `trackId:hostName:codec`, where:\n * - `trackId`: The RTC getStats track identifier.\n * - `hostName`: The remote endpoint IP address or hostname.\n * - `codec`: The track codec.\n */\nexport type RtcStats = Record<RtcStatsMetricNames, Record<string, number | string>>\n\nconst RtcStatsMetrics = Object.keys(RtcStatsMetricNames)\n\nfunction setStats(stats: RtcStats, name: RtcStatsMetricNames, key: string, value?: number | string): void {\n assert(RtcStatsMetrics.includes(name), `Unknown stat name: ${name}`)\n if (value === undefined) return\n if (!stats[name]) {\n stats[name] = {}\n }\n stats[name][key] = value\n}\n\nexport function rtcStatKey({\n pageIndex,\n trackId,\n hostName,\n codec,\n participantName,\n}: {\n pageIndex?: number\n trackId?: string\n hostName?: string\n codec?: string\n participantName?: string\n}): string {\n return [pageIndex ?? '', participantName || '', hostName || 'unknown', codec || '', trackId || ''].join(':')\n}\n\nexport function parseRtStatKey(key: string): {\n pageIndex?: number\n trackId?: string\n hostName: string\n codec?: string\n participantName?: string\n} {\n const [pageIndex, participantName, hostName, codec, trackId] = key.split(':', 5)\n return {\n pageIndex: pageIndex ? parseInt(pageIndex) : undefined,\n trackId: trackId || undefined,\n hostName: hostName || 'unknown',\n codec: codec || undefined,\n participantName: participantName || undefined,\n }\n}\n\n/**\n * Updates the {@link RtcStats} object with the collected track values.\n */\nexport function updateRtcStats(\n stats: RtcStats,\n pageIndex: number,\n trackId: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any,\n signalingHost?: string,\n participantName?: string,\n): void {\n const {\n enabled,\n inboundRtp,\n outboundRtp,\n remoteAddress,\n videoSentActiveEncodings,\n sentMaxBitrate,\n isDisplay,\n codec,\n availableOutgoingBitrate,\n } = value\n const hostName = signalingHost || remoteAddress\n const key = rtcStatKey({\n pageIndex,\n trackId,\n hostName,\n codec,\n participantName,\n })\n //log.log(`updateRtcStats`, {enabled, signalingHost, remoteAddress, isDisplay, key})\n // inbound\n if (inboundRtp) {\n const prefix = inboundRtp.kind === 'video' ? (isDisplay ? 'screen' : 'video') : 'audio'\n setStats(stats, (prefix + 'RecvCodec') as RtcStatsMetricNames, key, codec)\n if (enabled) {\n setStats(stats, (prefix + 'RecvAvgJitterBufferDelay') as RtcStatsMetricNames, key, inboundRtp.jitterBuffer)\n setStats(stats, (prefix + 'RecvBitrates') as RtcStatsMetricNames, key, inboundRtp.bitrate)\n setStats(stats, (prefix + 'RecvBytes') as RtcStatsMetricNames, key, inboundRtp.bytesReceived)\n setStats(stats, (prefix + 'RecvJitter') as RtcStatsMetricNames, key, inboundRtp.jitter)\n setStats(stats, (prefix + 'RecvRoundTripTime') as RtcStatsMetricNames, key, inboundRtp.transportRoundTripTime)\n setStats(stats, (prefix + 'RecvPackets') as RtcStatsMetricNames, key, inboundRtp.packetsReceived)\n setStats(\n stats,\n (prefix + 'RecvRetransmittedPackets') as RtcStatsMetricNames,\n key,\n inboundRtp.retransmittedPacketsReceived,\n )\n // TODO: remove this.\n setStats(stats, (prefix + 'RecvPacketsLost') as RtcStatsMetricNames, key, inboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'RecvPacketsLossRate') as RtcStatsMetricNames, key, inboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'RecvLostPackets') as RtcStatsMetricNames, key, inboundRtp.packetsLost)\n setStats(stats, (prefix + 'RecvNackCountSent') as RtcStatsMetricNames, key, inboundRtp.nackCount)\n setStats(stats, (prefix + 'RecvEndToEndDelay') as RtcStatsMetricNames, key, inboundRtp.endToEndDelay)\n if (inboundRtp.kind === 'audio') {\n ;[\n 'audioLevel',\n 'totalSamplesReceived',\n 'concealedSamples',\n 'concealmentEvents',\n 'insertedSamplesForDeceleration',\n 'removedSamplesForAcceleration',\n ].forEach(name => {\n setStats(\n stats,\n (prefix + 'Recv' + toTitleCase(name.replace('audio', ''))) as RtcStatsMetricNames,\n key,\n inboundRtp[name],\n )\n })\n }\n if (inboundRtp.kind === 'video' && inboundRtp.keyFramesDecoded > 0) {\n //setStats(stats, prefix + 'FramesDecoded', key, inboundRtp.framesDecoded\n setStats(stats, (prefix + 'RecvFrames') as RtcStatsMetricNames, key, inboundRtp.framesReceived)\n setStats(stats, (prefix + 'RecvFps') as RtcStatsMetricNames, key, inboundRtp.framesPerSecond)\n setStats(stats, (prefix + 'RecvHeight') as RtcStatsMetricNames, key, inboundRtp.frameHeight)\n setStats(stats, (prefix + 'RecvWidth') as RtcStatsMetricNames, key, inboundRtp.frameWidth)\n setStats(stats, (prefix + 'RecvFrameRate') as RtcStatsMetricNames, key, inboundRtp.frameRate)\n //setStats(stats, prefix + 'TotalDecodeTime', key, inboundRtp.totalDecodeTime)\n setStats(stats, (prefix + 'FirCountSent') as RtcStatsMetricNames, key, inboundRtp.firCount)\n setStats(stats, (prefix + 'PliCountSent') as RtcStatsMetricNames, key, inboundRtp.pliCount)\n setStats(stats, (prefix + 'DecodeLatency') as RtcStatsMetricNames, key, inboundRtp.decodeLatency)\n setStats(stats, (prefix + 'TotalFreezesDuration') as RtcStatsMetricNames, key, inboundRtp.totalFreezesDuration)\n }\n }\n }\n // outbound\n if (outboundRtp) {\n // log.log('outboundRtp', isDisplay, JSON.stringify(outboundRtp, null, 2));\n const prefix = outboundRtp.kind === 'video' ? (isDisplay ? 'screen' : 'video') : 'audio'\n setStats(stats, (prefix + 'SentCodec') as RtcStatsMetricNames, key, codec)\n if (enabled) {\n setStats(stats, (prefix + 'SentBitrates') as RtcStatsMetricNames, key, outboundRtp.bitrate)\n setStats(\n stats,\n (prefix + 'SentBytes') as RtcStatsMetricNames,\n key,\n outboundRtp.bytesSent + outboundRtp.headerBytesSent,\n )\n setStats(stats, (prefix + 'SentPackets') as RtcStatsMetricNames, key, outboundRtp.packetsSent)\n setStats(stats, (prefix + 'SentPacketsLost') as RtcStatsMetricNames, key, outboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'SentNackCountRecv') as RtcStatsMetricNames, key, outboundRtp.nackCount)\n //setStats(stats, prefix + 'SentPacketsLostCount', key, outboundRtp.packetsLost)\n setStats(stats, (prefix + 'SentRoundTripTime') as RtcStatsMetricNames, key, outboundRtp.roundTripTime)\n setStats(stats, (prefix + 'SentJitter') as RtcStatsMetricNames, key, outboundRtp.jitter)\n setStats(\n stats,\n (prefix + 'SentTransportRoundTripTime') as RtcStatsMetricNames,\n key,\n outboundRtp.transportRoundTripTime,\n )\n setStats(stats, 'transportSentAvailableOutgoingBitrate' as RtcStatsMetricNames, key, availableOutgoingBitrate)\n setStats(stats, (prefix + 'SentMaxBitrate') as RtcStatsMetricNames, key, sentMaxBitrate)\n setStats(\n stats,\n (prefix + 'SentRetransmittedPackets') as RtcStatsMetricNames,\n key,\n outboundRtp.retransmittedPacketsSent,\n )\n if (outboundRtp.kind === 'video') {\n setStats(stats, (prefix + 'SentActiveEncodings') as RtcStatsMetricNames, key, videoSentActiveEncodings)\n setStats(\n stats,\n (prefix + 'QualityLimitationResolutionChanges') as RtcStatsMetricNames,\n key,\n outboundRtp.qualityLimitationResolutionChanges,\n )\n setStats(stats, (prefix + 'QualityLimitationCpu') as RtcStatsMetricNames, key, outboundRtp.qualityLimitationCpu)\n setStats(\n stats,\n (prefix + 'QualityLimitationBandwidth') as RtcStatsMetricNames,\n key,\n outboundRtp.qualityLimitationBandwidth,\n )\n setStats(stats, (prefix + 'SentWidth') as RtcStatsMetricNames, key, outboundRtp.frameWidth)\n setStats(stats, (prefix + 'SentHeight') as RtcStatsMetricNames, key, outboundRtp.frameHeight)\n setStats(stats, (prefix + 'SentFrames') as RtcStatsMetricNames, key, outboundRtp.framesSent)\n setStats(stats, (prefix + 'SentFps') as RtcStatsMetricNames, key, outboundRtp.framesPerSecond)\n setStats(stats, (prefix + 'FirCountReceived') as RtcStatsMetricNames, key, outboundRtp.firCountReceived)\n setStats(stats, (prefix + 'PliCountReceived') as RtcStatsMetricNames, key, outboundRtp.pliCountReceived)\n setStats(stats, (prefix + 'EncodeLatency') as RtcStatsMetricNames, key, outboundRtp.encodeLatency)\n setStats(stats, (prefix + 'SentLatency') as RtcStatsMetricNames, key, outboundRtp.sentLatency)\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"rtcstats.js","sourceRoot":"","sources":["../../src/rtcstats.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'assert'\n\nimport { toTitleCase } from './utils'\n\n/**\n * Page stats metric names.\n */\nexport enum PageStatsNames {\n /** The browser processes CPU usage (per page). */\n cpu = 'cpu',\n /** The browser processes memory usage (per page). */\n memory = 'memory',\n /** The tool nodejs CPU usage. */\n nodeCpu = 'nodeCpu',\n /** The tool nodejs memory usage. */\n nodeMemory = 'nodeMemory',\n /** The system total CPU usage. */\n usedCpu = 'usedCpu',\n /** The system total memory usage. */\n usedMemory = 'usedMemory',\n /** The system total GPU usage. */\n usedGpu = 'usedGpu',\n /** The page CPU usage. */\n pageCpu = 'pageCpu',\n /** The page memory usage. */\n pageMemory = 'pageMemory',\n\n /** The opened pages count. */\n pages = 'pages',\n /** The current opened PeerConnections. */\n peerConnections = 'peerConnections',\n /** The maximum PeerConnections connected duration. */\n peerConnectionConnectionTime = 'peerConnectionConnectionTime',\n /** The maximum PeerConnections disconnection duration. */\n peerConnectionDisconnectionTime = 'peerConnectionDisconnectionTime',\n /** The total created PeerConnections. */\n peerConnectionsCreated = 'peerConnectionsCreated',\n /** The total connected PeerConnections. */\n peerConnectionsConnected = 'peerConnectionsConnected',\n /** The total closed PeerConnections. */\n peerConnectionsClosed = 'peerConnectionsClosed',\n /** The total disconnected PeerConnections. */\n peerConnectionsDisconnected = 'peerConnectionsDisconnected',\n /** The total failed PeerConnections. */\n peerConnectionsFailed = 'peerConnectionsFailed',\n /** The total delay from PeerConnections creation to connection. */\n peerConnectionsDelay = 'peerConnectionsDelay',\n\n /** The page errors count. */\n errors = 'errors',\n /** The page warnings count. */\n warnings = 'warnings',\n\n /** The page total HTTP sent bytes. */\n httpSentBytes = 'httpSentBytes',\n /** The page total HTTP received bytes. */\n httpRecvBytes = 'httpRecvBytes',\n /** The page HTTP receive latency. */\n httpRecvLatency = 'httpRecvLatency',\n\n /** The page total WebSocket sent bytes. */\n wsSentBytes = 'wsSentBytes',\n /** The page total WebSocket received bytes. */\n wsRecvBytes = 'wsRecvBytes',\n /** The page WebSocket receive latency. */\n wsRecvLatency = 'wsRecvLatency',\n\n /** The audio end to end total delay. */\n audioEndToEndDelay = 'audioEndToEndDelay',\n /** The audio start frame delay. */\n audioStartFrameDelay = 'audioStartFrameDelay',\n\n /** The video end to end total delay. */\n videoEndToEndDelay = 'videoEndToEndDelay',\n /** The video start frame delay. */\n videoStartFrameDelay = 'videoStartFrameDelay',\n\n /** The screen end to end total delay. */\n screenEndToEndDelay = 'screenEndToEndDelay',\n /** The screen start frame delay. */\n screenStartFrameDelay = 'screenStartFrameDelay',\n\n cpuPressure = 'cpuPressure',\n\n videoWidth = 'videoWidth',\n videoHeight = 'videoHeight',\n videoBufferedTime = 'videoBufferedTime',\n videoPlayingTime = 'videoPlayingTime',\n videoBufferingTime = 'videoBufferingTime',\n videoBufferingEvents = 'videoBufferingEvents',\n\n /** The throttle upload rate limitation. */\n throttleUpRate = 'throttleUpRate',\n /** The throttle upload delay. */\n throttleUpDelay = 'throttleUpDelay',\n /** The throttle upload packet loss. */\n throttleUpLoss = 'throttleUpLoss',\n /** The throttle upload packet queue. */\n throttleUpQueue = 'throttleUpQueue',\n\n /** The throttle download rate limitation. */\n throttleDownRate = 'throttleDownRate',\n /** The throttle download delay. */\n throttleDownDelay = 'throttleDownDelay',\n /** The throttle download packet loss. */\n throttleDownLoss = 'throttleDownLoss',\n /** The throttle download packet queue. */\n throttleDownQueue = 'throttleDownQueue',\n}\n\n/**\n * RTC metrics collected by the page helper scripts and related to each\n * track object created by PeerConnections.\n */\nexport enum RtcStatsMetricNames {\n /** The sent audio codec. */\n audioSentCodec = 'audioSentCodec',\n /** The total sent audio bytes. */\n audioSentBytes = 'audioSentBytes',\n /** The sent audio packets. */\n audioSentPackets = 'audioSentPackets',\n /** The sent audio bitrates. */\n audioSentBitrates = 'audioSentBitrates',\n /** The send audio lost packets. */\n audioSentPacketsLost = 'audioSentPacketsLost',\n //'audioSentPacketsLostCount',\n /** The total audio NACK received by the sender. */\n audioSentNackCountRecv = 'audioSentNackCountRecv',\n /** The sent audio round trip time. */\n audioSentRoundTripTime = 'audioSentRoundTripTime',\n /** The sent audio jitter. */\n audioSentJitter = 'audioSentJitter',\n /** The audio RTC transport round trip time. */\n audioSentTransportRoundTripTime = 'audioSentTransportRoundTripTime',\n /** The sent audio encoding max bitrate. */\n audioSentMaxBitrate = 'audioSentMaxBitrate',\n /** The sent audio RTX packets. */\n audioSentRetransmittedPackets = 'audioSentRetransmittedPackets',\n\n /** The sent video codec. */\n videoSentCodec = 'videoSentCodec',\n /** The FIR requests received by the video sender. */\n videoFirCountReceived = 'videoFirCountReceived',\n /** The PLI requests received by the video sender. */\n videoPliCountReceived = 'videoPliCountReceived',\n /** The sent video encode latency. */\n videoEncodeLatency = 'videoEncodeLatency',\n /** The sent video latency. */\n videoSentLatency = 'videoSentLatency',\n /** The sent video bandwidth quality limitations. */\n videoQualityLimitationBandwidth = 'videoQualityLimitationBandwidth',\n /** The sent video cpu quality limitations. */\n videoQualityLimitationCpu = 'videoQualityLimitationCpu',\n /** The sent video total resolution changes for quality limitations. */\n videoQualityLimitationResolutionChanges = 'videoQualityLimitationResolutionChanges',\n /** The sent video Simulcast active spatial layers. */\n videoSentActiveEncodings = 'videoSentActiveEncodings',\n /** The sent video bitrates. */\n videoSentBitrates = 'videoSentBitrates',\n /** The sent video bytes. */\n videoSentBytes = 'videoSentBytes',\n /** The sent video packets. */\n videoSentPackets = 'videoSentPackets',\n /** The sent video frames. */\n videoSentFrames = 'videoSentFrames',\n /** The sent video framerate. */\n videoSentFps = 'videoSentFps',\n /** The sent video width. */\n videoSentWidth = 'videoSentWidth',\n /** The sent video height. */\n videoSentHeight = 'videoSentHeight',\n /** The sent video encoding max bitrate. */\n videoSentMaxBitrate = 'videoSentMaxBitrate',\n //'videoSentPackets',\n /** The sent video lost packets. */\n videoSentPacketsLost = 'videoSentPacketsLost',\n //'videoSentPacketsLostCount',\n /** The NACK count received by video sender. */\n videoSentNackCountRecv = 'videoSentNackCountRecv',\n /** The sent video round trip time. */\n videoSentRoundTripTime = 'videoSentRoundTripTime',\n /** The transport send video round trip time. */\n videoSentTransportRoundTripTime = 'videoSentTransportRoundTripTime',\n /** The video sent jitter. */\n videoSentJitter = 'videoSentJitter',\n /** The sent video RTX packets. */\n videoSentRetransmittedPackets = 'videoSentRetransmittedPackets',\n\n /** The sent screen codec. */\n screenSentCodec = 'screenSentCodec',\n /** The received FIR from screen sender. */\n screenFirCountReceived = 'screenFirCountReceived',\n /** The received PLI from screen sender. */\n screenPliCountReceived = 'screenPliCountReceived',\n /** The sent screen encode latency. */\n screenEncodeLatency = 'screenEncodeLatency',\n /** The sent screen latency. */\n screenSentLatency = 'screenSentLatency',\n /** The sent screen bandwidth quality limitation. */\n screenQualityLimitationBandwidth = 'screenQualityLimitationBandwidth',\n /** The sent screen cpu quality limitation. */\n screenQualityLimitationCpu = 'screenQualityLimitationCpu',\n /** The sent screen resolustion changes caused by quality limitation. */\n screenQualityLimitationResolutionChanges = 'screenQualityLimitationResolutionChanges',\n /** The sent screen active Simulcast spatial layers. */\n screenSentActiveEncodings = 'screenSentActiveEncodings',\n /** The sent screen bitrates. */\n screenSentBitrates = 'screenSentBitrates',\n /** The sent screen bytes. */\n screenSentBytes = 'screenSentBytes',\n /** The sent screen packets. */\n screenSentPackets = 'screenSentPackets',\n /** The sent screen frames. */\n screenSentFrames = 'screenSentFrames',\n /** The sent screen framerate. */\n screenSentFps = 'screenSentFps',\n /** The sent screen width. */\n screenSentWidth = 'screenSentWidth',\n /** The sent screen height. */\n screenSentHeight = 'screenSentHeight',\n /** The sent screen encoding max bitrate. */\n screenSentMaxBitrate = 'screenSentMaxBitrate',\n //'screenSentPackets',\n /** The sent screen lost packets. */\n screenSentPacketsLost = 'screenSentPacketsLost',\n //'screenSentPacketsLostCount',\n /** The NACK count received by screen sender. */\n screenSentNackCountRecv = 'screenSentNackCountRecv',\n /** The sent screen round trip time. */\n screenSentRoundTripTime = 'screenSentRoundTripTime',\n /** The transport sent screen round trip time. */\n screenSentTransportRoundTripTime = 'screenSentTransportRoundTripTime',\n /** The screen sent jitter. */\n screenSentJitter = 'screenSentJitter',\n /** The screen audio RTX packets. */\n screenSentRetransmittedPackets = 'screenSentRetransmittedPackets',\n\n // inbound audio,\n audioRecvCodec = 'audioRecvCodec',\n audioRecvBytes = 'audioRecvBytes',\n audioRecvAvgJitterBufferDelay = 'audioRecvAvgJitterBufferDelay',\n audioRecvBitrates = 'audioRecvBitrates',\n audioRecvJitter = 'audioRecvJitter',\n audioRecvRoundTripTime = 'audioRecvRoundTripTime',\n audioRecvPackets = 'audioRecvPackets',\n audioRecvPacketsLost = 'audioRecvPacketsLost', // TODO: remove this.\n audioRecvLostPackets = 'audioRecvLostPackets',\n audioRecvPacketsLossRate = 'audioRecvPacketsLossRate',\n audioRecvRetransmittedPackets = 'audioRecvRetransmittedPackets',\n audioRecvNackCountSent = 'audioRecvNackCountSent',\n audioRecvLevel = 'audioRecvLevel',\n audioRecvTotalSamplesReceived = 'audioRecvTotalSamplesReceived',\n audioRecvConcealedSamples = 'audioRecvConcealedSamples',\n audioRecvConcealmentEvents = 'audioRecvConcealmentEvents',\n audioRecvInsertedSamplesForDeceleration = 'audioRecvInsertedSamplesForDeceleration',\n audioRecvRemovedSamplesForAcceleration = 'audioRecvRemovedSamplesForAcceleration',\n audioRecvEndToEndDelay = 'audioRecvEndToEndDelay',\n // inbound video,\n videoRecvCodec = 'videoRecvCodec',\n videoFirCountSent = 'videoFirCountSent',\n videoPliCountSent = 'videoPliCountSent',\n videoDecodeLatency = 'videoDecodeLatency',\n videoFramesDecoded = 'videoFramesDecoded',\n videoFramesDropped = 'videoFramesDropped',\n videoRecvFrames = 'videoRecvFrames',\n videoRecvFps = 'videoRecvFps',\n videoRecvAvgJitterBufferDelay = 'videoRecvAvgJitterBufferDelay',\n videoRecvBitrates = 'videoRecvBitrates',\n videoRecvBytes = 'videoRecvBytes',\n videoRecvHeight = 'videoRecvHeight',\n videoRecvJitter = 'videoRecvJitter',\n videoRecvRoundTripTime = 'videoRecvRoundTripTime',\n videoRecvPackets = 'videoRecvPackets',\n videoRecvLostPackets = 'videoRecvLostPackets',\n videoRecvPacketsLost = 'videoRecvPacketsLost', // TODO: remove this.\n videoRecvPacketsLossRate = 'videoRecvPacketsLossRate',\n videoRecvRetransmittedPackets = 'videoRecvRetransmittedPackets',\n videoRecvNackCountSent = 'videoRecvNackCountSent',\n videoRecvWidth = 'videoRecvWidth',\n videoRecvFrameRate = 'videoRecvFrameRate',\n //'videoTotalDecodeTime',\n videoTotalFreezesDuration = 'videoTotalFreezesDuration',\n videoRecvEndToEndDelay = 'videoRecvEndToEndDelay',\n // inbound screen,\n screenRecvCodec = 'screenRecvCodec',\n screenFirCountSent = 'screenFirCountSent',\n screenPliCountSent = 'screenPliCountSent',\n screenDecodeLatency = 'screenDecodeLatency',\n screenFramesDecoded = 'screenFramesDecoded',\n screenFramesDropped = 'screenFramesDropped',\n screenRecvFrames = 'screenRecvFrames',\n screenRecvFps = 'screenRecvFps',\n screenRecvAvgJitterBufferDelay = 'screenRecvAvgJitterBufferDelay',\n screenRecvBitrates = 'screenRecvBitrates',\n screenRecvBytes = 'screenRecvBytes',\n screenRecvHeight = 'screenRecvHeight',\n screenRecvJitter = 'screenRecvJitter',\n screenRecvRoundTripTime = 'screenRecvRoundTripTime',\n screenRecvPackets = 'screenRecvPackets',\n screenRecvLostPackets = 'screenRecvLostPackets',\n screenRecvPacketsLost = 'screenRecvPacketsLost', // TODO: remove this.\n screenRecvPacketsLossRate = 'screenRecvPacketsLossRate',\n screenRecvRetransmittedPackets = 'screenRecvRetransmittedPackets',\n screenRecvNackCountSent = 'screenRecvNackCountSent',\n screenRecvWidth = 'screenRecvWidth',\n screenRecvFrameRate = 'screenRecvFrameRate',\n //'screenTotalDecodeTime',\n screenTotalFreezesDuration = 'screenTotalFreezesDuration',\n screenRecvEndToEndDelay = 'screenRecvEndToEndDelay',\n /** The transport availableOutgoingBitrate stat. */\n transportSentAvailableOutgoingBitrate = 'transportSentAvailableOutgoingBitrate',\n}\n\n/**\n * The RTC stats collection indexed by {@link RtcStatsMetricNames}.\n *\n * Each {@link RtcStatsMetricNames} record points to an object indexed by\n * `trackId:hostName:codec`, where:\n * - `trackId`: The RTC getStats track identifier.\n * - `hostName`: The remote endpoint IP address or hostname.\n * - `codec`: The track codec.\n */\nexport type RtcStats = Record<RtcStatsMetricNames, Record<string, number | string>>\n\nconst RtcStatsMetrics = Object.keys(RtcStatsMetricNames)\n\nfunction setStats(stats: RtcStats, name: RtcStatsMetricNames, key: string, value?: number | string): void {\n assert(RtcStatsMetrics.includes(name), `Unknown stat name: ${name}`)\n if (value === undefined) return\n if (!stats[name]) {\n stats[name] = {}\n }\n stats[name][key] = value\n}\n\nexport function rtcStatKey({\n pageIndex,\n trackId,\n hostName,\n codec,\n participantName,\n}: {\n pageIndex?: number\n trackId?: string\n hostName?: string\n codec?: string\n participantName?: string\n}): string {\n return [pageIndex ?? '', participantName || '', hostName || 'unknown', codec || '', trackId || ''].join(':')\n}\n\nexport function parseRtStatKey(key: string): {\n pageIndex?: number\n trackId?: string\n hostName: string\n codec?: string\n participantName?: string\n} {\n const [pageIndex, participantName, hostName, codec, trackId] = key.split(':', 5)\n return {\n pageIndex: pageIndex ? parseInt(pageIndex) : undefined,\n trackId: trackId || undefined,\n hostName: hostName || 'unknown',\n codec: codec || undefined,\n participantName: participantName || undefined,\n }\n}\n\n/**\n * Updates the {@link RtcStats} object with the collected track values.\n */\nexport function updateRtcStats(\n stats: RtcStats,\n pageIndex: number,\n trackId: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: any,\n signalingHost?: string,\n participantName?: string,\n): void {\n const {\n enabled,\n inboundRtp,\n outboundRtp,\n remoteAddress,\n videoSentActiveEncodings,\n sentMaxBitrate,\n isDisplay,\n codec,\n availableOutgoingBitrate,\n } = value\n const hostName = signalingHost || remoteAddress\n const key = rtcStatKey({\n pageIndex,\n trackId,\n hostName,\n codec,\n participantName,\n })\n //log.log(`updateRtcStats`, {enabled, signalingHost, remoteAddress, isDisplay, key})\n // inbound\n if (inboundRtp) {\n const prefix = inboundRtp.kind === 'video' ? (isDisplay ? 'screen' : 'video') : 'audio'\n setStats(stats, (prefix + 'RecvCodec') as RtcStatsMetricNames, key, codec)\n if (enabled) {\n setStats(stats, (prefix + 'RecvAvgJitterBufferDelay') as RtcStatsMetricNames, key, inboundRtp.jitterBuffer)\n setStats(stats, (prefix + 'RecvBitrates') as RtcStatsMetricNames, key, inboundRtp.bitrate)\n setStats(stats, (prefix + 'RecvBytes') as RtcStatsMetricNames, key, inboundRtp.bytesReceived)\n setStats(stats, (prefix + 'RecvJitter') as RtcStatsMetricNames, key, inboundRtp.jitter)\n setStats(stats, (prefix + 'RecvRoundTripTime') as RtcStatsMetricNames, key, inboundRtp.transportRoundTripTime)\n setStats(stats, (prefix + 'RecvPackets') as RtcStatsMetricNames, key, inboundRtp.packetsReceived)\n setStats(\n stats,\n (prefix + 'RecvRetransmittedPackets') as RtcStatsMetricNames,\n key,\n inboundRtp.retransmittedPacketsReceived,\n )\n // TODO: remove this.\n setStats(stats, (prefix + 'RecvPacketsLost') as RtcStatsMetricNames, key, inboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'RecvPacketsLossRate') as RtcStatsMetricNames, key, inboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'RecvLostPackets') as RtcStatsMetricNames, key, inboundRtp.packetsLost)\n setStats(stats, (prefix + 'RecvNackCountSent') as RtcStatsMetricNames, key, inboundRtp.nackCount)\n setStats(stats, (prefix + 'RecvEndToEndDelay') as RtcStatsMetricNames, key, inboundRtp.endToEndDelay)\n if (inboundRtp.kind === 'audio') {\n ;[\n 'audioLevel',\n 'totalSamplesReceived',\n 'concealedSamples',\n 'concealmentEvents',\n 'insertedSamplesForDeceleration',\n 'removedSamplesForAcceleration',\n ].forEach(name => {\n setStats(\n stats,\n (prefix + 'Recv' + toTitleCase(name.replace('audio', ''))) as RtcStatsMetricNames,\n key,\n inboundRtp[name],\n )\n })\n }\n if (inboundRtp.kind === 'video' && inboundRtp.keyFramesDecoded > 0) {\n setStats(stats, (prefix + 'FramesDecoded') as RtcStatsMetricNames, key, inboundRtp.framesDecoded)\n setStats(stats, (prefix + 'FramesDropped') as RtcStatsMetricNames, key, inboundRtp.framesDropped)\n setStats(stats, (prefix + 'RecvFrames') as RtcStatsMetricNames, key, inboundRtp.framesReceived)\n setStats(stats, (prefix + 'RecvFps') as RtcStatsMetricNames, key, inboundRtp.framesPerSecond)\n setStats(stats, (prefix + 'RecvHeight') as RtcStatsMetricNames, key, inboundRtp.frameHeight)\n setStats(stats, (prefix + 'RecvWidth') as RtcStatsMetricNames, key, inboundRtp.frameWidth)\n setStats(stats, (prefix + 'RecvFrameRate') as RtcStatsMetricNames, key, inboundRtp.frameRate)\n //setStats(stats, prefix + 'TotalDecodeTime', key, inboundRtp.totalDecodeTime)\n setStats(stats, (prefix + 'FirCountSent') as RtcStatsMetricNames, key, inboundRtp.firCount)\n setStats(stats, (prefix + 'PliCountSent') as RtcStatsMetricNames, key, inboundRtp.pliCount)\n setStats(stats, (prefix + 'DecodeLatency') as RtcStatsMetricNames, key, inboundRtp.decodeLatency)\n setStats(stats, (prefix + 'TotalFreezesDuration') as RtcStatsMetricNames, key, inboundRtp.totalFreezesDuration)\n }\n }\n }\n // outbound\n if (outboundRtp) {\n // log.log('outboundRtp', isDisplay, JSON.stringify(outboundRtp, null, 2));\n const prefix = outboundRtp.kind === 'video' ? (isDisplay ? 'screen' : 'video') : 'audio'\n setStats(stats, (prefix + 'SentCodec') as RtcStatsMetricNames, key, codec)\n if (enabled) {\n setStats(stats, (prefix + 'SentBitrates') as RtcStatsMetricNames, key, outboundRtp.bitrate)\n setStats(\n stats,\n (prefix + 'SentBytes') as RtcStatsMetricNames,\n key,\n outboundRtp.bytesSent + outboundRtp.headerBytesSent,\n )\n setStats(stats, (prefix + 'SentPackets') as RtcStatsMetricNames, key, outboundRtp.packetsSent)\n setStats(stats, (prefix + 'SentPacketsLost') as RtcStatsMetricNames, key, outboundRtp.packetsLossRate)\n setStats(stats, (prefix + 'SentNackCountRecv') as RtcStatsMetricNames, key, outboundRtp.nackCount)\n //setStats(stats, prefix + 'SentPacketsLostCount', key, outboundRtp.packetsLost)\n setStats(stats, (prefix + 'SentRoundTripTime') as RtcStatsMetricNames, key, outboundRtp.roundTripTime)\n setStats(stats, (prefix + 'SentJitter') as RtcStatsMetricNames, key, outboundRtp.jitter)\n setStats(\n stats,\n (prefix + 'SentTransportRoundTripTime') as RtcStatsMetricNames,\n key,\n outboundRtp.transportRoundTripTime,\n )\n setStats(stats, 'transportSentAvailableOutgoingBitrate' as RtcStatsMetricNames, key, availableOutgoingBitrate)\n setStats(stats, (prefix + 'SentMaxBitrate') as RtcStatsMetricNames, key, sentMaxBitrate)\n setStats(\n stats,\n (prefix + 'SentRetransmittedPackets') as RtcStatsMetricNames,\n key,\n outboundRtp.retransmittedPacketsSent,\n )\n if (outboundRtp.kind === 'video') {\n setStats(stats, (prefix + 'SentActiveEncodings') as RtcStatsMetricNames, key, videoSentActiveEncodings)\n setStats(\n stats,\n (prefix + 'QualityLimitationResolutionChanges') as RtcStatsMetricNames,\n key,\n outboundRtp.qualityLimitationResolutionChanges,\n )\n setStats(stats, (prefix + 'QualityLimitationCpu') as RtcStatsMetricNames, key, outboundRtp.qualityLimitationCpu)\n setStats(\n stats,\n (prefix + 'QualityLimitationBandwidth') as RtcStatsMetricNames,\n key,\n outboundRtp.qualityLimitationBandwidth,\n )\n setStats(stats, (prefix + 'SentWidth') as RtcStatsMetricNames, key, outboundRtp.frameWidth)\n setStats(stats, (prefix + 'SentHeight') as RtcStatsMetricNames, key, outboundRtp.frameHeight)\n setStats(stats, (prefix + 'SentFrames') as RtcStatsMetricNames, key, outboundRtp.framesSent)\n setStats(stats, (prefix + 'SentFps') as RtcStatsMetricNames, key, outboundRtp.framesPerSecond)\n setStats(stats, (prefix + 'FirCountReceived') as RtcStatsMetricNames, key, outboundRtp.firCountReceived)\n setStats(stats, (prefix + 'PliCountReceived') as RtcStatsMetricNames, key, outboundRtp.pliCountReceived)\n setStats(stats, (prefix + 'EncodeLatency') as RtcStatsMetricNames, key, outboundRtp.encodeLatency)\n setStats(stats, (prefix + 'SentLatency') as RtcStatsMetricNames, key, outboundRtp.sentLatency)\n }\n }\n }\n}\n"]}
@@ -119,6 +119,7 @@ export declare function twoParticipantsWithRateLossDelay(id: string, { rate, los
119
119
  pageLogFilter: string;
120
120
  pageLogPath: string;
121
121
  enableBrowserLogging: string;
122
+ enableRtpDump: string;
122
123
  userAgent: string;
123
124
  scriptPath: string;
124
125
  scriptParams: string;
@@ -79,6 +79,7 @@ export interface SessionParams {
79
79
  useFakeMedia: boolean;
80
80
  enableGpu: string;
81
81
  enableBrowserLogging: string;
82
+ enableRtpDump: string;
82
83
  startTimestamp: number;
83
84
  sessions: number;
84
85
  tabsPerSession: number;
@@ -146,6 +147,7 @@ export declare class Session extends EventEmitter {
146
147
  private readonly useFakeMedia;
147
148
  private readonly enableGpu;
148
149
  private readonly enableBrowserLogging;
150
+ private readonly enableRtpDump;
149
151
  private readonly startTimestamp;
150
152
  private readonly sessions;
151
153
  private readonly tabsPerSession;
@@ -246,7 +248,7 @@ export declare class Session extends EventEmitter {
246
248
  pageErrors: number;
247
249
  private screensharePage?;
248
250
  private static readonly jsonFetchCache;
249
- constructor({ chromiumUrl, chromiumPath, chromiumFieldTrials, windowWidth, windowHeight, deviceScaleFactor, display, url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }: SessionParams);
251
+ constructor({ chromiumUrl, chromiumPath, chromiumFieldTrials, windowWidth, windowHeight, deviceScaleFactor, display, url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, enableRtpDump, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }: SessionParams);
250
252
  /**
251
253
  * Returns the chromium browser launch args
252
254
  * @return the args list
@@ -52,6 +52,7 @@ class Session extends events_1.default {
52
52
  useFakeMedia;
53
53
  enableGpu;
54
54
  enableBrowserLogging;
55
+ enableRtpDump;
55
56
  startTimestamp;
56
57
  sessions;
57
58
  tabsPerSession;
@@ -154,7 +155,7 @@ class Session extends events_1.default {
154
155
  });
155
156
  constructor({ chromiumUrl, chromiumPath, chromiumFieldTrials, windowWidth, windowHeight, deviceScaleFactor, display,
156
157
  /* audioRedForOpus, */
157
- url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
158
+ url, urlQuery, customUrlHandler, customUrlHandlerFn, mediaPath, videoWidth, videoHeight, videoFramerate, useFakeMedia, enableGpu, enableBrowserLogging, enableRtpDump, startTimestamp, sessions, tabsPerSession, spawnPeriod, statsInterval, disabledVideoCodecs, localStorage, sessionStorage, clearCookies, scriptPath, showPageLog, pageLogFilter, pageLogPath, userAgent, id, throttleIndex, useBrowserThrottling, evaluateAfter, exposedFunctions, scriptParams, blockedUrls, extraHeaders, responseModifiers, downloadResponses, extraCSS, cookies, overridePermissions, hardwareConcurrency, debuggingPort, debuggingAddress, randomAudioPeriod, maxVideoDecoders, maxVideoDecodersRange, incognito, serverPort, serverSecret, serverUseHttps, emulateCpuThrottling, }) {
158
159
  super();
159
160
  log.debug('constructor', { id });
160
161
  this.id = id;
@@ -184,6 +185,7 @@ class Session extends events_1.default {
184
185
  this.useFakeMedia = useFakeMedia;
185
186
  this.enableGpu = enableGpu;
186
187
  this.enableBrowserLogging = (0, utils_1.enabledForSession)(this.id, enableBrowserLogging);
188
+ this.enableRtpDump = (0, utils_1.enabledForSession)(this.id, enableRtpDump);
187
189
  this.startTimestamp = startTimestamp || Date.now();
188
190
  this.sessions = sessions || 1;
189
191
  this.tabsPerSession = tabsPerSession || 1;
@@ -344,12 +346,15 @@ class Session extends events_1.default {
344
346
  `--window-size=${this.windowWidth},${this.windowHeight}`,
345
347
  ];
346
348
  let fieldTrials = this.chromiumFieldTrials || '';
347
- if (this.enableBrowserLogging && this.pageLogPath) {
349
+ if (this.pageLogPath && this.enableBrowserLogging) {
348
350
  const pageLogDir = path_1.default.dirname(this.pageLogPath);
349
351
  const eventLogPath = path_1.default.resolve(pageLogDir, `webrtc-event-logging-${this.id}`);
350
352
  fs_1.default.mkdirSync(eventLogPath, { recursive: true });
351
353
  args.push('--enable-logging', '--vmodule=*/webrtc/*=5', '--v=0', `--webrtc-event-logging=${eventLogPath}`);
352
354
  fieldTrials = 'WebRTC-RtcEventLogNewFormat/Disabled/' + fieldTrials;
355
+ if (this.enableRtpDump) {
356
+ fieldTrials = 'WebRTC-Debugging-RtpDump/Enabled/' + fieldTrials;
357
+ }
353
358
  env.CHROME_LOG_FILE = path_1.default.resolve(pageLogDir, `chrome-${this.id}.log`);
354
359
  }
355
360
  if (this.maxVideoDecoders !== -1 && (0, utils_1.enabledForSession)(this.id, this.maxVideoDecodersRange)) {
@@ -1112,6 +1117,26 @@ Object.defineProperty(window.screen.orientation, 'type', { value: 'landscape-pri
1112
1117
  throttler_1.throttleNotifier.on('change', onThrottleChange);
1113
1118
  page.once('close', () => throttler_1.throttleNotifier.off('change', onThrottleChange));
1114
1119
  }
1120
+ if (this.pageLogPath && this.enableRtpDump) {
1121
+ page.once('close', async () => {
1122
+ const dirPath = path_1.default.dirname(this.pageLogPath);
1123
+ const logFilePath = path_1.default.join(dirPath, `chrome-${this.id}.log`);
1124
+ if (fs_1.default.existsSync(logFilePath)) {
1125
+ const pcapFilePath = path_1.default.join(dirPath, `chrome-${this.id}.pcap`);
1126
+ try {
1127
+ await (0, utils_1.runShellCommand)(`\
1128
+ grep RTP_DUMP ${logFilePath} | text2pcap -D -u 1000,2000 -t %H:%M:%S.%f - ${pcapFilePath};
1129
+ grep -v RTP_DUMP ${logFilePath} > ${logFilePath}.tmp;
1130
+ mv ${logFilePath}.tmp ${logFilePath};
1131
+ `);
1132
+ log.info(`rtp dump saved to: ${pcapFilePath}`);
1133
+ }
1134
+ catch (err) {
1135
+ log.error(`error converting rtp dump to pcap: ${err.stack}`);
1136
+ }
1137
+ }
1138
+ });
1139
+ }
1115
1140
  log.debug(`Page ${index + 1} "${url}" loaded in ${(Date.now() - pageLoadTime) / 1000}s`);
1116
1141
  for (let i = 0; i < this.evaluateAfter.length; i++) {
1117
1142
  await page.evaluate(