From fcd98b6a4d3fc613eaeb4a8b0387669e2e8d6bd5 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 16:30:01 +0800 Subject: [PATCH 01/81] Add queue prewarm candidate selection --- frontend/prewarm-next.js | 37 +++++++++++++++++++++++++++++++++++ frontend/prewarm-next.test.js | 26 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 frontend/prewarm-next.js create mode 100644 frontend/prewarm-next.test.js diff --git a/frontend/prewarm-next.js b/frontend/prewarm-next.js new file mode 100644 index 0000000..ec56f35 --- /dev/null +++ b/frontend/prewarm-next.js @@ -0,0 +1,37 @@ +/* Pure queue candidate selection for stream prewarming. */ +(function (root, factory) { + if (typeof module === 'object' && module.exports) module.exports = factory(); + else root.PrewarmNext = factory(); +})(typeof globalThis !== 'undefined' ? globalThis : this, function () { + 'use strict'; + + function candidates(queue, index, state = {}, n = 2, known = {}) { + if (!Array.isArray(queue) || !queue.length || !Number.isInteger(index) || index < 0 || index >= queue.length) return []; + if (state.loopOne) return []; + const count = Math.max(0, Math.floor(Number(n) || 0)); + if (!count) return []; + const repeatAll = state.repeatMode === 'all' || state.repeatAll === true; + const offline = new Set(known.offline || []); + const serverCached = new Set(known.serverCached || []); + const current = queue[index]; + const currentId = typeof current === 'string' ? current : current && current.id; + const seen = new Set(currentId ? [currentId] : []); + const ids = []; + for (let step = 1; step < queue.length + (repeatAll ? 1 : 0) && ids.length < count; step++) { + let at = index + step; + if (at >= queue.length) { + if (!repeatAll) break; + at %= queue.length; + } + const item = queue[at]; + const id = typeof item === 'string' ? item : item && item.id; + if (!id || seen.has(id)) continue; + seen.add(id); + if (offline.has(id) || serverCached.has(id) || (item && item.serverCached)) continue; + ids.push(id); + } + return ids; + } + + return { candidates }; +}); diff --git a/frontend/prewarm-next.test.js b/frontend/prewarm-next.test.js new file mode 100644 index 0000000..9a4f467 --- /dev/null +++ b/frontend/prewarm-next.test.js @@ -0,0 +1,26 @@ +'use strict'; +const test = require('node:test'); +const assert = require('node:assert/strict'); +const { candidates } = require('./prewarm-next.js'); + +const q = ['a', 'b', 'c', 'd'].map(id => ({ id })); + +test('returns the next n queue ids in existing order', () => { + assert.deepEqual(candidates(q, 0, {}, 2), ['b', 'c']); +}); +test('repeat all wraps and does not duplicate ids', () => { + assert.deepEqual(candidates(q, 3, { repeatMode: 'all' }, 2), ['a', 'b']); + assert.deepEqual(candidates([{ id: 'x' }, { id: 'x' }], 0, { repeatMode: 'all' }, 3), []); +}); +test('repeat off stops at the end and loop one has no candidates', () => { + assert.deepEqual(candidates(q, 3, {}, 2), []); + assert.deepEqual(candidates(q, 0, { loopOne: true, repeatMode: 'all' }, 2), []); +}); +test('skips offline and known server cached ids and deduplicates', () => { + assert.deepEqual(candidates(q, 0, {}, 3, { offline: ['b'], serverCached: ['c'] }), ['d']); + assert.deepEqual(candidates([{ id: 'a' }, { id: 'b', serverCached: true }, { id: 'c' }], 0, {}, 2), ['c']); +}); +test('shuffle follows the queue order selected before advance', () => { + const shuffled = ['a', 'd', 'b', 'c'].map(id => ({ id })); + assert.deepEqual(candidates(shuffled, 0, { shuffle: true }, 2), ['d', 'b']); +}); From d65b9e032af09b1b7355c58575da17e952228ede Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 16:30:15 +0800 Subject: [PATCH 02/81] Prewarm upcoming queue streams --- frontend/app.js | 15 +++++++++++++-- frontend/index.html | 1 + frontend/sw.js | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/app.js b/frontend/app.js index 8da49bd..c174b25 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -623,8 +623,9 @@ const API = { // Pre-resolve streams for videos the user is likely to play next (server // /api/streams/warm). Each id is warmed at most once per 20 min per tab. const warmedAt = new Map(); +const knownServerCachedIds = new Set(); function warmStreams(ids) { - if (!WEB || navigator.onLine === false) return; + if (!WEB || navigator.onLine === false || navigator.connection?.saveData) return; const now = Date.now(); for (const id of ids) { if (!id || !/^[A-Za-z0-9_-]{11}$/.test(id) || cachedIds.has(id)) continue; @@ -634,6 +635,14 @@ function warmStreams(ids) { } } +function warmNextQueue() { + if (!window.PrewarmNext || queueIndex < 0) return; + warmStreams(window.PrewarmNext.candidates(queue, queueIndex, data.settings, 2, { + offline: cachedIds, + serverCached: knownServerCachedIds, + })); +} + // Resolve a native file path to a URL the WebView can load (Tauri asset // protocol). Returns null on shells without it. function toAssetUrl(path) { @@ -2332,6 +2341,7 @@ const Player = { if (seq !== this._loadSeq) return; // a newer load took over meanwhile if (!res || !res.ok) throw new Error(res?.error || 'Could not load streams'); current = res.data; + if (current.serverCached && current.meta?.id) knownServerCachedIds.add(current.meta.id); // Merge richer metadata we may already have from the list card. current.meta = { ...videoObj, ...current.meta }; @@ -3014,7 +3024,7 @@ function wirePlayerEvents() { perfMeasure('ytp:tap-to-play', 'ytp:tap'); try { performance.clearMarks('ytp:tap'); } catch { /* ignore */ } } - if (Array.isArray(queue) && queueIndex >= 0) warmStreams(queue.slice(queueIndex + 1, queueIndex + 3).map((x) => x && x.id)); + warmNextQueue(); showSpinner(false); Player.clearBufferGrace(); if (Player.secondary && !el.paused && Player.secondary.paused) { @@ -8043,6 +8053,7 @@ function playFromList(list, index, source = '', { playFull = false } = {}) { unshuffledQueue = null; // Play-in-full keeps the list order — a service set plays as arranged. if (data.settings.shuffle && !playFull) applyShuffle(); + warmNextQueue(); Player.loadVideo(queue[queueIndex]); renderUpNext(); } diff --git a/frontend/index.html b/frontend/index.html index b4de34a..fa61d53 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -693,6 +693,7 @@ + diff --git a/frontend/sw.js b/frontend/sw.js index 7cfec85..7d584dc 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -124,6 +124,7 @@ const SHELL = [ '/piano.js', '/setlist-import.js', '/car-mode.js', + '/prewarm-next.js', '/car-mode.css', '/lower-third.css', '/settings-sections.css', From ad85cb6eb4e960f6b0816a188fed01a5d9c4301e Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 22:50:02 +0800 Subject: [PATCH 03/81] Plan phase 1: Add per-file hashes and a backward-compatible manifest --- plans/phase1-plan.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 plans/phase1-plan.md diff --git a/plans/phase1-plan.md b/plans/phase1-plan.md new file mode 100644 index 0000000..55b03e2 --- /dev/null +++ b/plans/phase1-plan.md @@ -0,0 +1,39 @@ +# Phase 1 — per-file asset hashes and server manifest + +1. Add tests first in `server/asset-manifest.test.js`, deliberately extend + `server/static-delivery.test.js` and `frontend/shell-consistency.test.js`. +2. Describe the existing shell in `frontend/assets.json`: ordered file groups, + contract 1, eager core/settings/playlist/service-mode/lyrics-editor. Preserve + index script order and both service-worker sources byte-for-byte. +3. Add importable `server/asset-manifest.js`; integrate boot-time recursive + hashing, stamped index, manifest endpoint, per-file headers and rollback into + `server/server.js`. Register module tests in `server/package.json`. +4. Stamp safe HTML resource URLs (CSS/JS, font preloads, webmanifest). Retain + plain JS-created worker/import URLs: introducing a new helper would require + modifying the unchanged worker's shell or frontend callers. Inventory these + exceptions explicitly in the report. Hash every recursively served file, + including files outside the shell, so the banner never misses a change. +5. Extract `b77938a` using `perf/make-shell-fixture.sh` with an explicitly + computed expected tag (never query production). Add `perf/migration.mjs` + and instructions to `perf/README.md`; test old-client Refresh UI, a single + banner, complete new cache, no loop, offline reload, and legacy URL bodies + on Chromium and WebKit. Run reduced LTE cold/warm/offline baselines. +6. Review against master plan §3.1/§6b; commit `plans/phase1-report.md` (≤350 + words) with commit IDs, measurements, exceptions and iPhone checks; write + DONE01 to the queue signal only after verification succeeds. + +Hash self-reference: stamp resource URLs first; hash a canonical index with its +build-meta placeholder intact to derive the manifest build tag. Stamp that tag +and expose the actual final index byte hash. Canonical tag computation normalizes +only this derived index field, avoiding a cryptographic fixed-point requirement. +SW response hashing must likewise describe injected bytes rather than raw source. + +Rollback: `ASSET_HASHING=0` restores the existing recursive build tag and legacy +single-tag CSS/JS stamping/header behavior. Default ON; test both modes. +Risks: old-worker ignoreSearch, stalled installation, mutable stale URLs, +recursive paths, derived HTML/SW hashes, shared iOS cache/audio quota. + +Acceptance: both unit suites green after each implementation commit; no weakened +characterization tests; migration passes in both browsers; reduced baseline cold, +warm and offline boot succeeds with no first-paint regression. Phase 1 still +fetches the whole shell on update; <30 KB CSS-only updates belong to Phase 2. From 6cb00d5073931325b15ec5b773bf15dc2b53816e Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 22:57:41 +0800 Subject: [PATCH 04/81] Add per-file asset hashes and a rollback-compatible server manifest --- frontend/assets.json | 254 +++++++++++++++++++++++++++++ frontend/shell-consistency.test.js | 22 +++ plans/phase1-plan.md | 3 +- server/asset-manifest.js | 87 ++++++++++ server/asset-manifest.test.js | 62 +++++++ server/package.json | 2 +- server/server.js | 100 ++++-------- server/static-delivery.test.js | 61 ++++++- 8 files changed, 509 insertions(+), 82 deletions(-) create mode 100644 frontend/assets.json create mode 100644 server/asset-manifest.js create mode 100644 server/asset-manifest.test.js diff --git a/frontend/assets.json b/frontend/assets.json new file mode 100644 index 0000000..0e1c9f3 --- /dev/null +++ b/frontend/assets.json @@ -0,0 +1,254 @@ +{ + "groups": { + "core": { + "contract": 1, + "eager": true, + "files": [ + "/index.html", + "/styles.css", + "/service-ui.css", + "/refresh.css", + "/recommendations.css", + "/flag-ui.js", + "/async-guard.js", + "/visible-timer.js", + "/sw-update.js", + "/fingerprint.js", + "/opfs.js", + "/opfs-worker.js", + "/lyrics-core.js", + "/lyrics-display.js", + "/sha256.js", + "/resume-core.js", + "/loudness-wasm.js", + "/loudness.js", + "/sha256-wasm.js", + "/settings-sections.js", + "/related-videos.js", + "/related-videos.css", + "/audio-continuity.js", + "/fullscreen-orientation.js", + "/fullscreen-orientation.css", + "/download-actions.js", + "/download-actions.css", + "/download-errors.js", + "/downloads.js", + "/downloads-page.js", + "/offline-pages.css", + "/saved-page.js", + "/server-backfill.js", + "/saved-page.css", + "/prewarm-next.js", + "/settings-sections.css", + "/app.js", + "/manifest.webmanifest", + "/icons/icon-192.png", + "/icons/icon-512.png", + "/fonts/fonts.css", + "/fonts/BricolageGrotesque-latin-ext.woff2", + "/fonts/BricolageGrotesque-latin.woff2", + "/fonts/HankenGrotesk-latin-ext.woff2", + "/fonts/HankenGrotesk-latin.woff2", + "/fonts/JetBrainsMono-latin-ext.woff2", + "/fonts/JetBrainsMono-latin.woff2" + ] + }, + "layout:glass": { + "contract": 1, + "eager": false, + "files": [ + "/theme-glass.css" + ] + }, + "layout:classic": { + "contract": 1, + "eager": false, + "files": [ + "/theme-classic.css" + ] + }, + "layout:glass-controls": { + "contract": 1, + "eager": false, + "files": [ + "/theme-glass-controls.css", + "/glass-controls.js" + ] + }, + "layout:glass-panel": { + "contract": 1, + "eager": false, + "files": [ + "/theme-glass-panel.css", + "/glass-panel-layout.js" + ] + }, + "layout:bento-hub": { + "contract": 1, + "eager": false, + "files": [ + "/theme-bento-hub.css", + "/bento-hub.js", + "/fonts/PlusJakartaSans-latin.woff2", + "/fonts/PlusJakartaSans-latin-ext.woff2" + ] + }, + "layout:f7-swipe": { + "contract": 1, + "eager": false, + "files": [ + "/theme-f7.css", + "/f7-layout.js", + "/vendor/framework7-swipe.min.js" + ] + }, + "feature:piano": { + "contract": 1, + "eager": false, + "files": [ + "/piano-core.js", + "/piano.js", + "/piano-engine.mjs" + ] + }, + "feature:midi": { + "contract": 1, + "eager": false, + "files": [ + "/midi.js" + ] + }, + "feature:party-dj": { + "contract": 1, + "eager": false, + "files": [ + "/party-dj.js" + ] + }, + "feature:lyrics-window": { + "contract": 1, + "eager": false, + "files": [ + "/lyrics-window.js" + ] + }, + "feature:lower-third": { + "contract": 1, + "eager": false, + "files": [ + "/lower-third.js", + "/lower-third.css" + ] + }, + "feature:vocal-reducer": { + "contract": 1, + "eager": false, + "files": [ + "/vocal-reducer.js" + ] + }, + "feature:eq-core": { + "contract": 1, + "eager": false, + "files": [ + "/eq-core.js" + ] + }, + "feature:setlist-import": { + "contract": 1, + "eager": false, + "files": [ + "/setlist-import.js" + ] + }, + "feature:car-mode": { + "contract": 1, + "eager": false, + "files": [ + "/car-mode.js", + "/car-mode.css" + ] + }, + "feature:p2p": { + "contract": 1, + "eager": false, + "files": [ + "/p2p-client.js", + "/p2p-core.js", + "/p2p-transfer.js", + "/p2p-recv-worker.js", + "/hash-worker.js", + "/device-db.js" + ] + }, + "feature:direct": { + "contract": 1, + "eager": false, + "files": [ + "/direct-protocol.js", + "/direct-stream.js", + "/direct-media.js", + "/direct-media.css", + "/direct-recv-worker.js" + ] + }, + "feature:video-edit": { + "contract": 1, + "eager": false, + "files": [ + "/video-edit.js" + ] + }, + "feature:stats": { + "contract": 1, + "eager": false, + "files": [ + "/stats-core.js" + ] + }, + "feature:export": { + "contract": 1, + "eager": false, + "files": [ + "/export.js" + ] + }, + "feature:playlist": { + "contract": 1, + "eager": true, + "files": [], + "embeddedIn": [ + "/app.js" + ] + }, + "feature:settings": { + "contract": 1, + "eager": true, + "files": [], + "embeddedIn": [ + "/app.js", + "/settings-sections.js", + "/settings-sections.css" + ] + }, + "feature:service-mode": { + "contract": 1, + "eager": true, + "files": [], + "embeddedIn": [ + "/app.js", + "/service-ui.css" + ] + }, + "feature:lyrics-editor": { + "contract": 1, + "eager": true, + "files": [], + "embeddedIn": [ + "/app.js", + "/lyrics-core.js", + "/lyrics-display.js" + ] + } + } +} diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 752875f..1aa4082 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -27,3 +27,25 @@ test('every SHELL asset exists on disk and there are no duplicate entries', () = assert.equal(new Set(shell).size, shell.length, 'SHELL has no duplicate entries'); for (const asset of shell) assert.ok(existsSync(join(__dirname, asset.slice(1))), `${asset} exists`); }); + +test('assets.json describes the complete existing shell exactly once with eager core features', () => { + const { groups } = JSON.parse(readFileSync(join(__dirname, 'assets.json'), 'utf8')); + const described = new Set(); + for (const [name, group] of Object.entries(groups)) { + assert.equal(group.contract, 1, `${name} initial contract`); + assert.equal(typeof group.eager, 'boolean'); + for (const asset of group.files) { + assert.ok(!described.has(asset), `${asset} has one group`); + described.add(asset); + assert.ok(existsSync(join(__dirname, asset.slice(1))), `${asset} exists`); + } + } + for (const asset of shell) if (asset !== '/') assert.ok(described.has(asset), `${asset} is described`); + // piano-engine is dynamically imported and historically absent from SHELL. + for (const asset of described) assert.ok(listed.has(asset) || asset === '/piano-engine.mjs', `${asset} shell or documented dynamic import`); + assert.equal(groups.core.eager, true); + for (const name of ['playlist', 'settings', 'service-mode', 'lyrics-editor']) { + assert.equal(groups[`feature:${name}`].eager, true); + for (const asset of groups[`feature:${name}`].embeddedIn) assert.ok(groups.core.files.includes(asset), `${name} remains in core`); + } +}); diff --git a/plans/phase1-plan.md b/plans/phase1-plan.md index 55b03e2..f322dd7 100644 --- a/plans/phase1-plan.md +++ b/plans/phase1-plan.md @@ -8,7 +8,8 @@ 3. Add importable `server/asset-manifest.js`; integrate boot-time recursive hashing, stamped index, manifest endpoint, per-file headers and rollback into `server/server.js`. Register module tests in `server/package.json`. -4. Stamp safe HTML resource URLs (CSS/JS, font preloads, webmanifest). Retain +4. Stamp HTML CSS/JS resource URLs. Keep font preloads consistent with + fonts.css and retain the existing webmanifest URL. Retain plain JS-created worker/import URLs: introducing a new helper would require modifying the unchanged worker's shell or frontend callers. Inventory these exceptions explicitly in the report. Hash every recursively served file, diff --git a/server/asset-manifest.js b/server/asset-manifest.js new file mode 100644 index 0000000..c9734e2 --- /dev/null +++ b/server/asset-manifest.js @@ -0,0 +1,87 @@ +// Boot-time snapshot of ./public, independent of frontend source locations. +import { createHash } from 'node:crypto'; +import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; + +export const assetHash = bytes => createHash('sha256').update(bytes).digest('hex').slice(0, 10); +const tagHash = bytes => createHash('sha256').update(bytes).digest('hex').slice(0, 12); +export const injectBuildTag = (source, tag) => source.replace( + /typeof __BUILD_TAG__ !== 'undefined' \? __BUILD_TAG__ : '[^']*'/, JSON.stringify(tag)); + +export function stampIndex(source, files, { hashing = true, buildTag = '__BUILD_TAG__' } = {}) { + if (!hashing) return source.replace('__BUILD_TAG__', buildTag) + .replace(/((?:href|src)=")((?![a-z]+:|\/)[^"?]+\.(?:css|js))(")/g, `$1$2?v=${buildTag}$3`); + // Rewrite resource tags only, not anchors. Preserve unrelated query/fragment + // components and absolute external URLs; include root-relative local URLs. + return source.replace(/<(?:script|link)\b[^>]*>/gi, tag => tag.replace( + /\b(href|src)=(['"])([^'"]+)\2/gi, (attribute, name, quote, url) => { + if (/^(?:[a-z][a-z\d+.-]*:|\/\/|#)/i.test(url)) return attribute; + const parsed = new URL(url, 'https://assets.invalid/'); + const file = files[decodeURIComponent(parsed.pathname)]; + // Font preload URLs must stay identical to fonts.css's relative URLs. + if (!file || !/\.(?:css|js)$/.test(parsed.pathname) || parsed.pathname === '/sw.js') return attribute; + parsed.searchParams.set('v', file.h); + const originalPath = url.split(/[?#]/)[0]; + return `${name}=${quote}${originalPath}${parsed.search}${parsed.hash}${quote}`; + })).replace('__BUILD_TAG__', buildTag); +} + +export function createAssetManifest(publicDir = './public', { hashing = true, buildTag: override } = {}) { + const bytes = new Map(); + const legacy = createHash('sha256'); + function walk(dir, prefix = '') { + for (const name of readdirSync(dir).sort()) { + const path = join(dir, name), url = `${prefix}/${name}`; + if (statSync(path).isDirectory()) walk(path, url); + else { + const content = readFileSync(path); + bytes.set(url, content); + legacy.update(`./public${url}`); legacy.update(content); + } + } + } + // Missing public is the historical fixed fallback used by local tests. + if (!existsSync(publicDir)) return { manifest: { buildTag: override || 'dev-build', files: {}, groups: {}, contracts: {} }, index: null, sw: null, bytes }; + walk(publicDir); + const definition = bytes.has('/assets.json') ? JSON.parse(bytes.get('/assets.json').toString()) : { + groups: { core: { contract: 1, eager: true, files: [...bytes.keys()].sort() } }, + }; + const groups = {}, contracts = {}, membership = new Map(); + for (const name of Object.keys(definition.groups).sort()) { + const group = definition.groups[name]; + if (!Number.isInteger(group.contract) || group.contract < 1 || typeof group.eager !== 'boolean' || !Array.isArray(group.files)) throw new Error(`Invalid asset group ${name}`); + groups[name] = group; contracts[name] = group.contract; + for (const url of group.files) { + if (!bytes.has(url)) throw new Error(`Asset group ${name}: missing ${url}`); + if (membership.has(url)) throw new Error(`Duplicate asset membership: ${url}`); + membership.set(url, name); + } + } + const files = {}; + for (const url of [...bytes.keys()].sort()) files[url] = { h: assetHash(bytes.get(url)), s: bytes.get(url).length, g: membership.get(url) || 'core' }; + const source = bytes.get('/index.html')?.toString() ?? null; + const swSource = bytes.get('/sw.js')?.toString() ?? null; + // Derived build metadata cannot be an input to its own hash. Canonicalize + // the index meta and SW injected tag, then publish hashes of the final bytes. + // All original bytes (including index/SW source) remain inputs via source hashes. + let canonicalIndex = source === null ? null : stampIndex(source, files, { hashing }); + const canonical = { files: { ...files }, groups, contracts }; + if (canonicalIndex !== null && hashing) canonical.files['/index.html'] = { ...files['/index.html'], h: assetHash(canonicalIndex), s: Buffer.byteLength(canonicalIndex), source: files['/index.html'].h }; + const buildTag = hashing ? tagHash(JSON.stringify(canonical)) : (override || legacy.digest('hex').slice(0, 12)); + const index = source === null ? null : stampIndex(source, files, { hashing, buildTag }); + const sw = swSource === null ? null : injectBuildTag(swSource, buildTag); + if (index !== null) files['/index.html'] = { ...files['/index.html'], h: assetHash(index), s: Buffer.byteLength(index) }; + if (sw !== null) files['/sw.js'] = { ...files['/sw.js'], h: assetHash(sw), s: Buffer.byteLength(sw) }; + if (index !== null) bytes.set('/index.html', Buffer.from(index)); + if (sw !== null) bytes.set('/sw.js', Buffer.from(sw)); + return { manifest: { buildTag, files, groups, contracts }, index, sw, bytes }; +} + +export function assetCacheControl(path, version, manifest, hashing = true) { + const current = hashing ? manifest.files[path]?.h : manifest.buildTag; + if (version !== undefined) { + if (version === current) return 'public, max-age=31536000, immutable'; + return hashing ? 'no-store' : 'no-cache'; + } + return /(^|\/)(fonts|icons)\//.test(path) && (hashing || !/\.(?:js|css|html|json|webmanifest|svg|txt)$/i.test(path)) ? 'public, max-age=2592000' : 'no-cache'; +} diff --git a/server/asset-manifest.test.js b/server/asset-manifest.test.js new file mode 100644 index 0000000..71d59b8 --- /dev/null +++ b/server/asset-manifest.test.js @@ -0,0 +1,62 @@ +import { test, expect } from 'bun:test'; +import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { createHash } from 'node:crypto'; +import { createAssetManifest } from './asset-manifest.js'; + +const hash = value => createHash('sha256').update(value).digest('hex').slice(0, 10); +function fixture(fn) { + const dir = mkdtempSync(join(tmpdir(), 'ytp-manifest-')); + try { + writeFileSync(join(dir, 'index.html'), ''); + writeFileSync(join(dir, 'app.js'), 'window.app=1'); + writeFileSync(join(dir, 'app.css'), 'body{}'); + writeFileSync(join(dir, 'sw.js'), "const BUILD_TAG = typeof __BUILD_TAG__ !== 'undefined' ? __BUILD_TAG__ : 'old';"); + writeFileSync(join(dir, 'assets.json'), JSON.stringify({ groups: { core: { contract: 1, eager: true, files: ['/index.html', '/app.js', '/app.css'] } } })); + fn(dir); + } finally { rmSync(dir, { recursive: true, force: true }); } +} +test('manifest determinism, final served byte hashes and one-file URL isolation', () => fixture(dir => { + const first = createAssetManifest(dir); + expect(createAssetManifest(dir)).toEqual(first); + expect(first.manifest.buildTag).toMatch(/^[a-f0-9]{12}$/); + expect(first.manifest.files['/app.js']).toEqual({ h: hash('window.app=1'), s: 12, g: 'core' }); + expect(first.manifest.contracts.core).toBe(1); + expect(first.manifest.groups.core.eager).toBe(true); + expect(first.index).toContain(`/app.css?v=${first.manifest.files['/app.css'].h}`); + expect(first.index).toContain(`app.js?old=1&v=${first.manifest.files['/app.js'].h}`); + expect(first.index).toContain('https://example.com/x.js'); + expect(first.index).toContain(`content="${first.manifest.buildTag}"`); + expect(first.manifest.files['/index.html'].h).toBe(hash(first.index)); + expect(first.manifest.files['/sw.js'].h).toBe(hash(first.sw)); + writeFileSync(join(dir, 'app.js'), 'window.app=2'); + const second = createAssetManifest(dir); + expect(second.manifest.buildTag).not.toBe(first.manifest.buildTag); + for (const path of ['/app.css', '/assets.json']) expect(second.manifest.files[path]).toEqual(first.manifest.files[path]); + expect(second.manifest.files['/app.js'].h).not.toBe(first.manifest.files['/app.js'].h); +})); +test('unlisted files affect build identity; group contracts and order affect identity', () => fixture(dir => { + const first = createAssetManifest(dir); + writeFileSync(join(dir, 'other.bin'), 'shipped'); + const second = createAssetManifest(dir); + expect(second.manifest.buildTag).not.toBe(first.manifest.buildTag); + expect(second.manifest.files['/other.bin'].h).toBe(hash('shipped')); + writeFileSync(join(dir, 'assets.json'), JSON.stringify({ groups: { core: { contract: 2, eager: true, files: ['/app.css', '/app.js', '/index.html'] } } })); + expect(createAssetManifest(dir).manifest.buildTag).not.toBe(second.manifest.buildTag); +})); +test('invalid group definitions fail visibly', () => fixture(dir => { + writeFileSync(join(dir, 'assets.json'), JSON.stringify({ groups: { core: { contract: 1, eager: true, files: ['/missing.js'] } } })); + expect(() => createAssetManifest(dir)).toThrow('missing'); +})); +test('rollback retains legacy tag algorithm and relative-only single-tag stamping', () => fixture(dir => { + const result = createAssetManifest(dir, { hashing: false }); + const expected = createHash('sha256'); + for (const name of ['app.css', 'app.js', 'assets.json', 'index.html', 'sw.js']) { + expected.update(`./public/${name}`); + const { readFileSync } = require('node:fs'); + expected.update(readFileSync(join(dir, name))); + } + expect(result.manifest.buildTag).toBe(expected.digest('hex').slice(0, 12)); + expect(result.index).toContain('href="/app.css"'); +})); diff --git a/server/package.json b/server/package.json index b2371ae..a4e37cf 100644 --- a/server/package.json +++ b/server/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "bun server.js", "dev": "bun --hot server.js", - "test": "bun test ./recommendations.test.js && bun test --timeout 60000 ./media-cache.test.js && bun test ./notes.test.js && bun test ./transcriptions.test.js && bun test ./admin-analytics.test.js && bun test ./remote.test.js && bun test ./party.test.js && bun test ./uploads.test.js && bun test ./innertube.test.js && bun test ./related.test.js && bun test ./ytdlp-pool.test.js && bun test ./warm-queue.test.js && bun test ./p2p-db.test.js && bun test ./p2p-admit.test.js && bun test ./p2p-retention.test.js && bun test ./p2p-routes.test.js && bun test ./p2p-hub.test.js && bun test --timeout 60000 ./p2p-intake.test.js && bun test ./flags.test.js && bun test ./static-delivery.test.js" + "test": "bun test ./recommendations.test.js && bun test --timeout 60000 ./media-cache.test.js && bun test ./notes.test.js && bun test ./transcriptions.test.js && bun test ./admin-analytics.test.js && bun test ./remote.test.js && bun test ./party.test.js && bun test ./uploads.test.js && bun test ./innertube.test.js && bun test ./related.test.js && bun test ./ytdlp-pool.test.js && bun test ./warm-queue.test.js && bun test ./p2p-db.test.js && bun test ./p2p-admit.test.js && bun test ./p2p-retention.test.js && bun test ./p2p-routes.test.js && bun test ./p2p-hub.test.js && bun test --timeout 60000 ./p2p-intake.test.js && bun test ./flags.test.js && bun test ./asset-manifest.test.js && bun test ./static-delivery.test.js" }, "dependencies": { "@hono/node-server": "^1.14.0", diff --git a/server/server.js b/server/server.js index 7596424..d98bcc0 100644 --- a/server/server.js +++ b/server/server.js @@ -30,10 +30,10 @@ * UI code works without modification in WEB mode. * ========================================================================== */ +import { createAssetManifest, assetCacheControl } from './asset-manifest.js'; import { registerDownloadRetryRoute } from './download-retry.js'; import { createResilientYtdlp, BOT_CHECK_RE, DEFAULT_FALLBACK_CLIENTS } from './ytdlp-resilience.js'; import { Hono } from 'hono'; -import { serveStatic } from 'hono/bun'; import { logger } from 'hono/logger'; import { spawn } from 'node:child_process'; import { createServer } from 'node:http'; @@ -96,48 +96,11 @@ function withSaveSlot(fn) { return run; } -// ---------------------------------------------------------------------------- -// BUILD_TAG — must be DETERMINISTIC across restarts of identical code. -// -// Previously this was `Date.now().toString(36)`, which changes every time the -// process starts even if nothing was deployed (crash-loop, healthcheck -// restart, container reschedule). The frontend's checkBuildTag() polls -// /api/version and re-shows the "Update available" modal the instant the tag -// drifts — so a restarting-but-unchanged server kept re-announcing an update -// that never actually happened, and clicking "Refresh UI" (which itself -// reloads the page and re-polls) never made the prompt go away for good. -// -// Fix: hash the actual served frontend files. Identical code → identical -// hash → identical tag, no matter how many times the process restarts. A -// real deploy (changed files) still produces a new tag as intended. -// process.env.BUILD_TAG still wins if a CI pipeline already injects a git -// SHA — that's an even better source of truth than a content hash. -// ---------------------------------------------------------------------------- -function computeBuildTag() { - try { - // Hash EVERY served frontend file (recursively, in sorted order), not a - // hand-picked subset — a change to any shell file (e.g. sw-update.js or - // opfs.js) must produce a new tag, or clients keep their old SW cache - // and never receive the change. - const hash = createHash('sha256'); - const walk = (dir) => { - for (const name of readdirSync(dir).sort()) { - const path = `${dir}/${name}`; - if (statSync(path).isDirectory()) walk(path); - else { hash.update(path); hash.update(readFileSync(path)); } - } - }; - walk('./public'); - return hash.digest('hex').slice(0, 12); - } catch { - // Frontend files not readable (e.g. unit tests run outside ./public) — - // fall back to a fixed tag rather than Date.now(), so it still never - // drifts spuriously between restarts. - return 'dev-build'; - } -} - -const BUILD_TAG = process.env.BUILD_TAG || computeBuildTag(); +// Snapshot every shipped public file. Hashes describe the served HTML/SW bytes; +// rollback retains the historical recursive tag and single-tag URL stamping. +const ASSET_HASHING = process.env.ASSET_HASHING !== '0'; +const assets = createAssetManifest('./public', { hashing: ASSET_HASHING, buildTag: process.env.BUILD_TAG }); +const BUILD_TAG = assets.manifest.buildTag; // BUILD_TIME — human-readable "when was this image built". Written by the // Dockerfile at image build time (never at container start, so restarts @@ -389,6 +352,14 @@ registerCatalogRoutes(app, { resolveListener: recommendationListener }); // GET /api/version // Returns version string + a build tag that changes on every server restart/deploy. // Clients poll this to detect when a new build is live and prompt a reload. +app.get('/api/manifest', (c) => { + const etag = `"${BUILD_TAG}"`; + const headers = { 'Cache-Control': 'no-store', ETag: etag }; + const matches = (c.req.header('if-none-match') || '').split(',').map(value => value.trim().replace(/^W\//, '')); + if (matches.includes(etag) || matches.includes('*')) return new Response(null, { status: 304, headers }); + return c.json(assets.manifest, 200, headers); +}); + app.get('/api/version', (c) => c.json( { version: APP_VERSION, buildTag: BUILD_TAG, buildTime: BUILD_TIME }, @@ -2482,7 +2453,7 @@ app.get('/sw.js', (c) => { if (src === _swSource) { console.error('[sw] BUILD_TAG injection failed — placeholder not found in sw.js'); } - return sendCompressed(c, compressedEntry('sw.js', Buffer.from(src), MIME.js), 'no-store, no-cache, must-revalidate'); + return sendCompressed(c, compressedEntry('sw.js', Buffer.from(src), MIME.js), 'no-store, no-cache, must-revalidate', assets.manifest.files['/sw.js']?.h); }); // ============================================================================ @@ -2511,8 +2482,9 @@ function compressedEntry(key, raw, type) { compressedCache.set(key, e); return e; } -function sendCompressed(c, e, cacheControl) { +function sendCompressed(c, e, cacheControl, hash) { const headers = { 'Content-Type': e.type, 'Cache-Control': cacheControl, ETag: e.etag, Vary: 'Accept-Encoding' }; + if (hash) headers['X-Asset-Hash'] = hash; const inm = c.req.header('if-none-match') || ''; if (inm.split(',').map((s) => s.trim()).includes(e.etag)) return new Response(null, { status: 304, headers }); const ae = c.req.header('accept-encoding') || ''; @@ -2523,42 +2495,28 @@ function sendCompressed(c, e, cacheControl) { const MIME = { js: 'text/javascript; charset=utf-8', css: 'text/css; charset=utf-8', html: 'text/html; charset=utf-8', json: 'application/json', webmanifest: 'application/manifest+json', svg: 'image/svg+xml', txt: 'text/plain; charset=utf-8' }; -let _indexSource = null; function indexHtml(c) { - if (_indexSource === null) { - try { _indexSource = readFileSync('./public/index.html', 'utf8'); } - catch { return c.text('index.html not found', 404); } - } - // Local css/js get `?v=`: that URL's bytes never change, so the static - // handler below lets browsers keep it forever; a new build is a new URL. - const html = _indexSource.replace('__BUILD_TAG__', BUILD_TAG) - .replace(/((?:href|src)=")((?![a-z]+:|\/)[^"?]+\.(?:css|js))(")/g, `$1$2?v=${BUILD_TAG}$3`); - return sendCompressed(c, compressedEntry('index.html', Buffer.from(html), MIME.html), 'no-cache'); + if (assets.index === null) return c.text('index.html not found', 404); + return sendCompressed(c, compressedEntry('index.html', Buffer.from(assets.index), MIME.html), + assetCacheControl('/index.html', c.req.query('v'), assets.manifest, ASSET_HASHING), assets.manifest.files['/index.html']?.h); } app.get('/', indexHtml); app.get('/index.html', indexHtml); -// no-cache (revalidate every time) on the shell: the service worker is the -// only cache that should hold app files. With no headers at all, a browser -// may heuristically cache app.js and hand a new worker's install the old one. +// Serve every file with its per-file hash, including binary icons/fonts and +// unversioned URLs requested by old clients/workers. A stale version gets the +// current body with no-store, never immutable caching under a mismatched URL. app.get('/*', async (c, next) => { const p = decodeURIComponent(new URL(c.req.url).pathname); - if (!COMPRESSIBLE.test(p) || p.includes('..') || p.startsWith('/api/')) return next(); + if (p.includes('..') || p.startsWith('/api/') || !assets.manifest.files[p]) return next(); const file = Bun.file('./public' + p); - if (!(await file.exists())) return next(); - const raw = Buffer.from(await file.arrayBuffer()); + const raw = assets.bytes.get(p); const ext = p.slice(p.lastIndexOf('.') + 1).toLowerCase(); - // `?v=` equal to the running build → forever (a new build changes the URL). - // Any other / missing v keeps revalidating. - const forever = c.req.query('v') === BUILD_TAG; - return sendCompressed(c, compressedEntry(p, raw, MIME[ext] || 'application/octet-stream'), - forever ? 'public, max-age=31536000, immutable' : 'no-cache'); + const hash = assets.manifest.files[p].h; + const cacheControl = assetCacheControl(p, c.req.query('v'), assets.manifest, ASSET_HASHING); + if (COMPRESSIBLE.test(p)) return sendCompressed(c, compressedEntry(p, raw, MIME[ext] || file.type), cacheControl, hash); + return new Response(raw, { headers: { 'Content-Type': file.type, 'Cache-Control': cacheControl, 'X-Asset-Hash': hash } }); }); -// Self-hosted fonts and icons rarely change: let the browser keep them for 30 days -// (the service worker precaches the shell anyway); everything else revalidates. -app.use('/*', serveStatic({ root: './public', onFound: (path, c) => { - c.header('Cache-Control', /(^|\/)(fonts|icons)\//.test(path) ? 'public, max-age=2592000' : 'no-cache'); -} })); // SPA fallback — return index.html for any unmatched path app.get('/*', indexHtml); diff --git a/server/static-delivery.test.js b/server/static-delivery.test.js index f3d7a0a..0aafb79 100644 --- a/server/static-delivery.test.js +++ b/server/static-delivery.test.js @@ -32,11 +32,11 @@ async function freePort() { }); } -async function startServer() { +async function startServer(hashing = true) { const port = await freePort(); const child = Bun.spawn([process.execPath, serverFile], { cwd: root, - env: { ...process.env, PORT: String(port), DB_PATH: join(dataDir, `db-${port}.sqlite`), MEDIA_DIR: join(dataDir, 'media'), UPLOAD_DIR: join(dataDir, 'uploads') }, + env: { ...process.env, PORT: String(port), ASSET_HASHING: hashing ? '1' : '0', BUILD_TAG: '', DB_PATH: join(dataDir, `db-${port}.sqlite`), MEDIA_DIR: join(dataDir, 'media'), UPLOAD_DIR: join(dataDir, 'uploads') }, stdout: 'pipe', stderr: 'pipe', }); const stdout = new Response(child.stdout).text(); @@ -97,20 +97,20 @@ describe('static delivery characterization', () => { test('index stamps only relative local css/js and serves expected cache headers', async () => { const index = await fetch(`${server.base}/`); const html = await index.text(); - const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); + const { buildTag, files } = await (await fetch(`${server.base}/api/manifest`)).json(); expect(html).toContain(``); - expect(html).toContain(`href="app.css?v=${buildTag}"`); - expect(html).toContain(`src="app.js?v=${buildTag}"`); + expect(html).toContain(`href="app.css?v=${files['/app.css'].h}"`); + expect(html).toContain(`src="app.js?v=${files['/app.js'].h}"`); expect(html).toContain('https://cdn.example/x.js'); - expect(html).toContain('href="/root.css"'); + expect(html).toContain(`href="/root.css?v=${files['/root.css'].h}"`); expect(index.headers.get('cache-control')).toBe('no-cache'); expect((await fetch(`${server.base}/index.html`)).headers.get('cache-control')).toBe('no-cache'); - const current = await fetch(`${server.base}/app.js?v=${buildTag}`, { headers: { 'Accept-Encoding': 'br' } }); + const current = await fetch(`${server.base}/app.js?v=${files['/app.js'].h}`, { headers: { 'Accept-Encoding': 'br' } }); expect(current.headers.get('cache-control')).toBe('public, max-age=31536000, immutable'); expect(current.headers.get('content-encoding')).toBe('br'); expect(current.headers.get('etag')).toBeTruthy(); - expect((await fetch(`${server.base}/app.js?v=stale`)).headers.get('cache-control')).toBe('no-cache'); + expect((await fetch(`${server.base}/app.js?v=stale`)).headers.get('cache-control')).toBe('no-store'); expect((await fetch(`${server.base}/app.js`)).headers.get('cache-control')).toBe('no-cache'); expect((await fetch(`${server.base}/fonts/font.woff2`)).headers.get('cache-control')).toBe('public, max-age=2592000'); expect((await fetch(`${server.base}/icons/icon.png`)).headers.get('cache-control')).toBe('public, max-age=2592000'); @@ -118,11 +118,54 @@ describe('static delivery characterization', () => { expect((await fetch(`${server.base}${path}`)).headers.get('cache-control')).toBe('no-store, no-cache, must-revalidate'); } const etag = current.headers.get('etag'); - const notModified = await fetch(`${server.base}/app.js?v=${buildTag}`, { headers: { 'If-None-Match': etag } }); + const notModified = await fetch(`${server.base}/app.js?v=${files['/app.js'].h}`, { headers: { 'If-None-Match': etag } }); expect(notModified.status).toBe(304); expect(await notModified.text()).toBe(''); }); + + test('manifest API, ETag/304 and hashes cover compressed and binary assets', async () => { + const response = await fetch(`${server.base}/api/manifest`); + expect(response.headers.get('cache-control')).toBe('no-store'); + const manifest = await response.json(); + expect(manifest.buildTag).toBe((await (await fetch(`${server.base}/api/version`)).json()).buildTag); + expect(manifest.groups.core.eager).toBe(true); + expect(manifest.contracts.core).toBe(1); + expect(response.headers.get('etag')).toBe(`"${manifest.buildTag}"`); + const unchanged = await fetch(`${server.base}/api/manifest`, { headers: { 'If-None-Match': response.headers.get('etag') } }); + expect(unchanged.status).toBe(304); + expect(await unchanged.text()).toBe(''); + const { createHash } = await import('node:crypto'); + for (const path of ['/app.js', '/fonts/font.woff2', '/icons/icon.png', '/index.html', '/sw.js']) { + const h = manifest.files[path].h; + for (const query of ['', `?v=${h}`, '?v=oldTag', '?__ytpfresh=123', '?v=']) { + const asset = await fetch(`${server.base}${path}${query}`); + expect(asset.status).toBe(200); + expect(asset.headers.get('x-asset-hash')).toBe(h); + expect(createHash('sha256').update(Buffer.from(await asset.arrayBuffer())).digest('hex').slice(0, 10)).toBe(h); + if (path !== '/sw.js') { + if (query === `?v=${h}`) expect(asset.headers.get('cache-control')).toBe('public, max-age=31536000, immutable'); + if (query === '?v=oldTag' || query === '?v=') expect(asset.headers.get('cache-control')).toBe('no-store'); + } + } + } + const canonical = await (await fetch(`${server.base}/`)).text(); + for (const path of ['/index.html', '/search', '/playlist/x']) expect(await (await fetch(`${server.base}${path}`)).text()).toBe(canonical); + }); + + test('ASSET_HASHING=0 restores single-tag stamping and old cache matrix', async () => { + await stopServer(server); + server = await startServer(false); + try { + const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); + const html = await (await fetch(`${server.base}/`)).text(); + expect(html).toContain(`src="app.js?v=${buildTag}"`); + expect(html).toContain('href="/root.css"'); + expect((await fetch(`${server.base}/app.js?v=${buildTag}`)).headers.get('cache-control')).toBe('public, max-age=31536000, immutable'); + expect((await fetch(`${server.base}/app.js?v=stale`)).headers.get('cache-control')).toBe('no-cache'); + } finally { await stopServer(server); server = await startServer(); } + }); + test('service worker injection tracks fallback literal and reports missing placeholder', async () => { let sw = await (await fetch(`${server.base}/sw.js`)).text(); const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); From d18d17cf29778f0f3afaccb9df308de0f3a1e46c Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:01:55 +0800 Subject: [PATCH 05/81] Preserve legacy cache rules and pin service worker bytes at boot --- server/asset-manifest.js | 8 ++++++-- server/server.js | 12 +++--------- server/static-delivery.test.js | 20 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/server/asset-manifest.js b/server/asset-manifest.js index c9734e2..b7a5104 100644 --- a/server/asset-manifest.js +++ b/server/asset-manifest.js @@ -41,7 +41,7 @@ export function createAssetManifest(publicDir = './public', { hashing = true, bu } } // Missing public is the historical fixed fallback used by local tests. - if (!existsSync(publicDir)) return { manifest: { buildTag: override || 'dev-build', files: {}, groups: {}, contracts: {} }, index: null, sw: null, bytes }; + if (!existsSync(publicDir)) return { manifest: { buildTag: override || 'dev-build', files: {}, groups: {}, contracts: {} }, index: null, sw: null, swSource: null, bytes }; walk(publicDir); const definition = bytes.has('/assets.json') ? JSON.parse(bytes.get('/assets.json').toString()) : { groups: { core: { contract: 1, eager: true, files: [...bytes.keys()].sort() } }, @@ -74,10 +74,14 @@ export function createAssetManifest(publicDir = './public', { hashing = true, bu if (sw !== null) files['/sw.js'] = { ...files['/sw.js'], h: assetHash(sw), s: Buffer.byteLength(sw) }; if (index !== null) bytes.set('/index.html', Buffer.from(index)); if (sw !== null) bytes.set('/sw.js', Buffer.from(sw)); - return { manifest: { buildTag, files, groups, contracts }, index, sw, bytes }; + return { manifest: { buildTag, files, groups, contracts }, index, sw, swSource, bytes }; } export function assetCacheControl(path, version, manifest, hashing = true) { + const shortCache = /(^|\/)(fonts|icons)\//.test(path) ? 'public, max-age=2592000' : 'no-cache'; + // The legacy index route always revalidates; legacy binary delivery ignored v. + if (!hashing && path === '/index.html') return 'no-cache'; + if (!hashing && !/\.(?:js|css|html|json|webmanifest|svg|txt)$/i.test(path)) return shortCache; const current = hashing ? manifest.files[path]?.h : manifest.buildTag; if (version !== undefined) { if (version === current) return 'public, max-age=31536000, immutable'; diff --git a/server/server.js b/server/server.js index d98bcc0..43e9654 100644 --- a/server/server.js +++ b/server/server.js @@ -350,7 +350,7 @@ registerCatalogRoutes(app, { resolveListener: recommendationListener }); // ============================================================================ // GET /api/version -// Returns version string + a build tag that changes on every server restart/deploy. +// Returns version and a deterministic tag that changes only with shipped files. // Clients poll this to detect when a new build is live and prompt a reload. app.get('/api/manifest', (c) => { const etag = `"${BUILD_TAG}"`; @@ -2432,15 +2432,9 @@ app.post('/api/admin/p2p/revoke', notes.requireAdminOrToken, async (c) => { // Served with no-store cache headers so browsers always re-fetch it and // pick up the substituted value rather than a browser-cached stale copy. // ============================================================================ -let _swSource = null; +const _swSource = assets.swSource; app.get('/sw.js', (c) => { - if (!_swSource) { - try { - _swSource = readFileSync('./public/sw.js', 'utf8'); - } catch { - return c.text('Service worker not found', 404); - } - } + if (_swSource === null) return c.text('Service worker not found', 404); // Inject the build tag: replace the whole fallback expression with the // real value. Matched by REGEX, not an exact string — an exact match broke // the moment the fallback literal in sw.js was bumped ('v1.0.3' → 'v1.0.4'), diff --git a/server/static-delivery.test.js b/server/static-delivery.test.js index 0aafb79..4a9231d 100644 --- a/server/static-delivery.test.js +++ b/server/static-delivery.test.js @@ -94,7 +94,7 @@ describe('static delivery characterization', () => { expect(fallback.buildTag).toBe('dev-build'); }); - test('index stamps only relative local css/js and serves expected cache headers', async () => { + test('index stamps relative and root-local css/js and serves expected cache headers', async () => { const index = await fetch(`${server.base}/`); const html = await index.text(); const { buildTag, files } = await (await fetch(`${server.base}/api/manifest`)).json(); @@ -123,7 +123,6 @@ describe('static delivery characterization', () => { expect(await notModified.text()).toBe(''); }); - test('manifest API, ETag/304 and hashes cover compressed and binary assets', async () => { const response = await fetch(`${server.base}/api/manifest`); expect(response.headers.get('cache-control')).toBe('no-store'); @@ -163,6 +162,9 @@ describe('static delivery characterization', () => { expect(html).toContain('href="/root.css"'); expect((await fetch(`${server.base}/app.js?v=${buildTag}`)).headers.get('cache-control')).toBe('public, max-age=31536000, immutable'); expect((await fetch(`${server.base}/app.js?v=stale`)).headers.get('cache-control')).toBe('no-cache'); + expect((await fetch(`${server.base}/index.html?v=${buildTag}`)).headers.get('cache-control')).toBe('no-cache'); + expect((await fetch(`${server.base}/fonts/font.woff2?v=${buildTag}`)).headers.get('cache-control')).toBe('public, max-age=2592000'); + expect((await fetch(`${server.base}/fonts/font.woff2?v=stale`)).headers.get('cache-control')).toBe('public, max-age=2592000'); } finally { await stopServer(server); server = await startServer(); } }); @@ -190,6 +192,20 @@ describe('static delivery characterization', () => { server = await startServer(); }); + test('served bytes remain pinned to their boot-time hashes', async () => { + const before = await (await fetch(`${server.base}/app.js`)).text(); + const swBefore = await (await fetch(`${server.base}/sw.js`)).text(); + writeFileSync(join(publicDir, 'app.js'), 'changed after boot'); + writeFileSync(join(publicDir, 'sw.js'), 'changed after boot'); + try { + expect(await (await fetch(`${server.base}/app.js`)).text()).toBe(before); + expect(await (await fetch(`${server.base}/sw.js`)).text()).toBe(swBefore); + } finally { + writeFileSync(join(publicDir, 'app.js'), before); + writeFileSync(join(publicDir, 'sw.js'), "const BUILD_TAG = 'missing-placeholder';\n"); + } + }); + test('SPA routes fall back to the stamped index', async () => { const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); for (const path of ['/search', '/playlist/x']) { From 84546eeb7da50fdfcfadb5368cbdf9054b014b9e Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:09:04 +0800 Subject: [PATCH 06/81] Group all Glass Stage dependencies under the selected layout --- frontend/assets.json | 24 ++++++------------------ frontend/shell-consistency.test.js | 8 ++++++++ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/frontend/assets.json b/frontend/assets.json index 0e1c9f3..b70facf 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -53,11 +53,15 @@ "/fonts/JetBrainsMono-latin.woff2" ] }, - "layout:glass": { + "layout:glass-stage": { "contract": 1, "eager": false, "files": [ - "/theme-glass.css" + "/theme-glass.css", + "/theme-glass-controls.css", + "/glass-controls.js", + "/theme-glass-panel.css", + "/glass-panel-layout.js" ] }, "layout:classic": { @@ -67,22 +71,6 @@ "/theme-classic.css" ] }, - "layout:glass-controls": { - "contract": 1, - "eager": false, - "files": [ - "/theme-glass-controls.css", - "/glass-controls.js" - ] - }, - "layout:glass-panel": { - "contract": 1, - "eager": false, - "files": [ - "/theme-glass-panel.css", - "/glass-panel-layout.js" - ] - }, "layout:bento-hub": { "contract": 1, "eager": false, diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 1aa4082..8612339 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -49,3 +49,11 @@ test('assets.json describes the complete existing shell exactly once with eager for (const asset of groups[`feature:${name}`].embeddedIn) assert.ok(groups.core.files.includes(asset), `${name} remains in core`); } }); + +test('the selected glass-stage layout includes its controls and panel dependencies', () => { + const { groups } = JSON.parse(readFileSync(join(__dirname, 'assets.json'), 'utf8')); + assert.deepEqual(groups['layout:glass-stage'].files, [ + '/theme-glass.css', '/theme-glass-controls.css', '/glass-controls.js', + '/theme-glass-panel.css', '/glass-panel-layout.js', + ]); +}); From 7c45d098b18261c75525ca712f6ebbc3e377b159 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:12:48 +0800 Subject: [PATCH 07/81] Verify production-client migration and record Phase 1 measurements --- perf/README.md | 40 +++ perf/migration.mjs | 176 +++++++++++ perf/results/phase1-cold-2026-10-07.json | 128 ++++++++ perf/results/phase1-migration-2026-10-07.json | 33 ++ .../results/phase1-overlapped-2026-10-07.json | 296 ++++++++++++++++++ perf/results/phase1-reduced-2026-10-07.json | 296 ++++++++++++++++++ 6 files changed, 969 insertions(+) create mode 100644 perf/migration.mjs create mode 100644 perf/results/phase1-cold-2026-10-07.json create mode 100644 perf/results/phase1-migration-2026-10-07.json create mode 100644 perf/results/phase1-overlapped-2026-10-07.json create mode 100644 perf/results/phase1-reduced-2026-10-07.json diff --git a/perf/README.md b/perf/README.md index e9fecd5..55b3ed0 100644 --- a/perf/README.md +++ b/perf/README.md @@ -141,3 +141,43 @@ node perf/hidden-timers.mjs ``` Exits with code 0 on success, or code 1 if any interval fails to pause, fails to resume, or if page errors occur. +## Phase 1 production-client migration + +Build the production fixture locally without contacting the unavailable production +site (COMMON.md takes precedence over the older live-tag instructions above): + +```bash +perf/make-shell-fixture.sh b77938a 1175f1a1d2c1 +node perf/migration.mjs # Chromium and WebKit +node perf/migration.mjs --browser webkit # one browser +``` + +The harness archives the actual `b77938a` server and uses the reconstructed old +frontend, isolated database/media/upload paths, and an ephemeral origin behind the +`lossy` throttle/stall proxy. It restarts onto the current server and frontend at +that same origin, then invokes the OLD application's update check and clicks its +actual Refresh UI button. Assertions cover one banner, exactly one reload, cleared +update-attempt state, all new SHELL entries with correct hashes, no script errors, +and offline boot. Plain, stale `?v=` and `?__ytpfresh=` asset responses are +also compared byte-for-byte with the current files. Results are stored in +`perf/results/phase1-migration-2026-10-07.json`; scratch trees are removed on exit. +No service-worker source is patched or simulated. Offline checks stop Bun and +block the proxy; WebKit avoids its broken native setOffline API. Known WebKit +transport errors for disconnected version/recommendation requests are verified +separately from script errors. + +The current server snapshots static bytes at boot; restart it after frontend +changes. `ASSET_HASHING=0` restores the previous single-tag stamp/cache behavior. +The manifest's tag hashes sorted canonical metadata: CSS/JS URLs are stamped +before hashing the index, with its derived build-meta placeholder intact. The +published index/SW hashes describe their final served bytes after tag injection; +these derived hashes are not fed recursively into their own build identity. + +JS-created workers/importScripts/dynamic imports retain their existing plain URLs +in Phase 1. Adding a separate loader would require changing the intentionally +unchanged SHELL; worker import URL propagation belongs with the client migration. +WASM binaries are embedded in the existing `sha256-wasm.js`/`loudness-wasm.js`, +which receive hashed URLs as HTML scripts. Font preloads retain plain URLs to match +`fonts.css`; the webmanifest and its icon URLs also stay plain and precached. +`piano-engine.mjs` is manifested but is historically absent from SHELL; this +existing offline piano limitation is deferred to the loader phase. diff --git a/perf/migration.mjs b/perf/migration.mjs new file mode 100644 index 0000000..bec737e --- /dev/null +++ b/perf/migration.mjs @@ -0,0 +1,176 @@ +#!/usr/bin/env node +// Real production-client migration through the unchanged Refresh UI flow. +import assert from 'node:assert/strict'; +import { spawn, execFileSync } from 'node:child_process'; +import { mkdtempSync, mkdirSync, symlinkSync, unlinkSync, writeFileSync, rmSync, readFileSync } from 'node:fs'; +import { join, resolve } from 'node:path'; +import { createServer } from 'node:net'; +import { fileURLToPath } from 'node:url'; +import { createThrottleProxy } from './proxy.mjs'; +import { chromium, webkit } from 'playwright'; + +const repo = resolve(fileURLToPath(new URL('..', import.meta.url))); +const commit = 'b77938a', oldTag = '1175f1a1d2c1'; +const args = process.argv.slice(2); +const browserName = args.includes('--browser') ? args[args.indexOf('--browser') + 1] : 'all'; +assert.ok(['all', 'chromium', 'webkit'].includes(browserName)); +execFileSync('bash', [join(repo, 'perf/make-shell-fixture.sh'), commit, oldTag], { cwd: repo, stdio: 'inherit' }); +const scratch = mkdtempSync(join(repo, 'perf/.tmp/migration-')); +const archive = join(scratch, 'old-server.tar'); +writeFileSync(archive, execFileSync('git', ['archive', commit, 'server'], { cwd: repo, maxBuffer: 20 * 1024 * 1024 })); +execFileSync('tar', ['-xf', archive, '-C', scratch]); +symlinkSync(join(repo, 'server/node_modules'), join(scratch, 'server/node_modules')); +// Archived server modules resolve their Docker-style public imports relative +// to the module, while static routes resolve ./public relative to cwd. +symlinkSync(join(repo, `perf/fixtures/shell-${oldTag}`), join(scratch, 'server/public')); +const shell = [...readFileSync(join(repo, 'frontend/sw.js'), 'utf8').match(/const SHELL = \[([\s\S]*?)\n\];/)[1].matchAll(/['"](\/[^'"]+)['"]/g)].map(m => m[1]); +const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); +async function freePort() { + const server = createServer(); + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); + const port = server.address().port; + await new Promise(resolve => server.close(resolve)); + return port; +} +async function run(name) { + const cwd = join(scratch, name); + mkdirSync(cwd); + const port = await freePort(); + let child, output = '', browser, proxy; + async function stop() { + if (!child) return; + const process = child; child = null; + await new Promise(resolve => { + if (process.exitCode !== null) return resolve(); + process.once('exit', resolve); process.kill('SIGTERM'); + }); + } + async function start(old) { + symlinkSync(old ? join(repo, `perf/fixtures/shell-${oldTag}`) : join(repo, 'frontend'), join(cwd, 'public')); + output = ''; + child = spawn('bun', [old ? join(scratch, 'server/server.js') : join(repo, 'server/server.js')], { + cwd, env: { ...process.env, BUILD_TAG: '', ASSET_HASHING: old ? '0' : '1', PORT: String(port), + DATA_DIR: join(cwd, 'data'), DB_PATH: join(cwd, 'db.sqlite'), MEDIA_DIR: join(cwd, 'media'), UPLOAD_DIR: join(cwd, 'uploads') }, + stdio: ['ignore', 'pipe', 'pipe'], + }); + for (const stream of [child.stdout, child.stderr]) stream.on('data', chunk => { output = (output + chunk).slice(-12000); }); + for (let i = 0; i < 200; i++) { + if (child.exitCode !== null) throw new Error(`Bun server exited: ${output}`); + try { if ((await fetch(`http://127.0.0.1:${port}/api/version`)).ok) return; } catch {} + await sleep(100); + } + throw new Error(`Bun startup timeout: ${output}`); + } + try { + await start(true); + assert.equal((await (await fetch(`http://127.0.0.1:${port}/api/version`)).json()).buildTag, oldTag); + proxy = createThrottleProxy({ targetPort: port, profile: 'lossy' }); + const proxyPort = await proxy.listen(); + const origin = `http://127.0.0.1:${proxyPort}`; + browser = await ({ chromium, webkit }[name]).launch({ headless: true }); + const context = await browser.newContext(); + // Keep this harness entirely local, including any UI third-party requests. + await context.route('**/*', route => route.request().url().startsWith(origin) ? route.continue() : route.abort()); + let banners = 0, navigations = 0; + const errors = []; + const failedRequests = []; + let disconnected = false; + const page = await context.newPage(); + await page.exposeFunction('migrationBanner', () => { banners++; }); + await page.addInitScript(() => { + let visible = false; + new MutationObserver(() => { + const modal = document.querySelector('#modal'); + const now = !!modal && !modal.classList.contains('hidden') && /Update available/.test(document.querySelector('#modalTitle')?.textContent || ''); + if (now && !visible) window.migrationBanner(); + visible = now; + }).observe(document, { subtree: true, childList: true, attributes: true, characterData: true }); + }); + page.on('pageerror', error => errors.push({ message: error.message, disconnected })); + page.on('requestfailed', request => failedRequests.push(request.url())); + page.on('framenavigated', frame => { if (frame === page.mainFrame()) navigations++; }); + await page.goto(origin, { waitUntil: 'load', timeout: 90000 }); + await page.waitForFunction(() => !!navigator.serviceWorker.controller, { timeout: 90000 }); + assert.equal(await page.locator('meta[name="ytp-build"]').getAttribute('content'), oldTag); + assert.equal(banners, 0, 'no first-install banner'); + await stop(); unlinkSync(join(cwd, 'public')); await start(false); + const backend = `http://127.0.0.1:${port}`; + const manifest = await (await fetch(`${backend}/api/manifest`)).json(); + assert.notEqual(manifest.buildTag, oldTag); + // Old URLs must continue delivering actual NEW bytes, not error/fallback HTML. + for (const path of ['/app.js', '/theme-glass.css', '/opfs-worker.js', '/sha256-wasm.js', '/manifest.webmanifest', '/icons/icon-192.png', '/fonts/HankenGrotesk-latin.woff2']) { + for (const query of ['', '?__ytpfresh=migration', `?v=${oldTag}`]) { + const response = await fetch(`${backend}${path}${query}`); + assert.equal(response.status, 200); + assert.equal(response.headers.get('x-asset-hash'), manifest.files[path].h); + assert.deepEqual(Buffer.from(await response.arrayBuffer()), readFileSync(join(repo, 'frontend', path.slice(1)))); + if (query.includes('?v=')) assert.equal(response.headers.get('cache-control'), 'no-store'); + } + } + proxy.resetStats(); proxy.startTracking(); + const started = Date.now(); + // Use the old application's public functions; no simulated update helper. + await page.evaluate(async () => { + await checkBuildTag(); + await (await navigator.serviceWorker.getRegistration()).update(); + }); + await page.waitForFunction(async () => !!(await navigator.serviceWorker.getRegistration())?.waiting, { timeout: 90000 }); + await page.waitForFunction(() => /Update available/.test(document.querySelector('#modalTitle')?.textContent || '') && !document.querySelector('#modal').classList.contains('hidden')); + assert.equal(banners, 1, 'exactly one offer before refresh'); + const before = navigations; + await page.locator('#modal').getByRole('button', { name: 'Refresh UI', exact: true }).click(); + await page.waitForFunction(tag => document.querySelector('meta[name="ytp-build"]')?.content === tag && typeof checkBuildTag === 'function', manifest.buildTag, { timeout: 90000 }); + await page.waitForFunction(() => !sessionStorage.getItem('ytpUpdateAttempt')); + await page.evaluate(async () => { await checkBuildTag(); await checkBuildTag(); await checkBuildTag(); }); + await sleep(2000); + assert.equal(navigations - before, 1, 'one reload, no update loop'); + assert.equal(banners, 1, 'no banner after applying the current build'); + const cacheResult = await page.evaluate(async ({ tag, shell, files }) => { + const cache = await caches.open(`ytplayer-${tag}`); + const missing = [], incorrect = []; + for (const path of shell) { + const response = await cache.match(path); + if (!response) { missing.push(path); continue; } + if (response.headers.get('x-asset-hash') !== files[path === '/' ? '/index.html' : path]?.h) incorrect.push(path); + } + return { missing, incorrect, count: (await cache.keys()).length }; + }, { tag: manifest.buildTag, shell, files: manifest.files }); + assert.deepEqual(cacheResult.missing, []); + assert.deepEqual(cacheResult.incorrect, [], 'every cached shell asset belongs to the new build'); + proxy.stopTracking(); + const stats = proxy.getStats(); + const durationMs = Date.now() - started; + assert.deepEqual(errors, [], 'no script failures during installation and update'); + disconnected = true; + // Match baseline.mjs: Linux WebKit's setOffline breaks even SW navigation. + // Cut the proxy AND stop Bun so offline boot cannot use network bytes. + if (name !== 'webkit') await context.setOffline(true); + proxy.setOffline(true); + await stop(); + await page.reload({ waitUntil: 'load', timeout: 60000 }); + assert.equal(await page.locator('meta[name="ytp-build"]').getAttribute('content'), manifest.buildTag); + await page.waitForFunction(() => typeof checkBuildTag === 'function' && !!document.querySelector('#cards')?.dataset.view); + assert.equal(banners, 1); + // WebKit surfaces rejected SW network fetches as pageerrors even when the + // app catches them. Check only the exact, intentional offline API failures; + // syntax/reference/runtime exceptions must still fail this harness. + for (const error of errors) { + assert.equal(name, 'webkit', 'only WebKit has offline transport pageerrors'); + assert.equal(error.disconnected, true, 'transport errors only after disconnection'); + assert.ok(error.message === 'TypeError: Load failed' || /\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(error.message), `unexpected offline error: ${error.message}`); + } + if (errors.length) assert.ok(failedRequests.some(url => /\/api\/(?:recommendations|version)/.test(url)), 'transport errors correspond to disconnected API requests'); + const result = { browser: name, oldTag, newTag: manifest.buildTag, banners, updateReloads: 1, cachedFiles: cacheResult.count, durationMs, wireBytes: stats.totalWireBytes, offline: true, legacyURLs: 21, profile: 'lossy', offlineTransportErrors: errors.length }; + console.log(JSON.stringify(result)); + return result; + } finally { + await browser?.close(); + if (proxy) { proxy.server.closeAllConnections(); await proxy.close(); } + await stop(); + } +} +try { + const results = []; + for (const name of browserName === 'all' ? ['chromium', 'webkit'] : [browserName]) results.push(await run(name)); + writeFileSync(join(repo, 'perf/results/phase1-migration-2026-10-07.json'), JSON.stringify({ commit, results }, null, 2) + '\n'); +} finally { rmSync(scratch, { recursive: true, force: true }); } diff --git a/perf/results/phase1-cold-2026-10-07.json b/perf/results/phase1-cold-2026-10-07.json new file mode 100644 index 0000000..5ea4664 --- /dev/null +++ b/perf/results/phase1-cold-2026-10-07.json @@ -0,0 +1,128 @@ +{ + "date": "2026-10-07T14:58:19.058Z", + "commit": "6cb00d5073931325b15ec5b773bf15dc2b53816e", + "runsConfigured": 3, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 168, + "min": 168, + "max": 168, + "values": [ + 168, + 168, + 168 + ] + }, + "wireBytes": { + "median": 1042903, + "min": 1042903, + "max": 1042903, + "values": [ + 1042903, + 1042903, + 1042903 + ] + }, + "fcp": { + "median": 1576, + "min": 1536, + "max": 1604, + "values": [ + 1604, + 1536, + 1576 + ] + }, + "lcp": { + "median": 1924, + "min": 1892, + "max": 1960, + "values": [ + 1960, + 1892, + 1924 + ] + }, + "domContentLoaded": { + "median": 10331, + "min": 10304, + "max": 11004, + "values": [ + 11004, + 10304, + 10331 + ] + }, + "bootDone": { + "median": 10466, + "min": 10425, + "max": 11184, + "values": [ + 11184, + 10425, + 10466 + ] + }, + "longTaskTotal": { + "median": 450, + "min": 379, + "max": 481, + "values": [ + 481, + 379, + 450 + ] + }, + "swInstallDuration": { + "median": 40643, + "min": 40439, + "max": 41259, + "values": [ + 41259, + 40439, + 40643 + ] + }, + "swInstallBytes": { + "median": 1042903, + "min": 1042903, + "max": 1042903, + "values": [ + 1042903, + 1042903, + 1042903 + ] + }, + "storageEstimate": { + "usage": 3490858, + "quota": 5372199978 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28587, + "js": 479281, + "css": 130718, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 336, + "other": 631 + } + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase1-migration-2026-10-07.json b/perf/results/phase1-migration-2026-10-07.json new file mode 100644 index 0000000..f5336d8 --- /dev/null +++ b/perf/results/phase1-migration-2026-10-07.json @@ -0,0 +1,33 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "ee1f3de99a02", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 87, + "durationMs": 19381, + "wireBytes": 1191657, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "ee1f3de99a02", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 87, + "durationMs": 15257, + "wireBytes": 668490, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase1-overlapped-2026-10-07.json b/perf/results/phase1-overlapped-2026-10-07.json new file mode 100644 index 0000000..c0a0720 --- /dev/null +++ b/perf/results/phase1-overlapped-2026-10-07.json @@ -0,0 +1,296 @@ +{ + "date": "2026-10-07T15:08:29.812Z", + "commit": "d18d17cf29778f0f3afaccb9df308de0f3a1e46c", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 168, + "min": 168, + "max": 168, + "values": [ + 168 + ] + }, + "wireBytes": { + "median": 1042858, + "min": 1042858, + "max": 1042858, + "values": [ + 1042858 + ] + }, + "fcp": { + "median": 1628, + "min": 1628, + "max": 1628, + "values": [ + 1628 + ] + }, + "lcp": { + "median": 1976, + "min": 1976, + "max": 1976, + "values": [ + 1976 + ] + }, + "domContentLoaded": { + "median": 11020, + "min": 11020, + "max": 11020, + "values": [ + 11020 + ] + }, + "bootDone": { + "median": 11149, + "min": 11149, + "max": 11149, + "values": [ + 11149 + ] + }, + "longTaskTotal": { + "median": 460, + "min": 460, + "max": 460, + "values": [ + 460 + ] + }, + "swInstallDuration": { + "median": 41250, + "min": 41250, + "max": 41250, + "values": [ + 41250 + ] + }, + "swInstallBytes": { + "median": 1042858, + "min": 1042858, + "max": 1042858, + "values": [ + 1042858 + ] + }, + "storageEstimate": { + "usage": 3490858, + "quota": 5372199978 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28542, + "js": 479281, + "css": 130718, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 336, + "other": 631 + } + }, + "warm": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5 + ] + }, + "wireBytes": { + "median": 10581, + "min": 10581, + "max": 10581, + "values": [ + 10581 + ] + }, + "fcp": { + "median": 280, + "min": 280, + "max": 280, + "values": [ + 280 + ] + }, + "lcp": { + "median": 992, + "min": 992, + "max": 992, + "values": [ + 992 + ] + }, + "domContentLoaded": { + "median": 787, + "min": 787, + "max": 787, + "values": [ + 787 + ] + }, + "bootDone": { + "median": 974, + "min": 974, + "max": 974, + "values": [ + 974 + ] + }, + "longTaskTotal": { + "median": 287, + "min": 287, + "max": 287, + "values": [ + 287 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 100, + "min": 100, + "max": 100, + "values": [ + 100 + ] + }, + "lcp": { + "median": 100, + "min": 100, + "max": 100, + "values": [ + 100 + ] + }, + "domContentLoaded": { + "median": 296, + "min": 296, + "max": 296, + "values": [ + 296 + ] + }, + "bootDone": { + "median": 327, + "min": 327, + "max": 327, + "values": [ + 327 + ] + }, + "reloadDuration": { + "median": 349, + "min": 349, + "max": 349, + "values": [ + 349 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 90, + "min": 90, + "max": 90, + "values": [ + 90 + ] + }, + "wireBytes": { + "median": 613029, + "min": 613029, + "max": 613029, + "values": [ + 613029 + ] + }, + "duration": { + "median": 2088, + "min": 2088, + "max": 2088, + "values": [ + 2088 + ] + }, + "wireBytesByType": { + "html": 18996, + "js": 267655, + "css": 65359, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 62, + "other": 631 + } + }, + "updateCss": { + "requestCount": { + "median": 90, + "min": 90, + "max": 90, + "values": [ + 90 + ] + }, + "wireBytes": { + "median": 613046, + "min": 613046, + "max": 613046, + "values": [ + 613046 + ] + }, + "duration": { + "median": 1997, + "min": 1997, + "max": 1997, + "values": [ + 1997 + ] + }, + "wireBytesByType": { + "html": 18996, + "js": 267644, + "css": 65387, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 62, + "other": 631 + } + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase1-reduced-2026-10-07.json b/perf/results/phase1-reduced-2026-10-07.json new file mode 100644 index 0000000..f848276 --- /dev/null +++ b/perf/results/phase1-reduced-2026-10-07.json @@ -0,0 +1,296 @@ +{ + "date": "2026-10-07T15:10:34.781Z", + "commit": "84546eeb7da50fdfcfadb5368cbdf9054b014b9e", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 168, + "min": 168, + "max": 168, + "values": [ + 168 + ] + }, + "wireBytes": { + "median": 1042858, + "min": 1042858, + "max": 1042858, + "values": [ + 1042858 + ] + }, + "fcp": { + "median": 1564, + "min": 1564, + "max": 1564, + "values": [ + 1564 + ] + }, + "lcp": { + "median": 1920, + "min": 1920, + "max": 1920, + "values": [ + 1920 + ] + }, + "domContentLoaded": { + "median": 11001, + "min": 11001, + "max": 11001, + "values": [ + 11001 + ] + }, + "bootDone": { + "median": 11137, + "min": 11137, + "max": 11137, + "values": [ + 11137 + ] + }, + "longTaskTotal": { + "median": 430, + "min": 430, + "max": 430, + "values": [ + 430 + ] + }, + "swInstallDuration": { + "median": 41164, + "min": 41164, + "max": 41164, + "values": [ + 41164 + ] + }, + "swInstallBytes": { + "median": 1042858, + "min": 1042858, + "max": 1042858, + "values": [ + 1042858 + ] + }, + "storageEstimate": { + "usage": 3490858, + "quota": 5372199978 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28542, + "js": 479281, + "css": 130718, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 336, + "other": 631 + } + }, + "warm": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5 + ] + }, + "wireBytes": { + "median": 10581, + "min": 10581, + "max": 10581, + "values": [ + 10581 + ] + }, + "fcp": { + "median": 172, + "min": 172, + "max": 172, + "values": [ + 172 + ] + }, + "lcp": { + "median": 648, + "min": 648, + "max": 648, + "values": [ + 648 + ] + }, + "domContentLoaded": { + "median": 531, + "min": 531, + "max": 531, + "values": [ + 531 + ] + }, + "bootDone": { + "median": 641, + "min": 641, + "max": 641, + "values": [ + 641 + ] + }, + "longTaskTotal": { + "median": 148, + "min": 148, + "max": 148, + "values": [ + 148 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 80, + "min": 80, + "max": 80, + "values": [ + 80 + ] + }, + "lcp": { + "median": 240, + "min": 240, + "max": 240, + "values": [ + 240 + ] + }, + "domContentLoaded": { + "median": 211, + "min": 211, + "max": 211, + "values": [ + 211 + ] + }, + "bootDone": { + "median": 232, + "min": 232, + "max": 232, + "values": [ + 232 + ] + }, + "reloadDuration": { + "median": 254, + "min": 254, + "max": 254, + "values": [ + 254 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 90, + "min": 90, + "max": 90, + "values": [ + 90 + ] + }, + "wireBytes": { + "median": 613029, + "min": 613029, + "max": 613029, + "values": [ + 613029 + ] + }, + "duration": { + "median": 1891, + "min": 1891, + "max": 1891, + "values": [ + 1891 + ] + }, + "wireBytesByType": { + "html": 18996, + "js": 267655, + "css": 65359, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 62, + "other": 631 + } + }, + "updateCss": { + "requestCount": { + "median": 88, + "min": 88, + "max": 88, + "values": [ + 88 + ] + }, + "wireBytes": { + "median": 607743, + "min": 607743, + "max": 607743, + "values": [ + 607743 + ] + }, + "duration": { + "median": 1890, + "min": 1890, + "max": 1890, + "values": [ + 1890 + ] + }, + "wireBytesByType": { + "html": 18996, + "js": 262403, + "css": 65387, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 0, + "other": 631 + } + } + } + } + } +} \ No newline at end of file From 7434f2f48696e2a43f9006bb623f9770964b3111 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:14:14 +0800 Subject: [PATCH 08/81] Document Phase 1 verification and retained plain asset URLs --- plans/phase1-report.md | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 plans/phase1-report.md diff --git a/plans/phase1-report.md b/plans/phase1-report.md new file mode 100644 index 0000000..e4f3a26 --- /dev/null +++ b/plans/phase1-report.md @@ -0,0 +1,44 @@ +# Phase 1 report + +Shipped: `6cb00d5` adds asset groups/contracts, boot snapshots, per-file hashes, +HTML stamping, `/api/manifest`, ETag/304, hash headers and `ASSET_HASHING=0`. +`d18d17c` preserves the exact legacy index/binary cache rules and pins SW bytes. +Plan: `ad85cb6`; `84546ee` groups Glass Stage dependencies together. +Migration harness/results: `7c45d09`. + +Verification: 156 frontend and 178 server tests pass. Server tests used an +isolated scratch Python environment with yt-dlp installed; none were skipped. +Both service-worker sources, index source, playback and timers remain unchanged. +Production fixture: `b77938a` → `1175f1a1d2c1`, reproduced without production calls. +Chromium/WebKit migration passes through the lossy/stalling proxy: one banner, +one update reload, all 87 shell entries verified, 21 legacy URL/body checks, +and offline boot with Bun stopped. Migration took 19.4/15.3 s respectively. +WebKit's known disconnected API transport errors are checked separately; script +errors during installation/update fail the harness. + +Reduced Chromium LTE: three-run cold median before final regrouping 10,466 ms +vs 10,480 ms. Final standalone single-run cold: 11,137 ms (+6.3%); FCP +1,564 ms vs 1,572 ms; wire bytes 1,042,858 (+0.3%). Warm/offline boots: +641/232 ms vs 692/259 ms. Overlapped-run timings are retained separately. + +JS-requested assets receiving hashed URLs: **none**. HTML CSS/JS references are +hashed, including sha256-wasm.js/loudness-wasm.js (embedded WASM; no standalone +.wasm fetch). Plain worker URLs: opfs-worker.js, hash-worker.js, +direct-recv-worker.js, p2p-recv-worker.js. Plain worker imports: sha256.js, +resume-core.js, sha256-wasm.js. Plain dynamic loads: piano-engine.mjs, +vendor/framework7-swipe.min.js. Propagating URL maps safely needs caller/worker +changes and a cached bootstrap; retain the unchanged client protocol this phase. +All are manifested; piano-engine.mjs is historically absent from SHELL, an +existing offline limitation deferred to the loader phase. + +Also plain: manifest.webmanifest; icons/icon-{192,512}.png; +fonts/{BricolageGrotesque,HankenGrotesk,JetBrainsMono,PlusJakartaSans}-{latin,latin-ext}.woff2. +Font preloads must match fonts.css URLs; manifest icon paths remain unchanged. + +Build identity hashes sorted canonical metadata with the index build-meta +placeholder intact; published index/SW hashes describe final served bytes, +avoiding self-reference. Restart after frontend edits; hashing mode ignores +BUILD_TAG overrides. Incremental downloads/lazy parsing await later phases. + +Owner iPhone checks: install/update, offline launch, active layout, then 30-minute +locked playback, dropouts, battery use and resume. No push, merge or deployment. From a1f16f2e3bddbbdb6fe0f913ba4a07ffadd5d79f Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:20:59 +0800 Subject: [PATCH 09/81] Plan phase 2: Add incremental asset sync and migration verification --- plans/phase2-plan.md | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 plans/phase2-plan.md diff --git a/plans/phase2-plan.md b/plans/phase2-plan.md new file mode 100644 index 0000000..003ba05 --- /dev/null +++ b/plans/phase2-plan.md @@ -0,0 +1,64 @@ +# Phase 2 — incremental service-worker asset sync + +Base: `codex/phase1` at `7434f2f`; branch: `codex/phase2`. + +1. Add tests first in `frontend/asset-sync-core.test.js`, extend + `frontend/sw.test.js` / `frontend/sw-update.test.js`, and deliberately extend + `frontend/shell-consistency.test.js` and `server/static-delivery.test.js`. +2. Add pure UMD `frontend/asset-sync-core.js`: exact hashed URL planning, + group-based blocking sets (everything except explicit background groups), + contract-bump blocking, verified resumable writes, capped six-way concurrency, + three retries, missing-entry checks and changed-file N-1 retention/N-2 pruning. + Register it in `frontend/assets.json`, `frontend/index.html` and the retained + legacy SHELL. Do not include unrelated shipped test/source files in downloads. +3. Integrate in `frontend/sw.js`: persistent `ytplayer-assets` utility cache, + per-build candidate manifests, atomic active-manifest promotion on activation, + verified exact lookups, plain-URL resolution, navigation/SPA index fallback, + resumable install, honest CACHE_STATUS, and quota logging. Preserve thumbnails, + fonts, share-target handling and network-only APIs. Delete legacy shell caches + only after commit and retain verified old bytes/manifest for N-1 compatibility. +4. Integrate in `frontend/sw-update.js`: a thin sync-core refresh caller, + preserved opt-in ready fast path, and playback checks immediately before + activation and every reload callback. Keep a legacy fallback for rollback. + Never change the banner rule, update outcome logic or audio/timer machinery. +5. Required server gap: inject ASSET_SYNC mode and a versioned core-module URL + into the served worker in `server/asset-manifest.js` / `server/server.js`. + Keep served worker hash headers accurate after injection. `ASSET_SYNC=0` + selects the legacy worker install/update path; test both modes. For cold + installs, share already downloaded HTTP asset bytes without accepting stale + plain responses or weakening hash verification; report remaining URL gaps. +6. Extend `perf/migration.mjs`: actual b77938a old helper, ready:true reply, + proof no refresh re-download, exactly one banner/reload, N-1 old-tab requests, + offline boot; Chromium/WebKit, with and without `perf/proxy.mjs` stalls. + Add browser checks for interrupted downloads, eviction repair and rollback. +7. Run `perf/baseline.mjs` reduced update/cold/warm/offline measurements against + `perf/results/after-phase0-2026-10-07.json`; record requested asset paths and + compressed bytes. Acceptance: JS-only change fetches JS + index + manifest; + CSS-only change <30 KB; zero font/icon update downloads; no duplicate cold + shell transfer (or explain an evidenced gap). All required unit suites green + after each implementation commit, and browser checks pass in both engines. +8. Review full diff against master §2c/§3.2/§6b; commit a ≤350-word + `plans/phase2-report.md` with hashes, measurements, gaps and iPhone checks; + write DONE02 only after completion. No push, merge, deploy or production call. + +Risks: an install must not silently switch the active tab's manifest; incomplete +sync must not delete old data; exact hashes must not resolve to unrelated current +bytes; worker/page HTTP caches can duplicate font transfers; cache quota competes +with saved audio. Rollback preserves both schemes until its own commit succeeds. + +## Required owner decision before implementation + +The production `b77938a` helper already running in legacy tabs does not check +Player._wantsPlaying: applyUpdate sends SKIP_WAITING and schedules an unconditional +reload after four seconds. A read-only Node VM reproduction using that exact git +source with Player._wantsPlaying=true produced: +`{"wantsPlaying":true,"messages":["SKIP_WAITING"],"reloads":1}`. +A newly installed worker cannot cancel a timer in an already-running old page. +Refusing SKIP_WAITING still leaves that old timer able to reload via the old worker. + +Recommended policy: enforce the playback guarantee in all upgraded clients and +require paused playback for the one-time legacy Refresh UI migration. Legacy +migration browser tests use paused playback; already-open playing tabs are never +automatically reloaded. This explicit legacy exception needs owner clarification +because the brief states the guarantee without an exception. COMMON.md requires +QUESTION and stopping for an unanswered user-visible behavior decision. From 54a07a0a2ae1711e441545b208c45c55b3318963 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:40:20 +0800 Subject: [PATCH 10/81] Synchronize verified assets incrementally and guard update activation --- frontend/asset-sync-core.js | 25 +++++++ frontend/asset-sync-core.test.js | 9 +++ frontend/asset-worker.test.js | 12 +++ frontend/assets.json | 1 + frontend/index.html | 1 + frontend/shell-consistency.test.js | 7 ++ frontend/sw-update.js | 51 ++++++++++++- frontend/sw-update.test.js | 7 ++ frontend/sw.js | 114 +++++++++++++++++++++++++++-- frontend/sw.test.js | 1 + plans/phase2-plan.md | 7 ++ server/asset-manifest.js | 8 +- server/asset-manifest.test.js | 8 ++ server/server.js | 14 ++-- server/static-delivery.test.js | 17 ++++- 15 files changed, 260 insertions(+), 22 deletions(-) create mode 100644 frontend/asset-sync-core.js create mode 100644 frontend/asset-sync-core.test.js create mode 100644 frontend/asset-worker.test.js diff --git a/frontend/asset-sync-core.js b/frontend/asset-sync-core.js new file mode 100644 index 0000000..d3c9f37 --- /dev/null +++ b/frontend/asset-sync-core.js @@ -0,0 +1,25 @@ +/* Exact, resumable asset synchronization shared by pages and workers. */ +(function(root){ + 'use strict'; + const CACHE='ytplayer-assets', STATE='/__ytp_asset_state'; + const url=(path,file)=>path+'?v='+file.h; + function paths(m){return [...new Set(Object.values(m.groups).flatMap(g=>g.files))].sort();} + function blocking(m){return [...new Set(Object.entries(m.groups).filter(([n,g])=>n==='core'||!g.background).flatMap(([,g])=>g.files))].sort();} + function plan(m,keys){const held=new Set(keys);return {missing:paths(m).map(p=>url(p,m.files[p])).filter(u=>!held.has(u)),blocking:blocking(m).map(p=>url(p,m.files[p]))};} + function retained(current,previous){const keep=new Set(paths(current).map(p=>url(p,current.files[p])));if(previous)for(const p of paths(previous))if(current.files[p]&¤t.files[p].h!==previous.files[p].h)keep.add(url(p,previous.files[p]));return keep;} + async function status(m,cache){let missing=0;for(const p of blocking(m)){const r=await cache.match(url(p,m.files[p]));if(!r||r.headers.get('X-Asset-Hash')!==m.files[p].h)missing++;}return {ready:missing===0,missing,version:m.buildTag};} + async function syncAssets(m,{cache,fetchFn,concurrency=6,attempts=3}){ + const missing=[];for(const p of paths(m)){const u=url(p,m.files[p]),r=await cache.match(u);if(!r||r.headers.get('X-Asset-Hash')!==m.files[p].h)missing.push(u);} + const count=missing.length;let failure; + await Promise.all(Array.from({length:Math.min(6,concurrency,Math.max(1,count))},async()=>{ + while(missing.length&&!failure){const u=missing.shift();let error; + for(let i=0;ictl.abort(),30000);let r;try{r=await fetchFn(u,{credentials:'same-origin',signal:ctl.signal});}finally{clearTimeout(timer);}if(!r.ok||r.headers.get('X-Asset-Hash')!==u.split('v=')[1])throw Error('Asset hash mismatch: '+u);await cache.put(u,r);error=null;break;}catch(e){error=e;}} + if(error)failure=error; + } + }));if(failure)throw failure;if(!(await status(m,cache)).ready)throw Error('Incomplete blocking assets');return {refreshed:count,caches:1}; + } + async function state(cache){const r=await cache.match(STATE);return r?await r.json():null;} + async function commit(m,cache){if(!(await status(m,cache)).ready)throw Error('Incomplete blocking assets');const old=await state(cache);const previous=old?.current?.buildTag===m.buildTag?old.previous:old?.current;await cache.put(STATE,new Response(JSON.stringify({current:m,previous}),{headers:{'Content-Type':'application/json'}}));const keep=retained(m,previous);for(const req of await cache.keys()){const u=new URL(req.url);const k=u.pathname+u.search;if(u.searchParams.has('v')&&!keep.has(k))await cache.delete(k);}return {current:m,previous};} + const api={CACHE,STATE,url,paths,blocking,plan,retained,status,syncAssets,state,commit}; + if(typeof module!=='undefined'&&module.exports)module.exports=api;else root.AssetSyncCore=api; +})(typeof globalThis!=='undefined'?globalThis:this); diff --git a/frontend/asset-sync-core.test.js b/frontend/asset-sync-core.test.js new file mode 100644 index 0000000..1b62137 --- /dev/null +++ b/frontend/asset-sync-core.test.js @@ -0,0 +1,9 @@ +const {test}=require('node:test'); +const assert=require('node:assert/strict'); +const core=require('./asset-sync-core'); +const manifest=(a='a',b='b')=>({buildTag:a+b,files:{'/a.js':{h:a},'/index.html':{h:b}},groups:{core:{files:['/a.js','/index.html']}}}); +function cache(){const entries=new Map();return {entries,async match(k){return entries.get(k)?.clone()},async put(k,r){entries.set(k,r.clone())},async keys(){return [...entries.keys()].map(url=>({url:'http://local'+url}))},async delete(k){return entries.delete(k)}}} +const response=h=>new Response(h,{headers:{'X-Asset-Hash':h}}); +test('exact diff shares unchanged URLs; retains N-1 and prunes N-2',()=>{assert.deepEqual(core.plan(manifest(),['/a.js?v=a']).missing,['/index.html?v=b']);assert.deepEqual([...core.retained(manifest('c'),manifest())].sort(),['/a.js?v=a','/a.js?v=c','/index.html?v=b']);}); +test('interrupted sync resumes verified files and refuses a mismatched hash',async()=>{const c=cache();let fail=true;let calls=[];const fetchFn=async u=>{calls.push(u);if(u.includes('index')&&fail)return response('wrong');return response(u.split('=')[1])};await assert.rejects(core.syncAssets(manifest(),{cache:c,fetchFn}),/hash/);assert.ok(await c.match('/a.js?v=a'));fail=false;calls=[];await core.syncAssets(manifest(),{cache:c,fetchFn});assert.deepEqual(calls,['/index.html?v=b']);await c.delete('/a.js?v=a');assert.equal((await core.status(manifest(),c)).missing,1);}); +test('commit is atomic and pruning keeps only current and previous changed versions',async()=>{const c=cache();await c.put('/a.js?v=z',response('z'));await core.syncAssets(manifest(),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest(),c);await core.syncAssets(manifest('c'),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest('c'),c);assert.ok(await c.match('/a.js?v=a'));assert.equal(await c.match('/a.js?v=z'),undefined);await core.syncAssets(manifest('d'),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest('d'),c);assert.equal(await c.match('/a.js?v=a'),undefined);}); diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js new file mode 100644 index 0000000..f7cc057 --- /dev/null +++ b/frontend/asset-worker.test.js @@ -0,0 +1,12 @@ +const {test}=require('node:test');const assert=require('node:assert/strict');const vm=require('node:vm');const fs=require('node:fs');const core=require('./asset-sync-core'); +function environment(){ + const stores=new Map(),listeners={},messages=[],skips=[];const m={buildTag:'next',files:{'/index.html':{h:'index'},'/app.js':{h:'app'}},groups:{core:{files:['/index.html','/app.js']}}}; + const storage={async keys(){return [...stores.keys()]},async delete(n){return stores.delete(n)},async open(n){if(!stores.has(n)){const map=new Map();stores.set(n,{async match(k){return map.get(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)?.clone()},async put(k,r){map.set(k,r.clone())},async keys(){return [...map.keys()].map(k=>({url:'https://local'+k}))},async delete(k){return map.delete(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)}})}return stores.get(n)}}; + const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':u.split('v=')[1]}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; + vm.runInNewContext(fs.readFileSync(__dirname+'/sw.js','utf8'),sandbox); + async function dispatch(t,e={}){let p;listeners[t]({...e,waitUntil:v=>p=v});await p} + async function request(url,mode='cors',clientId='new'){let p;listeners.fetch({request:{url:'https://local'+url,method:'GET',mode},clientId,respondWith:v=>p=v});return p} + return {storage,m,skips,dispatch,request}; +} +test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);}); +test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); diff --git a/frontend/assets.json b/frontend/assets.json index b70facf..1326222 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -12,6 +12,7 @@ "/flag-ui.js", "/async-guard.js", "/visible-timer.js", + "/asset-sync-core.js", "/sw-update.js", "/fingerprint.js", "/opfs.js", diff --git a/frontend/index.html b/frontend/index.html index 8e55e31..f55934d 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -665,6 +665,7 @@ + diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 8612339..547c292 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -57,3 +57,10 @@ test('the selected glass-stage layout includes its controls and panel dependenci '/theme-glass-panel.css', '/glass-panel-layout.js', ]); }); + +test('the shared sync core is eager and loads before the update helper',()=>{ + const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); + assert.ok(groups.core.files.includes('/asset-sync-core.js')); + assert.ok(html.indexOf('src="asset-sync-core.js"')} */ - async function refreshShellInPlace({ cachesApi, fetchFn, isShellCache, bust, timeoutMs, attempts, attemptTimeoutMs, concurrency, stagingKey, setTimeout: setTimeoutFn }) { + async function refreshLegacyShell({ cachesApi, fetchFn, isShellCache, bust, timeoutMs, attempts, attemptTimeoutMs, concurrency, stagingKey, setTimeout: setTimeoutFn }) { const names = (await cachesApi.keys()).filter(isShellCache); if (!names.length) return { refreshed: 0, caches: 0, resumed: 0 }; // uncontrolled page: a reload already hits the network @@ -145,6 +145,42 @@ return { refreshed: urls.size, caches: names.length, resumed }; } + async function refreshShellInPlace(opts) { + const core = root.AssetSyncCore; + if (core) { + const response = await opts.fetchFn('/api/manifest', { cache: 'no-store' }); + if (!response.ok) throw new Error('Manifest unavailable'); + const m = await response.json(); + const cache = await opts.cachesApi.open(core.CACHE); + // Only upgraded workers can route the persistent scheme. A rollback + // worker explicitly advertises the legacy path through CACHE_STATUS. + const reg = root.navigator && await root.navigator.serviceWorker.getRegistration(); + const worker = reg && (reg.waiting || reg.active); + const status = await askCacheStatus(worker); + if (status && status.assetSync) { + const result = await core.syncAssets(m,{cache,fetchFn:opts.fetchFn}); + if (!reg.waiting) await core.commit(m,cache); + return result; + } + } + return refreshLegacyShell({ ...opts, isShellCache: n => n !== 'ytplayer-assets' && opts.isShellCache(n) }); + } + + function playing() { return typeof Player !== 'undefined' && !!Player._wantsPlaying; } + function reportPlaying(value = playing()) { + const sw = root.navigator && root.navigator.serviceWorker; + if (!sw) return; + sw.getRegistration().then(reg => { + for (const worker of [sw.controller, reg && reg.waiting]) if(worker) worker.postMessage({type:'PLAYING',value}); + }).catch(()=>{}); + } + if (root.document && root.navigator && root.navigator.serviceWorker) { + if (root.VisibleTimer) root.VisibleTimer.setIntervalWhenVisible(()=>reportPlaying(),1000); + for (const event of ['play','pause','ended']) root.document.addEventListener(event,()=>reportPlaying(),true); + root.document.addEventListener('visibilitychange',()=>reportPlaying()); + root.navigator.serviceWorker.addEventListener('controllerchange',()=>reportPlaying()); + } + /** * Asks a worker whether it has already precached its whole shell. * Resolves to null on any problem (no reply, no MessageChannel, timeout) — @@ -191,7 +227,14 @@ * @param {Function} [opts.setTimeout] injectable for tests * @returns {Promise} */ - async function applyUpdate({ reg, container, reload, refreshShell, askStatus, onPhase, setTimeout: setTimeoutFn }) { + async function applyUpdate({ reg, container, reload, refreshShell, askStatus, onPhase, isPlaying = playing, confirmOverride = root.confirm && root.confirm.bind(root), setTimeout: setTimeoutFn }) { + let overridden = false; + const guard = () => { + if (!isPlaying() || overridden) return true; + if (confirmOverride && confirmOverride('Playing - update after this song / when paused. Update now anyway? Playback may stop.')) { overridden = true; return true; } + return false; + }; + if (!guard()) throw new Error('Playing - update after this song / when paused'); const scheduleTimeout = setTimeoutFn || (typeof setTimeout !== 'undefined' ? setTimeout : null); const waiting = reg && reg.waiting; @@ -209,6 +252,7 @@ if (onPhase) onPhase(precached ? 'ready' : 'downloading'); if (!precached && refreshShell) await refreshShell(); + if (!guard()) throw new Error('Playing - update after this song / when paused'); if (!waiting) { reload(); return; @@ -216,7 +260,7 @@ let reloaded = false; const reloadOnce = () => { - if (reloaded) return; + if (reloaded || (isPlaying() && !overridden)) return; reloaded = true; reload(); }; @@ -224,6 +268,7 @@ // either way; reload on controllerchange, or after a short safety net. container.addEventListener('controllerchange', reloadOnce, { once: true }); if (scheduleTimeout) scheduleTimeout(reloadOnce, 4000); + if (overridden) waiting.postMessage({type:'PLAYING',value:false}); waiting.postMessage({ type: 'SKIP_WAITING' }); } diff --git a/frontend/sw-update.test.js b/frontend/sw-update.test.js index 11f3e0a..53e336f 100644 --- a/frontend/sw-update.test.js +++ b/frontend/sw-update.test.js @@ -349,3 +349,10 @@ test('askCacheStatus returns the worker reply', async () => { const got = await askCacheStatus(worker, { setTimeout: () => {}, Channel: FakeChannel }); assert.deepStrictEqual(got, { ready: true, version: 'abc' }); }); + +test('playback guard blocks activation and reload unless explicit override is accepted',async()=>{ + let messages=[],reloads=0;const reg={waiting:{postMessage:m=>messages.push(m)}}; + await assert.rejects(applyUpdate({reg,container:fakeContainer(),reload:()=>reloads++,isPlaying:()=>true,confirmOverride:()=>false}),/Playing/); + assert.equal(messages.length,0);assert.equal(reloads,0); + let playing=false;const container=fakeContainer();await applyUpdate({reg,container,reload:()=>reloads++,isPlaying:()=>playing,askStatus:async()=>({ready:true}),setTimeout:()=>{}});playing=true;container.fireControllerChange();assert.equal(reloads,0); +}); diff --git a/frontend/sw.js b/frontend/sw.js index 2c50908..f41b7ff 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -27,13 +27,15 @@ // It changes on every deploy/restart so the cache is busted automatically // without any manual version bump. const VERSION = typeof __BUILD_TAG__ !== 'undefined' ? __BUILD_TAG__ : 'v1.0.4'; +const ASSET_SYNC = typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true; +if (ASSET_SYNC) importScripts('/asset-sync-core.js'); const CACHE = 'ytplayer-' + VERSION; // Prefix shared by every versioned app-shell cache (ytplayer-). // Utility caches (ytplayer-thumbs, ytplayer-fonts) intentionally do NOT // match this — they aren't versioned and must survive every activate. const SHELL_CACHE_PREFIX = 'ytplayer-'; -const UTILITY_CACHES = new Set(['ytplayer-thumbs', 'ytplayer-fonts']); +const UTILITY_CACHES = new Set(['ytplayer-thumbs', 'ytplayer-fonts', 'ytplayer-assets']); const THUMB_CACHE = 'ytplayer-thumbs'; // Hosts serving video thumbnails and channel avatars. yt-dlp hands back @@ -71,6 +73,7 @@ const SHELL = [ '/export.js', '/async-guard.js', '/visible-timer.js', + '/asset-sync-core.js', '/sw-update.js', '/fingerprint.js', '/opfs.js', @@ -146,7 +149,7 @@ const SHELL = [ // skipWaiting() is NOT called here — the page activates a waiting worker // from "Refresh UI" (see sw-update.js). self.addEventListener('install', (e) => { - e.waitUntil(precacheShell()); + e.waitUntil(ASSET_SYNC ? installAssets() : precacheShell()); }); // Fresh requests (`cache: 'reload'` skips the browser HTTP cache, which could @@ -180,6 +183,7 @@ async function precacheShell() { // ---- Activate: evict old caches, claim clients, notify about update ---- self.addEventListener('activate', (e) => { e.waitUntil((async () => { + if (ASSET_SYNC) { await activateAssets(); return; } const keys = await caches.keys(); // Was there a *previous deploy's* app-shell cache lying around? If so, @@ -278,13 +282,20 @@ self.addEventListener('fetch', (e) => { } // App shell → cache-first, then network, then generic offline fallback - e.respondWith(cacheFirst(request)); + e.respondWith(cacheFirst(request, e.clientId)); }); // ---- Message: handle SKIP_WAITING from the client ---- +const playingClients = new Map(), deferredClients = new Set(); self.addEventListener('message', (e) => { + if (e.data && e.data.type === 'PLAYING' && e.source) { + playingClients.set(e.source.id, !!e.data.value); + if (!e.data.value && deferredClients.delete(e.source.id)) self.skipWaiting(); + } if (e.data && e.data.type === 'SKIP_WAITING') { - self.skipWaiting(); + const id = e.source && e.source.id; + if (playingClients.get(id)) deferredClients.add(id); + else self.skipWaiting(); } // "Is your shell already downloaded?" — a waiting worker has precached the // whole new build during install, so "Refresh UI" can swap to it instantly @@ -293,6 +304,13 @@ self.addEventListener('message', (e) => { // storage pressure, so the files are actually checked. if (e.data && e.data.type === 'CACHE_STATUS') { e.waitUntil((async () => { + if (ASSET_SYNC) { + let reply = { ready: false, missing: -1, version: VERSION }; + try { const cache = await caches.open(AssetSyncCore.CACHE); const m = await candidate(cache); if(m) reply = await AssetSyncCore.status(m,cache); } catch {} + reply.type = 'CACHE_STATUS'; reply.assetSync = true; + if(e.ports && e.ports[0]) e.ports[0].postMessage(reply); else if(e.source) e.source.postMessage(reply); + return; + } let missing = SHELL.length; try { const cache = await caches.open(CACHE); @@ -311,7 +329,8 @@ self.addEventListener('message', (e) => { // ============================================================================ // Cache-first: serve from cache; if missing, fetch, cache, return. -async function cacheFirst(request) { +async function cacheFirst(request, clientId) { + if (ASSET_SYNC) return assetFetch(request, clientId); const cache = await caches.open(CACHE); // Shell files are precached under their plain URL; index.html asks for them as // `file?v=` (so the HTTP cache can keep them forever) — match ignoring it. @@ -417,3 +436,88 @@ async function staleWhileRevalidate(request, cacheName) { // surface a real network error instead. return cached || (await networkFetch) || Response.error(); } + +// Installation stores a candidate only. Activation publishes one atomic state record. +const candidateKey = '/__ytp_candidate/' + VERSION; +async function candidate(cache) { const r = await cache.match(candidateKey); return r ? r.json() : null; } +async function installAssets() { + const r = await fetch('/api/manifest', { cache: 'no-store' }); + if (!r.ok) throw Error('Manifest unavailable'); + const m = await r.json(); + if (m.buildTag !== VERSION) throw Error('Deployment changed during install'); + const cache = await caches.open(AssetSyncCore.CACHE); + const freshInstall = !(await AssetSyncCore.state(cache)); + const fetchAsset = async (url,init) => { + // Fonts/icons still use plain URLs in CSS/manifest. On first install reuse + // their HTTP-cache responses, but only if the hash proves current bytes. + if(freshInstall && /^(?:\/fonts\/|\/icons\/|\/manifest.webmanifest)/.test(url)) { + const r = await fetch(url.split('?')[0],{...init,cache:'force-cache'}); + if(r.ok && r.headers.get('X-Asset-Hash') === url.split('v=')[1]) return r; + } + return fetch(url,init); + }; + await AssetSyncCore.syncAssets(m, { cache, fetchFn: fetchAsset }); + await cache.put(candidateKey, new Response(JSON.stringify(m))); +} +async function migrateLegacy(cache, m) { + // Legacy responses lack hash headers. Verify their actual bytes locally before + // retaining them; this also preserves old whole-build URLs in already-open tabs. + const names = (await caches.keys()).filter(isVersionedShellCache); + let previous = null; + for (const name of names) { + const old = await caches.open(name); + const files = {}, legacyURLs = {}; + for (const req of await old.keys()) { + const u = new URL(req.url), p = u.pathname === '/' ? '/index.html' : u.pathname; + if (!m.files[p]) continue; + const r = await old.match(req); + if (!r || !r.ok) continue; + const bytes = await r.clone().arrayBuffer(); + const digest = await crypto.subtle.digest('SHA-256', bytes); + const h = [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2,'0')).join('').slice(0,10); + const headers = new Headers(r.headers); headers.set('X-Asset-Hash', h); + files[p] = { h }; legacyURLs[p] = p + '?v=' + h; + await cache.put(legacyURLs[p], new Response(bytes, { headers })); + } + if (Object.keys(files).length) previous = { buildTag:name.slice(SHELL_CACHE_PREFIX.length),files,groups:{core:{files:Object.keys(files)}},legacyURLs }; + } + if (previous && !(await AssetSyncCore.state(cache))) await cache.put(AssetSyncCore.STATE, new Response(JSON.stringify({current:previous}))); + return names; +} +async function activateAssets() { + const cache = await caches.open(AssetSyncCore.CACHE), m = await candidate(cache); + if (!m) throw Error('Missing candidate manifest'); + const names = await migrateLegacy(cache,m), old = await AssetSyncCore.state(cache); + const state = await AssetSyncCore.commit(m,cache); + state.previousClients = (await self.clients.matchAll({type:'window'})).map(c=>c.id); + await cache.put(AssetSyncCore.STATE,new Response(JSON.stringify(state))); + // Legacy deletion occurs strictly after verified commit. + await Promise.all(names.map(n => caches.delete(n))); + for (const req of await cache.keys()) if(new URL(req.url).pathname.startsWith('/__ytp_candidate/')) await cache.delete(req); + await self.clients.claim(); + if(old && old.current.buildTag !== m.buildTag) for(const c of await self.clients.matchAll({type:'window',includeUncontrolled:true})) c.postMessage({type:'SW_UPDATE_AVAILABLE',version:VERSION}); + try { console.info('[asset-sync] storage', await self.navigator.storage.estimate()); } catch {} +} +async function assetFetch(request, clientId) { + const cache = await caches.open(AssetSyncCore.CACHE), state = await AssetSyncCore.state(cache); + if(!state) return fetch(request); + const u = new URL(request.url); + let m = state.current; + if(u.origin !== self.location.origin) return fetch(request); + if(u.searchParams.has('__ytpfresh')) return fetch(request); + const nav = request.mode === 'navigate' || u.pathname === '/' || u.pathname === '/index.html'; + if(!nav && state.previousClients?.includes(clientId) && state.previous?.files[u.pathname]) m = state.previous; + let path = nav ? '/index.html' : u.pathname; + let key; + if(u.searchParams.has('v') && !nav) { + key = u.pathname + u.search; + if(state.previous?.legacyURLs && u.searchParams.get('v') === state.previous.buildTag) key = state.previous.legacyURLs[path] || key; + } else if(m.files[path]) key = AssetSyncCore.url(path,m.files[path]); + if(key) { + const cached = await cache.match(key); + const h = new URL(key,self.location.origin).searchParams.get('v'); + if(cached && cached.headers.get('X-Asset-Hash') === h) return cached; + try { const r = await fetch(key); if(r.ok && r.headers.get('X-Asset-Hash') === h) await cache.put(key,r.clone()); return r; } catch { return new Response('Offline',{status:503}); } + } + try { return await fetch(request); } catch { return new Response('Offline',{status:503}); } +} diff --git a/frontend/sw.test.js b/frontend/sw.test.js index 56d7ac4..6d17e88 100644 --- a/frontend/sw.test.js +++ b/frontend/sw.test.js @@ -56,6 +56,7 @@ function loadSw(initialCacheKeys, { fetchImpl } = {}) { }; const sandbox = { + __ASSET_SYNC__: false, self: self_, caches: caches_, fetch: fetchImpl || (async () => { throw new Error('fetch not mocked'); }), diff --git a/plans/phase2-plan.md b/plans/phase2-plan.md index 003ba05..c8635ef 100644 --- a/plans/phase2-plan.md +++ b/plans/phase2-plan.md @@ -62,3 +62,10 @@ migration browser tests use paused playback; already-open playing tabs are never automatically reloaded. This explicit legacy exception needs owner clarification because the brief states the guarantee without an exception. COMMON.md requires QUESTION and stopping for an unanswered user-visible behavior decision. + +## Owner answer + +Accepted: the legacy timer remains user-triggered by Refresh UI. New pages +show a playback guard with an explicit override, report PLAYING to the worker, +and the worker defers known-playing requests. Installation never calls +skipWaiting. Migration must prove no automatic legacy reload. diff --git a/server/asset-manifest.js b/server/asset-manifest.js index b7a5104..22e4384 100644 --- a/server/asset-manifest.js +++ b/server/asset-manifest.js @@ -26,7 +26,7 @@ export function stampIndex(source, files, { hashing = true, buildTag = '__BUILD_ })).replace('__BUILD_TAG__', buildTag); } -export function createAssetManifest(publicDir = './public', { hashing = true, buildTag: override } = {}) { +export function createAssetManifest(publicDir = './public', { hashing = true, buildTag: override, assetSync = true } = {}) { const bytes = new Map(); const legacy = createHash('sha256'); function walk(dir, prefix = '') { @@ -65,11 +65,13 @@ export function createAssetManifest(publicDir = './public', { hashing = true, bu // the index meta and SW injected tag, then publish hashes of the final bytes. // All original bytes (including index/SW source) remain inputs via source hashes. let canonicalIndex = source === null ? null : stampIndex(source, files, { hashing }); - const canonical = { files: { ...files }, groups, contracts }; + const canonical = { assetSync, files: { ...files }, groups, contracts }; if (canonicalIndex !== null && hashing) canonical.files['/index.html'] = { ...files['/index.html'], h: assetHash(canonicalIndex), s: Buffer.byteLength(canonicalIndex), source: files['/index.html'].h }; const buildTag = hashing ? tagHash(JSON.stringify(canonical)) : (override || legacy.digest('hex').slice(0, 12)); const index = source === null ? null : stampIndex(source, files, { hashing, buildTag }); - const sw = swSource === null ? null : injectBuildTag(swSource, buildTag); + const sw = swSource === null ? null : injectBuildTag(swSource, buildTag) + .replace("typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true", JSON.stringify(assetSync)) + .replace("importScripts('/asset-sync-core.js')", "importScripts('/asset-sync-core.js?v=" + (files['/asset-sync-core.js']?.h || '') + "')"); if (index !== null) files['/index.html'] = { ...files['/index.html'], h: assetHash(index), s: Buffer.byteLength(index) }; if (sw !== null) files['/sw.js'] = { ...files['/sw.js'], h: assetHash(sw), s: Buffer.byteLength(sw) }; if (index !== null) bytes.set('/index.html', Buffer.from(index)); diff --git a/server/asset-manifest.test.js b/server/asset-manifest.test.js index 71d59b8..0b03375 100644 --- a/server/asset-manifest.test.js +++ b/server/asset-manifest.test.js @@ -60,3 +60,11 @@ test('rollback retains legacy tag algorithm and relative-only single-tag stampin expect(result.manifest.buildTag).toBe(expected.digest('hex').slice(0, 12)); expect(result.index).toContain('href="/app.css"'); })); + +test('sync rollback changes build identity and injected worker byte hash', () => fixture(dir => { + writeFileSync(join(dir,'sw.js'), "const VERSION = typeof __BUILD_TAG__ !== 'undefined' ? __BUILD_TAG__ : 'old'; const SYNC = typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true;"); + const on=createAssetManifest(dir),off=createAssetManifest(dir,{assetSync:false}); + expect(on.sw).toContain('const SYNC = true');expect(off.sw).toContain('const SYNC = false'); + expect(on.manifest.buildTag).not.toBe(off.manifest.buildTag); + expect(off.manifest.files['/sw.js'].h).toBe(hash(off.sw)); +})); diff --git a/server/server.js b/server/server.js index 43e9654..b7a7f3f 100644 --- a/server/server.js +++ b/server/server.js @@ -99,7 +99,7 @@ function withSaveSlot(fn) { // Snapshot every shipped public file. Hashes describe the served HTML/SW bytes; // rollback retains the historical recursive tag and single-tag URL stamping. const ASSET_HASHING = process.env.ASSET_HASHING !== '0'; -const assets = createAssetManifest('./public', { hashing: ASSET_HASHING, buildTag: process.env.BUILD_TAG }); +const assets = createAssetManifest('./public', { hashing: ASSET_HASHING, assetSync: process.env.ASSET_SYNC !== '0', buildTag: process.env.BUILD_TAG }); const BUILD_TAG = assets.manifest.buildTag; // BUILD_TIME — human-readable "when was this image built". Written by the @@ -357,7 +357,8 @@ app.get('/api/manifest', (c) => { const headers = { 'Cache-Control': 'no-store', ETag: etag }; const matches = (c.req.header('if-none-match') || '').split(',').map(value => value.trim().replace(/^W\//, '')); if (matches.includes(etag) || matches.includes('*')) return new Response(null, { status: 304, headers }); - return c.json(assets.manifest, 200, headers); + const entry = compressedEntry('api-manifest',Buffer.from(JSON.stringify(assets.manifest)), 'application/json; charset=utf-8'); + return sendCompressed(c, { ...entry, etag }, 'no-store'); }); app.get('/api/version', (c) => @@ -2440,13 +2441,8 @@ app.get('/sw.js', (c) => { // the moment the fallback literal in sw.js was bumped ('v1.0.3' → 'v1.0.4'), // after which the replacement silently did nothing, the SW version froze, // and clients never saw another update no matter how many times we deployed. - const src = _swSource.replace( - /typeof __BUILD_TAG__ !== 'undefined' \? __BUILD_TAG__ : '[^']*'/, - JSON.stringify(BUILD_TAG) - ); - if (src === _swSource) { - console.error('[sw] BUILD_TAG injection failed — placeholder not found in sw.js'); - } + const src = assets.sw; + if (!/typeof __BUILD_TAG__/.test(_swSource)) console.error('[sw] BUILD_TAG injection failed — placeholder not found in sw.js'); return sendCompressed(c, compressedEntry('sw.js', Buffer.from(src), MIME.js), 'no-store, no-cache, must-revalidate', assets.manifest.files['/sw.js']?.h); }); diff --git a/server/static-delivery.test.js b/server/static-delivery.test.js index 4a9231d..0a6fff0 100644 --- a/server/static-delivery.test.js +++ b/server/static-delivery.test.js @@ -32,11 +32,11 @@ async function freePort() { }); } -async function startServer(hashing = true) { +async function startServer(hashing = true, sync = true) { const port = await freePort(); const child = Bun.spawn([process.execPath, serverFile], { cwd: root, - env: { ...process.env, PORT: String(port), ASSET_HASHING: hashing ? '1' : '0', BUILD_TAG: '', DB_PATH: join(dataDir, `db-${port}.sqlite`), MEDIA_DIR: join(dataDir, 'media'), UPLOAD_DIR: join(dataDir, 'uploads') }, + env: { ...process.env, PORT: String(port), ASSET_HASHING: hashing ? '1' : '0', ASSET_SYNC: sync ? '1' : '0', BUILD_TAG: '', DB_PATH: join(dataDir, `db-${port}.sqlite`), MEDIA_DIR: join(dataDir, 'media'), UPLOAD_DIR: join(dataDir, 'uploads') }, stdout: 'pipe', stderr: 'pipe', }); const stdout = new Response(child.stdout).text(); @@ -168,6 +168,19 @@ describe('static delivery characterization', () => { } finally { await stopServer(server); server = await startServer(); } }); + test('manifest compression preserves build ETag and sync mode is injected', async () => { + const version=await (await fetch(`${server.base}/api/version`)).json(); + const response=await fetch(`${server.base}/api/manifest`,{headers:{'Accept-Encoding':'gzip'}}); + expect(response.headers.get('etag')).toBe(`"${version.buildTag}"`); + expect(response.headers.get('content-encoding')).toBe('gzip'); + expect((await response.json()).buildTag).toBe(version.buildTag); + writeFileSync(join(publicDir,'sw.js'), "const BUILD_TAG = typeof __BUILD_TAG__ !== 'undefined' ? __BUILD_TAG__ : 'v-test'; const SYNC = typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true;"); + await stopServer(server);server=await startServer(true,false); + expect(await (await fetch(`${server.base}/sw.js`)).text()).toContain('const SYNC = false'); + await stopServer(server);server=await startServer(true,true); + expect(await (await fetch(`${server.base}/sw.js`)).text()).toContain('const SYNC = true'); + }); + test('service worker injection tracks fallback literal and reports missing placeholder', async () => { let sw = await (await fetch(`${server.base}/sw.js`)).text(); const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); From 5b25ccaa8693e4147a028edc978bc3735e9560d8 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:56:46 +0800 Subject: [PATCH 11/81] Publish asset state atomically and reject unavailable versions --- frontend/asset-sync-core.js | 131 +++++++++++++++++++++++++------ frontend/asset-sync-core.test.js | 3 + frontend/asset-worker.test.js | 4 +- frontend/sw.js | 11 ++- 4 files changed, 119 insertions(+), 30 deletions(-) diff --git a/frontend/asset-sync-core.js b/frontend/asset-sync-core.js index d3c9f37..e2b68fb 100644 --- a/frontend/asset-sync-core.js +++ b/frontend/asset-sync-core.js @@ -1,25 +1,112 @@ /* Exact, resumable asset synchronization shared by pages and workers. */ -(function(root){ +(function (root) { 'use strict'; - const CACHE='ytplayer-assets', STATE='/__ytp_asset_state'; - const url=(path,file)=>path+'?v='+file.h; - function paths(m){return [...new Set(Object.values(m.groups).flatMap(g=>g.files))].sort();} - function blocking(m){return [...new Set(Object.entries(m.groups).filter(([n,g])=>n==='core'||!g.background).flatMap(([,g])=>g.files))].sort();} - function plan(m,keys){const held=new Set(keys);return {missing:paths(m).map(p=>url(p,m.files[p])).filter(u=>!held.has(u)),blocking:blocking(m).map(p=>url(p,m.files[p]))};} - function retained(current,previous){const keep=new Set(paths(current).map(p=>url(p,current.files[p])));if(previous)for(const p of paths(previous))if(current.files[p]&¤t.files[p].h!==previous.files[p].h)keep.add(url(p,previous.files[p]));return keep;} - async function status(m,cache){let missing=0;for(const p of blocking(m)){const r=await cache.match(url(p,m.files[p]));if(!r||r.headers.get('X-Asset-Hash')!==m.files[p].h)missing++;}return {ready:missing===0,missing,version:m.buildTag};} - async function syncAssets(m,{cache,fetchFn,concurrency=6,attempts=3}){ - const missing=[];for(const p of paths(m)){const u=url(p,m.files[p]),r=await cache.match(u);if(!r||r.headers.get('X-Asset-Hash')!==m.files[p].h)missing.push(u);} - const count=missing.length;let failure; - await Promise.all(Array.from({length:Math.min(6,concurrency,Math.max(1,count))},async()=>{ - while(missing.length&&!failure){const u=missing.shift();let error; - for(let i=0;ictl.abort(),30000);let r;try{r=await fetchFn(u,{credentials:'same-origin',signal:ctl.signal});}finally{clearTimeout(timer);}if(!r.ok||r.headers.get('X-Asset-Hash')!==u.split('v=')[1])throw Error('Asset hash mismatch: '+u);await cache.put(u,r);error=null;break;}catch(e){error=e;}} - if(error)failure=error; - } - }));if(failure)throw failure;if(!(await status(m,cache)).ready)throw Error('Incomplete blocking assets');return {refreshed:count,caches:1}; + const CACHE = 'ytplayer-assets'; + const STATE = '/__ytp_asset_state'; + const url = (path, file) => path + '?v=' + file.h; + + function paths(manifest) { + return [...new Set(Object.values(manifest.groups).flatMap(group => group.files))].sort(); } - async function state(cache){const r=await cache.match(STATE);return r?await r.json():null;} - async function commit(m,cache){if(!(await status(m,cache)).ready)throw Error('Incomplete blocking assets');const old=await state(cache);const previous=old?.current?.buildTag===m.buildTag?old.previous:old?.current;await cache.put(STATE,new Response(JSON.stringify({current:m,previous}),{headers:{'Content-Type':'application/json'}}));const keep=retained(m,previous);for(const req of await cache.keys()){const u=new URL(req.url);const k=u.pathname+u.search;if(u.searchParams.has('v')&&!keep.has(k))await cache.delete(k);}return {current:m,previous};} - const api={CACHE,STATE,url,paths,blocking,plan,retained,status,syncAssets,state,commit}; - if(typeof module!=='undefined'&&module.exports)module.exports=api;else root.AssetSyncCore=api; -})(typeof globalThis!=='undefined'?globalThis:this); + + function blocking(manifest, previous, activeLayout) { + return [...new Set(Object.entries(manifest.groups) + .filter(([name, group]) => name === 'core' || !group.background || + name === 'layout:' + activeLayout || + (previous?.groups[name] && previous.groups[name].contract !== group.contract)) + .flatMap(([, group]) => group.files))].sort(); + } + + function plan(manifest, keys) { + const held = new Set(keys); + return { + missing: paths(manifest).map(path => url(path, manifest.files[path])).filter(key => !held.has(key)), + blocking: blocking(manifest).map(path => url(path, manifest.files[path])), + }; + } + + function retained(current, previous) { + const keep = new Set(paths(current).map(path => url(path, current.files[path]))); + if (previous) for (const path of paths(previous)) { + if (current.files[path]?.h !== previous.files[path].h) keep.add(url(path, previous.files[path])); + } + return keep; + } + + async function state(cache) { + const response = await cache.match(STATE); + return response ? response.json() : null; + } + + async function status(manifest, cache, { previous, activeLayout } = {}) { + const found = await Promise.all(blocking(manifest, previous, activeLayout).map(async path => { + const response = await cache.match(url(path, manifest.files[path])); + return !!response && response.headers.get('X-Asset-Hash') === manifest.files[path].h; + })); + const missing = found.filter(value => !value).length; + return { ready: missing === 0, missing, version: manifest.buildTag }; + } + + async function syncAssets(manifest, { cache, fetchFn, concurrency = 6, attempts = 3, activeLayout }) { + const previous = (await state(cache))?.current; + const missing = []; + for (const path of blocking(manifest, previous, activeLayout)) { + const key = url(path, manifest.files[path]); + const response = await cache.match(key); + if (!response || response.headers.get('X-Asset-Hash') !== manifest.files[path].h) missing.push(key); + } + const count = missing.length; + let failure; + await Promise.all(Array.from({ length: Math.max(1, Math.min(6, concurrency, count)) }, async () => { + while (missing.length && !failure) { + const key = missing.shift(); + let error; + for (let attempt = 0; attempt < Math.min(3, attempts); attempt++) { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), 30000); + try { + const response = await fetchFn(key, { credentials: 'same-origin', signal: controller.signal }); + if (!response.ok || response.headers.get('X-Asset-Hash') !== key.split('v=')[1]) { + throw new Error('Asset hash mismatch: ' + key); + } + // Keep the timeout through body consumption, not just response headers. + await cache.put(key, response); + error = null; + break; + } catch (err) { error = err; } + finally { clearTimeout(timer); } + } + if (error) failure = error; + } + })); + if (failure) throw failure; + if (!(await status(manifest, cache, { previous, activeLayout })).ready) throw new Error('Incomplete blocking assets'); + return { refreshed: count, caches: 1 }; + } + + async function commit(manifest, cache, { previousClients, activeLayout } = {}) { + const old = await state(cache); + if (!(await status(manifest, cache, { previous: old?.current, activeLayout })).ready) { + throw new Error('Incomplete blocking assets'); + } + const sameBuild = old?.current?.buildTag === manifest.buildTag; + const previous = sameBuild ? old.previous : old?.current; + const next = { + current: manifest, previous, + previousClients: previousClients || (sameBuild ? old.previousClients : []), + }; + // One state write publishes the complete build and its old-tab affinity. + await cache.put(STATE, new Response(JSON.stringify(next), { headers: { 'Content-Type': 'application/json' } })); + const keep = retained(manifest, previous); + for (const request of await cache.keys()) { + const parsed = new URL(request.url); + const key = parsed.pathname + parsed.search; + if (parsed.searchParams.has('v') && !keep.has(key)) await cache.delete(key); + } + return next; + } + + const api = { CACHE, STATE, url, paths, blocking, plan, retained, status, syncAssets, state, commit }; + if (typeof module !== 'undefined' && module.exports) module.exports = api; + else root.AssetSyncCore = api; +})(typeof globalThis !== 'undefined' ? globalThis : this); diff --git a/frontend/asset-sync-core.test.js b/frontend/asset-sync-core.test.js index 1b62137..a34a871 100644 --- a/frontend/asset-sync-core.test.js +++ b/frontend/asset-sync-core.test.js @@ -7,3 +7,6 @@ const response=h=>new Response(h,{headers:{'X-Asset-Hash':h}}); test('exact diff shares unchanged URLs; retains N-1 and prunes N-2',()=>{assert.deepEqual(core.plan(manifest(),['/a.js?v=a']).missing,['/index.html?v=b']);assert.deepEqual([...core.retained(manifest('c'),manifest())].sort(),['/a.js?v=a','/a.js?v=c','/index.html?v=b']);}); test('interrupted sync resumes verified files and refuses a mismatched hash',async()=>{const c=cache();let fail=true;let calls=[];const fetchFn=async u=>{calls.push(u);if(u.includes('index')&&fail)return response('wrong');return response(u.split('=')[1])};await assert.rejects(core.syncAssets(manifest(),{cache:c,fetchFn}),/hash/);assert.ok(await c.match('/a.js?v=a'));fail=false;calls=[];await core.syncAssets(manifest(),{cache:c,fetchFn});assert.deepEqual(calls,['/index.html?v=b']);await c.delete('/a.js?v=a');assert.equal((await core.status(manifest(),c)).missing,1);}); test('commit is atomic and pruning keeps only current and previous changed versions',async()=>{const c=cache();await c.put('/a.js?v=z',response('z'));await core.syncAssets(manifest(),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest(),c);await core.syncAssets(manifest('c'),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest('c'),c);assert.ok(await c.match('/a.js?v=a'));assert.equal(await c.match('/a.js?v=z'),undefined);await core.syncAssets(manifest('d'),{cache:c,fetchFn:async u=>response(u.split('=')[1])});await core.commit(manifest('d'),c);assert.equal(await c.match('/a.js?v=a'),undefined);}); +test('downloads are capped at six and each failure gets three attempts',async()=>{const c=cache(),files={},list=[];for(let i=0;i<13;i++){const p='/'+i+'.js';files[p]={h:String(i)};list.push(p)}const m={buildTag:'pool',files,groups:{core:{files:list}}};let active=0,max=0;const tries={};await core.syncAssets(m,{cache:c,concurrency:20,fetchFn:async u=>{active++;max=Math.max(max,active);await new Promise(r=>setTimeout(r,5));active--;tries[u]=(tries[u]||0)+1;if(tries[u]<3)throw Error('drop');return response(u.split('=')[1])}});assert.equal(max,6);assert.ok(Object.values(tries).every(n=>n===3));}); +test('background files do not block, but active layout and contract changes do',()=>{const m=manifest();m.groups.extra={background:true,contract:2,files:['/extra.js']};m.files['/extra.js']={h:'e'};assert.deepEqual(core.blocking(m),['/a.js','/index.html']);assert.ok(core.blocking(m,{groups:{extra:{contract:1}}}).includes('/extra.js'));m.groups['layout:classic']={background:true,files:['/classic.css']};m.files['/classic.css']={h:'c'};assert.ok(core.blocking(m,null,'classic').includes('/classic.css'));}); +test('removed files survive one previous build for open tabs',()=>{const previous=manifest(),current=manifest('c');delete current.files['/a.js'];current.groups.core.files=['/index.html'];assert.ok(core.retained(current,previous).has('/a.js?v=a'));}); diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index f7cc057..667c887 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -2,11 +2,11 @@ const {test}=require('node:test');const assert=require('node:assert/strict');con function environment(){ const stores=new Map(),listeners={},messages=[],skips=[];const m={buildTag:'next',files:{'/index.html':{h:'index'},'/app.js':{h:'app'}},groups:{core:{files:['/index.html','/app.js']}}}; const storage={async keys(){return [...stores.keys()]},async delete(n){return stores.delete(n)},async open(n){if(!stores.has(n)){const map=new Map();stores.set(n,{async match(k){return map.get(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)?.clone()},async put(k,r){map.set(k,r.clone())},async keys(){return [...map.keys()].map(k=>({url:'https://local'+k}))},async delete(k){return map.delete(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)}})}return stores.get(n)}}; - const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':u.split('v=')[1]}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; + const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':m.files[u.split('?')[0]]?.h || ''}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; vm.runInNewContext(fs.readFileSync(__dirname+'/sw.js','utf8'),sandbox); async function dispatch(t,e={}){let p;listeners[t]({...e,waitUntil:v=>p=v});await p} async function request(url,mode='cors',clientId='new'){let p;listeners.fetch({request:{url:'https://local'+url,method:'GET',mode},clientId,respondWith:v=>p=v});return p} return {storage,m,skips,dispatch,request}; } -test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);}); +test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal(reply.missing,1);assert.equal(reply.version,'next');assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);assert.equal((await e.request('/app.js?v=stale')).status,409);}); test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); diff --git a/frontend/sw.js b/frontend/sw.js index f41b7ff..43e7d6b 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -306,7 +306,7 @@ self.addEventListener('message', (e) => { e.waitUntil((async () => { if (ASSET_SYNC) { let reply = { ready: false, missing: -1, version: VERSION }; - try { const cache = await caches.open(AssetSyncCore.CACHE); const m = await candidate(cache); if(m) reply = await AssetSyncCore.status(m,cache); } catch {} + try { const cache = await caches.open(AssetSyncCore.CACHE); const m = await candidate(cache) || (await AssetSyncCore.state(cache))?.current; if(m) reply = await AssetSyncCore.status(m,cache); } catch {} reply.type = 'CACHE_STATUS'; reply.assetSync = true; if(e.ports && e.ports[0]) e.ports[0].postMessage(reply); else if(e.source) e.source.postMessage(reply); return; @@ -488,9 +488,8 @@ async function activateAssets() { const cache = await caches.open(AssetSyncCore.CACHE), m = await candidate(cache); if (!m) throw Error('Missing candidate manifest'); const names = await migrateLegacy(cache,m), old = await AssetSyncCore.state(cache); - const state = await AssetSyncCore.commit(m,cache); - state.previousClients = (await self.clients.matchAll({type:'window'})).map(c=>c.id); - await cache.put(AssetSyncCore.STATE,new Response(JSON.stringify(state))); + const previousClients = (await self.clients.matchAll({type:'window'})).map(c=>c.id); + await AssetSyncCore.commit(m,cache,{previousClients}); // Legacy deletion occurs strictly after verified commit. await Promise.all(names.map(n => caches.delete(n))); for (const req of await cache.keys()) if(new URL(req.url).pathname.startsWith('/__ytp_candidate/')) await cache.delete(req); @@ -509,7 +508,7 @@ async function assetFetch(request, clientId) { if(!nav && state.previousClients?.includes(clientId) && state.previous?.files[u.pathname]) m = state.previous; let path = nav ? '/index.html' : u.pathname; let key; - if(u.searchParams.has('v') && !nav) { + if(u.searchParams.has('v') && state.current.files[u.pathname]) { key = u.pathname + u.search; if(state.previous?.legacyURLs && u.searchParams.get('v') === state.previous.buildTag) key = state.previous.legacyURLs[path] || key; } else if(m.files[path]) key = AssetSyncCore.url(path,m.files[path]); @@ -517,7 +516,7 @@ async function assetFetch(request, clientId) { const cached = await cache.match(key); const h = new URL(key,self.location.origin).searchParams.get('v'); if(cached && cached.headers.get('X-Asset-Hash') === h) return cached; - try { const r = await fetch(key); if(r.ok && r.headers.get('X-Asset-Hash') === h) await cache.put(key,r.clone()); return r; } catch { return new Response('Offline',{status:503}); } + try { const r = await fetch(key); if(r.ok && r.headers.get('X-Asset-Hash') !== h) return new Response('Asset version unavailable',{status:409}); if(r.ok && request.method !== 'HEAD') await cache.put(key,r.clone()); return r; } catch { return new Response('Offline',{status:503}); } } try { return await fetch(request); } catch { return new Response('Offline',{status:503}); } } From bb446c717f92ef912f5000ddc757b9d1071120dc Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Wed, 7 Oct 2026 23:58:29 +0800 Subject: [PATCH 12/81] Keep single-tag rollback on the legacy worker path --- server/asset-manifest.js | 2 ++ server/asset-manifest.test.js | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/server/asset-manifest.js b/server/asset-manifest.js index 22e4384..6df5494 100644 --- a/server/asset-manifest.js +++ b/server/asset-manifest.js @@ -27,6 +27,8 @@ export function stampIndex(source, files, { hashing = true, buildTag = '__BUILD_ } export function createAssetManifest(publicDir = './public', { hashing = true, buildTag: override, assetSync = true } = {}) { + // Single-tag URLs cannot be verified against per-file URL hashes. + assetSync = hashing && assetSync; const bytes = new Map(); const legacy = createHash('sha256'); function walk(dir, prefix = '') { diff --git a/server/asset-manifest.test.js b/server/asset-manifest.test.js index 0b03375..c09a7a3 100644 --- a/server/asset-manifest.test.js +++ b/server/asset-manifest.test.js @@ -68,3 +68,7 @@ test('sync rollback changes build identity and injected worker byte hash', () => expect(on.manifest.buildTag).not.toBe(off.manifest.buildTag); expect(off.manifest.files['/sw.js'].h).toBe(hash(off.sw)); })); +test('single-tag hashing rollback also selects the legacy worker', () => fixture(dir => { + writeFileSync(join(dir,'sw.js'), "const VERSION = typeof __BUILD_TAG__ !== 'undefined' ? __BUILD_TAG__ : 'old'; const SYNC = typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true;"); + expect(createAssetManifest(dir,{hashing:false}).sw).toContain('const SYNC = false'); +})); From 5d1e5ec791fc76f85c1893639eefe978461d7f14 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 00:03:14 +0800 Subject: [PATCH 13/81] Verify explicit activation and legacy incremental migration --- frontend/asset-worker.test.js | 2 +- frontend/sw-update.js | 8 +++- frontend/sw-update.test.js | 6 +++ frontend/sw.js | 10 ++--- perf/baseline.mjs | 5 +++ perf/migration.mjs | 71 ++++++++++++++++++++++++++++++++--- perf/proxy.mjs | 10 ++++- 7 files changed, 96 insertions(+), 16 deletions(-) diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index 667c887..193a31a 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -9,4 +9,4 @@ function environment(){ return {storage,m,skips,dispatch,request}; } test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal(reply.missing,1);assert.equal(reply.version,'next');assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);assert.equal((await e.request('/app.js?v=stale')).status,409);}); -test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); +test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); diff --git a/frontend/sw-update.js b/frontend/sw-update.js index e4b195e..d40de07 100644 --- a/frontend/sw-update.js +++ b/frontend/sw-update.js @@ -1,7 +1,7 @@ /* ============================================================================ * sw-update — makes "Refresh UI" actually land the new build. * - * Framework-free and dependency-free on purpose (same pattern as + * Framework-free, with a shared sync core and a legacy fallback (same pattern as * async-guard.js): * • Loads as a plain '); + const result=createAssetManifest(dir); + const map=JSON.parse(result.index.match(/id="ytp-assets">([^<]+)<\/script>/)[1]); + expect(map.buildTag).toBe(result.manifest.buildTag); + expect(map.groups).toEqual(result.manifest.groups); + expect(map.files['/app.js'].h).toBe(result.manifest.files['/app.js'].h); + expect(map.files['/index.html']).toBeUndefined(); + expect(map.files['/sw.js']).toBeUndefined(); + expect(createAssetManifest(dir).manifest).toEqual(result.manifest); + expect(result.manifest.files['/index.html'].h).toBe(hash(result.index)); + const off=createAssetManifest(dir,{hashing:false}); + const legacy=JSON.parse(off.index.match(/id="ytp-assets">([^<]+)<\/script>/)[1]); + expect(legacy.files['/app.js'].h).toBe(off.manifest.buildTag); +})); From 5d6a1545df3fa2c39809bf77293df51a7a4b6765 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 01:29:50 +0800 Subject: [PATCH 21/81] Load layouts and optional features from staged asset caches --- frontend/app.js | 84 +++++++++++++------ frontend/asset-sync-core.js | 11 ++- frontend/asset-sync-core.test.js | 11 +++ frontend/asset-worker.test.js | 27 +++++- frontend/assets.json | 127 +++++++++++++++++++++++------ frontend/car-mode.js | 8 +- frontend/direct-media.js | 2 +- frontend/direct-recv-worker.js | 2 +- frontend/eq-core.js | 19 +---- frontend/eq-parameters.js | 25 ++++++ frontend/f7-layout.js | 2 +- frontend/feature-bootstrap.js | 77 +++++++++++++++++ frontend/hash-worker.js | 2 +- frontend/index.html | 36 +------- frontend/lazy.js | 70 +++++++++++++--- frontend/lazy.test.js | 13 +++ frontend/lyrics-window.js | 2 +- frontend/opfs-worker.js | 7 +- frontend/opfs.js | 2 +- frontend/p2p-client.js | 4 +- frontend/p2p-recv-worker.js | 2 +- frontend/p2p-transfer.js | 2 +- frontend/piano.js | 2 +- frontend/settings-sections.js | 11 ++- frontend/sha256.js | 2 +- frontend/shell-consistency.test.js | 18 +++- frontend/sw-update.js | 7 +- frontend/sw.js | 55 ++++++++++++- frontend/worker-imports.test.js | 12 +++ server/static-delivery.test.js | 16 +++- 30 files changed, 512 insertions(+), 146 deletions(-) create mode 100644 frontend/eq-parameters.js create mode 100644 frontend/feature-bootstrap.js create mode 100644 frontend/worker-imports.test.js diff --git a/frontend/app.js b/frontend/app.js index 2145032..26c2594 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -1666,7 +1666,10 @@ function applyAppearance() { root.dataset.density = s.density || 'comfortable'; root.dataset.perf = s.perfMode ? 'on' : 'off'; root.dataset.motion = s.reduceMotion ? 'reduced' : 'full'; - root.dataset.layout = s.layout || 'classic'; + const desiredLayout=s.layout || 'classic'; + if(root.dataset.layout!==desiredLayout && !Lazy.loaded('layout:'+desiredLayout)) { + Lazy.load('layout:'+desiredLayout).then(()=>{if((data.settings.layout||'classic')===desiredLayout)applyAppearance();}).catch(error=>toast(error.message)); + } else root.dataset.layout=desiredLayout; } function fmtBytes(n) { if (!n) return '0 B'; @@ -2056,7 +2059,8 @@ async function deleteCustomVideo(id) { // Open the editor modal for a source video. `duration` seconds is needed to // compute keep segments; we take it from the live player when the video is // currently playing, else from the card metadata. -function openVideoEditor(source) { +async function openVideoEditor(source) { + try { await Lazy.load('feature:video-edit'); } catch (error) { toast(error.message); return; } if (!(WEB && window.OPFS && window.OPFS.isSupported())) { toast('⚠ Editing needs offline storage, which this browser doesn’t support'); return; @@ -3135,6 +3139,7 @@ async function renderAvailability(id) { const el = $('npAvail'); if (!el) return; const off = data.settings.p2pShare === false && data.settings.p2pReceive === false; + if (WEB && !off && navigator.onLine !== false && id && !window.P2PCore) { try { await Lazy.load('feature:p2p'); } catch {} } if (!WEB || !window.P2PCore || off || navigator.onLine === false || String(id).startsWith('edit_')) { el.classList.add('hidden'); return; @@ -3161,6 +3166,7 @@ async function renderAvailability(id) { // Fetch a verified copy from another device (docs/p2p-architecture.md flow 6). // Download-then-play: on success the file is saved offline like any save. async function getFromPeers(videoObj, c, peers, onProgress) { + try { await Lazy.load('feature:direct'); } catch (error) { toast(error.message); return false; } if (window.DirectMedia && !DirectMedia.enabled()) { toast('Direct device transfer is off. Enable it in Settings or use a server copy.'); return false; } if (window.DirectMedia?.enabled()) { const ok = await DirectMedia.obtain(videoObj.id); if (!ok) toast('Pair the source device through Remote or use the same profile to receive its saved copy.'); return !!ok; } const id = videoObj.id; @@ -3186,6 +3192,7 @@ async function getFromPeers(videoObj, c, peers, onProgress) { // Offered when a video won't load: only if some device holding it is online now. async function offerPeerDownload(videoObj) { + if (WEB && data.settings.p2pReceive !== false) { try { await Lazy.load('feature:p2p'); } catch { return; } } if (!WEB || !window.P2PTransfer || !window.P2PCore || data.settings.p2pReceive === false) return; const id = videoObj && videoObj.id; if (!id || videoObj.custom || cachedIds.has(id)) return; @@ -5035,7 +5042,8 @@ const Remote = (() => { body.querySelector('[data-act="unpair"]').classList.toggle('hidden', !live); } - function openHostModal() { + async function openHostModal() { + try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } const body = document.createElement('div'); body.className = 'remote-host'; body.innerHTML = ` @@ -5306,7 +5314,8 @@ const Remote = (() => { } } - function openRemoteView({ code = '' } = {}) { + async function openRemoteView({ code = '' } = {}) { + try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } rc.open = true; rc.seekTimer = VisibleTimer.setIntervalWhenVisible(renderSeek, 500); // This phone is the remote now — don't also play here. @@ -5918,7 +5927,8 @@ const StatsTrack = (() => { } function tick(cur) { const meta = current && current.meta; - if (!meta || !meta.id || !window.StatsCore) return; + if (!meta || !meta.id) return; + if (!window.StatsCore) { Lazy.load('feature:stats').catch(() => {}); return; } if (meta.id !== st.id) { commit(false); st.id = meta.id; @@ -5949,7 +5959,9 @@ const StatsTrack = (() => { // ============================================================================ // Stats view // ============================================================================ -function renderStats() { +async function renderStats() { + try { await Lazy.load('feature:stats'); } catch (error) { toast(error.message); return; } + if (view.type !== 'stats') return; StatsTrack.flush(); els.listTitle.textContent = 'Stats'; resetListHeaderExtras(); @@ -6679,8 +6691,8 @@ const EqRender = (() => { const g = EQ.gains(); const lufs = Level.enabled() ? Level.remembered(id) : null; const levelDb = lufs == null ? 0 : Math.round(Level.gainFor(lufs) * 2) / 2; - const vocal = VocalReducer.amount(data.settings.vocalLevel ?? 100); - const width = EqCore.width(data.settings.stereoWidth); + const vocal = EqParameters.amount(data.settings.vocalLevel ?? 100); + const width = EqParameters.width(data.settings.stereoWidth); if (g.every((v) => v === 0) && Math.abs(levelDb) < 0.5 && vocal === 100 && width === 0) return null; return { gains: g, levelDb, vocal, width, sig: g.join(',') + '|' + levelDb + '|vocal:' + vocal + '|width:' + width }; } @@ -6719,7 +6731,7 @@ const EqRender = (() => { function writeViaWorker(name, buffer) { return new Promise((resolve, reject) => { - const w = new Worker('/opfs-worker.js'); + const w = Lazy.worker('/opfs-worker.js'); w.onmessage = (e) => { w.terminate(); (e.data && e.data.type === 'written') ? resolve() : reject(new Error((e.data && e.data.error) || 'write failed')); }; w.onerror = () => { w.terminate(); reject(new Error('worker failed')); }; w.postMessage({ op: 'write', dir: DIR, name, buffer }, [buffer]); @@ -6731,6 +6743,7 @@ const EqRender = (() => { const w = wanted(id); if (!w) { await drop(id); return; } if (readMap()[id] === w.sig) return; + await loadSoundFeatures(); const file = await window.OPFS.getFileObject(id); if (!file) return; const buf = await file.arrayBuffer(); @@ -6834,8 +6847,9 @@ const PiP = (() => { // is chosen (createMediaElementSource can't be undone; afterwards "Flat" // simply zeroes the gains). Disabled on iOS: Safari suspends Web Audio when // the screen locks, which would silence background playback. -const EQ_BANDS = EqCore.bands; -const EQ_PRESETS = EqCore.presets; +const loadSoundFeatures=()=>Promise.all([Lazy.load('feature:eq-core'),Lazy.load('feature:vocal-reducer')]); +const EQ_BANDS = EqParameters.bands; +const EQ_PRESETS = EqParameters.presets; const EQ = (() => { const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); const AC = window.AudioContext || window.webkitAudioContext; @@ -6850,12 +6864,16 @@ const EQ = (() => { const rendered = () => !!(current && current.eqAudioUrl); const gains = () => { const g = data.settings.eq && Array.isArray(data.settings.eq.g) ? data.settings.eq.g : EQ_PRESETS.flat.g; - return EqCore.migrate(g); + return EqParameters.migrate(g); }; const isFlat = () => gains().every((v) => v === 0); function build() { if (st.ctx) return true; + if (!Lazy.loaded('feature:eq-core') || !Lazy.loaded('feature:vocal-reducer')) { + loadSoundFeatures().then(()=>{apply(); Level.apply();}).catch(error=>toast(error.message)); + return false; + } try { st.ctx = new AC(); st.filters = EQ_BANDS.map((b) => { @@ -6893,7 +6911,7 @@ const EQ = (() => { // Apply the stored curve; wires the graph up the first time it's non-flat. function apply() { if (!available()) return; - if (!st.ctx && isFlat() && VocalReducer.amount(data.settings.vocalLevel ?? 100) === 100 && EqCore.width(data.settings.stereoWidth) === 0) return; + if (!st.ctx && isFlat() && EqParameters.amount(data.settings.vocalLevel ?? 100) === 100 && EqParameters.width(data.settings.stereoWidth) === 0) return; if (!build()) return; attach(els.video); attach(els.audio); @@ -6921,7 +6939,8 @@ const EQ = (() => { if (typeof EqRender !== 'undefined') EqRender.scheduleAll(); } - function open() { + async function open() { + try { await loadSoundFeatures(); } catch(error) { toast(error.message); return; } const body = document.createElement('div'); body.className = 'eq-panel'; if (!AC) { @@ -7795,7 +7814,7 @@ const Party = (() => { function setStatus(t) { const el = $('ptStatus'); if (el) el.textContent = t; } function sysMsg(text) { st.chat.push({ sys: true, text, at: Date.now() }); renderChat(); } function link() { return `${location.origin}/?party=${st.code}`; } - function showPanel() { $('partyPanel').classList.remove('hidden'); st.minimized = false; $('partyPanel').classList.remove('min'); render(); } + function showPanel() { Lazy.load('feature:party-dj').then(render).catch(error=>toast(error.message)); Lazy.load('feature:direct').catch(error=>toast(error.message)); $('partyPanel').classList.remove('hidden'); st.minimized = false; $('partyPanel').classList.remove('min'); render(); } function render() { const panel = $('partyPanel'); @@ -7836,7 +7855,7 @@ const Party = (() => {
`; const dj = document.createElement('div'); panel.querySelector('.pt-body').append(dj); - PartyDJ.render(dj, { state: st.dj, host: isHost(), pid, send, search: async q => { const result = await API.search(q); return result.results || result.videos || []; } }); + if (Lazy.loaded('feature:party-dj')) PartyDJ.render(dj, { state: st.dj, host: isHost(), pid, send, search: async q => { const result = await API.search(q); return result.results || result.videos || []; } }); renderChat(); } function renderChat() { @@ -9104,6 +9123,7 @@ function addBrowseCta(empty, label) { // through the server. Buttons appear only when the file is ready so each one // runs inside its own tap (the share sheet needs a fresh user gesture). async function exportToDevice(video) { + try { await Lazy.load('feature:export'); } catch(error) { toast(error.message); return; } if (!video || !video.id || !window.DeviceExport) return; const id = video.id; const title = video.title || videoTitleById(id) || id; @@ -9869,7 +9889,12 @@ async function renderSettings() { // ---- Wire appearance / accessibility ---- $('setTheme').addEventListener('change', (e) => { data.settings.theme = e.target.value; applyAppearance(); persist(); }); - $('setLayout').addEventListener('change', (e) => { data.settings.layout = e.target.value; applyAppearance(); persist(); }); + $('setLayout').addEventListener('change', async (e) => { + const select=e.target, next=select.value, previous=data.settings.layout; select.disabled=true; + try { await Lazy.load('layout:'+next); data.settings.layout=next; Lazy.layout=next; if(WEB)saveDataToStorage(JSON.stringify(data)); applyAppearance(); persist(); Lazy.reportLayout?.(); } + catch(error) { select.value=previous; toast(error.message); } + finally { select.disabled=false; } + }); $('setFont').addEventListener('change', (e) => { data.settings.fontScale = e.target.value; applyAppearance(); persist(); }); $('setParallelSaves').addEventListener('change', (e) => { data.settings.parallelSaves = Number(e.target.value) || 4; persist(); SaveSlots.pump(); }); $('setDensity').addEventListener('change', (e) => { data.settings.density = e.target.value; applyAppearance(); persist(); }); @@ -11118,7 +11143,7 @@ function wireUI() { // ---- Empty-home playlist grid ---- $('homePlNewBtn').addEventListener('click', () => newPlaylist(null)); - const importSetlist = document.createElement('button'); importSetlist.type = 'button'; importSetlist.className = 'icon-btn'; importSetlist.textContent = '⇥'; importSetlist.title = 'Import setlist'; importSetlist.setAttribute('aria-label', 'Import setlist'); importSetlist.onclick = () => SetlistImport.open(); els.newPlaylistBtn.after(importSetlist); + const importSetlist = document.createElement('button'); importSetlist.type = 'button'; importSetlist.className = 'icon-btn'; importSetlist.textContent = '⇥'; importSetlist.title = 'Import setlist'; importSetlist.setAttribute('aria-label', 'Import setlist'); importSetlist.onclick = () => SetlistImport.open(); els.newPlaylistBtn.after(importSetlist); Lazy.intent(importSetlist,'feature:setlist-import'); $('homePlGrid').addEventListener('scroll', updateHomeGridScrollState, { passive: true }); window.addEventListener('resize', updateHomeGridScrollState); @@ -12267,7 +12292,7 @@ async function applyUpdate(target, { quiet = false } = {}) { const reg = _swReg || (('serviceWorker' in navigator) ? await navigator.serviceWorker.getRegistration() : null); const SU = window.SwUpdate; const reload = () => window.location.reload(); - if (!SU) { reload(); return; } // helper failed to load (flaky link): a reload is the best we can do + if (!SU) throw new Error('Update helper unavailable; try Refresh UI again when paused'); await SU.applyUpdate({ reg, container: navigator.serviceWorker, @@ -12342,6 +12367,7 @@ async function registerServiceWorker() { // cached copy of sw.js — the server always returns it fresh (no-store). const reg = await navigator.serviceWorker.register('/sw.js', { updateViaCache: 'none' }); _swReg = reg; + Lazy.reportLayout(reg); // A waiting worker only means "update pending" when this page is already // controlled by a previous SW. On a FIRST install (fresh visit, or right @@ -12588,6 +12614,7 @@ async function boot() { // and re-render only if something actually changed. syncOnLaunch(); startPlaylistInboxWatch(); + if(LowerThird.active()) await Lazy.load('feature:lower-third'); Presenter.boot(); if (LowerThird.active()) return; SectionRail.boot(); @@ -12617,7 +12644,7 @@ async function boot() { PiP.render(); LyricsWindow.configure({ prepare: () => { if (!isServiceModeOpen()) Notes.stageLyrics.set(true); }, view: () => isServiceModeOpen() && data.settings.serviceLyrics ? $('serviceLyrics') : $('stageLyrics'), line: () => $('serviceLyricsList')?.querySelector('.active')?.textContent || $('stageLyricsList')?.querySelector('.active')?.textContent || current?.meta?.title || 'Nothing playing', toggle: () => { Player.toggle(); updatePlayBtn(); }, next: playNext, refresh: () => { Notes.stageLyrics.render(true); Notes.serviceRefresh(); }, toast }); EQ.renderButton(); - if (data.settings.eq?.g?.length === 5) { data.settings.eq.g = EqCore.migrate(data.settings.eq.g); persist(); } + if (data.settings.eq?.g?.length === 5) { data.settings.eq.g = EqParameters.migrate(data.settings.eq.g); persist(); } EQ.apply(); EqCore.register({ settings: () => data.settings, persist, open: EQ.open, apply: () => { EQ.apply(); EqRender.scheduleAll(); } }); VocalReducer.register({ settings: () => data.settings, persist, apply: () => { EQ.apply(); EqRender.scheduleAll(); } }); @@ -12630,6 +12657,8 @@ async function boot() { else if (action === 'panic') MidiPedals.fade({ volume: Player.soundEl.volume, setVolume: v => { Player.soundEl.volume = v; }, pause: () => { Player.pause(); updatePlayBtn(); }, restore: () => Player.applyVolume() }); } }); applyAppearance(); + Lazy.load('layout:'+data.settings.layout).then(()=>{ if(window.BentoHub)BentoHub.playlists=()=>data.playlists||[]; renderSidebar(); }).catch(error=>toast(error.message)); + if(data.settings.midiEnabled)Lazy.load('feature:midi').catch(error=>toast(error.message)); CarMode.configure({ input: els.searchInput, search: () => els.searchForm.requestSubmit(), toast, state: () => ({ title: current?.meta?.title || '', paused: Player.master?.paused !== false }), action: action => { if (action === 'toggle') { Player.toggle(); updatePlayBtn(); } else if (action === 'next') playNext(); else if (action === 'prev') playPrev(); else if (action === 'back') Player.seek(Math.max(0, (Player.master.currentTime || 0) - 15)); } }); updateProfileStatus(); updateLoopRepeatButtons(); @@ -12643,10 +12672,12 @@ async function boot() { await refreshCachedIds(); startCacheResyncWatch(); // Peer-to-peer: report what this device holds (on by default; settings.p2pShare). - if (WEB && window.P2PClient) { - window.P2PClient.start({ getSettings: () => data.settings, getProfile: () => (data.profile && data.profile.name) || '', getProfileSecret: () => ProfileSecret.getFor(data.profile?.name) }); - if (window.P2PTransfer) window.P2PTransfer.start({ canShare: () => false }); // New scoped invitations replace the unconfirmed legacy sender. - } + Lazy.onLoad('feature:p2p', () => { if (WEB) { + window.P2PClient.start({ getSettings: () => data.settings, getProfile: () => (data.profile && data.profile.name) || '', getProfileSecret: () => ProfileSecret.getFor(data.profile?.name), initialDelay: 0 }); + if (window.P2PTransfer) window.P2PTransfer.start({ canShare: () => false }); // Scoped invitations preserve receiver confirmation. + } }); + // Preserve the existing eight-second sharing startup without parsing transport at boot. + if (WEB) setTimeout(() => Lazy.load('feature:direct').catch(error=>console.warn(error.message)),8000); data.playlists.forEach(preloadPlaylist); preloadPinnedPlaylists(); updateBottomChrome(); @@ -12675,6 +12706,11 @@ async function boot() { if (WEB) checkUpdateOutcome(); registerServiceWorker(); if (WEB) pollBuildTag(); + window.addEventListener('ytp-reload-required',()=>checkBuildTag()); + window.addEventListener('ytp-lazy-error',event=>{ toast(event.detail?.error?.message||'Feature unavailable; try Refresh UI'); checkBuildTag(); }); + Lazy.intent($('navPartyBtn'),'feature:party-dj'); Lazy.intent($('navRemoteBtn'),'feature:direct'); + Lazy.intent($('remoteChip'),'feature:direct'); Lazy.intent($('eqBtn'),'feature:eq-core'); + Lazy.reportLayout?.(); Lazy.warm?.(); if (WEB) { fetch('/api/user/sync', { method: 'POST', diff --git a/frontend/asset-sync-core.js b/frontend/asset-sync-core.js index 20671af..e8d951c 100644 --- a/frontend/asset-sync-core.js +++ b/frontend/asset-sync-core.js @@ -10,11 +10,13 @@ } function blocking(manifest, previous, activeLayout) { - return [...new Set(Object.entries(manifest.groups) + const names = new Set(Object.entries(manifest.groups) .filter(([name, group]) => name === 'core' || !group.background || name === 'layout:' + activeLayout || (previous?.groups[name] && previous.groups[name].contract !== group.contract)) - .flatMap(([, group]) => group.files))].sort(); + .map(([name]) => name)); + for (const name of names) for (const dependency of manifest.groups[name].dependencies || []) names.add(dependency); + return [...new Set([...names].flatMap(name => manifest.groups[name].files))].sort(); } function plan(manifest, keys) { @@ -26,9 +28,10 @@ } function retained(current, previous) { - const keep = new Set(paths(current).map(path => url(path, current.files[path]))); + const currentPaths = new Set(paths(current)); + const keep = new Set([...currentPaths].map(path => url(path, current.files[path]))); if (previous) for (const path of paths(previous)) { - if (current.files[path]?.h !== previous.files[path].h) keep.add(url(path, previous.files[path])); + if (!currentPaths.has(path) || current.files[path]?.h !== previous.files[path].h) keep.add(url(path, previous.files[path])); } return keep; } diff --git a/frontend/asset-sync-core.test.js b/frontend/asset-sync-core.test.js index 1e6979a..2c9a9d4 100644 --- a/frontend/asset-sync-core.test.js +++ b/frontend/asset-sync-core.test.js @@ -34,3 +34,14 @@ test('background synchronization fills all groups without publishing a new curre assert.ok(await c.match('/extra.js?v=e')); assert.deepEqual(await core.state(c), before); }); + +test('active layouts also block on shared dependencies, while other layouts stay background', () => { + const m=manifest(); m.groups['layout:glass-stage']={contract:1,background:true,files:['/glass.css'],dependencies:['feature:controls']}; m.groups['feature:controls']={contract:1,background:true,files:['/controls.js']}; m.groups['layout:bento-hub']={contract:1,background:true,files:['/bento.css']}; + for(const path of ['/glass.css','/controls.js','/bento.css'])m.files[path]={h:'h'}; + assert.deepEqual(core.blocking(m,null,'glass-stage'),['/a.js','/controls.js','/glass.css','/index.html']); +}); + +test('removing group membership retains the old tab URL even if the physical file is still shipped unchanged',()=>{ + const previous=manifest(),current=manifest();current.groups.core.files=['/index.html']; + assert.ok(core.retained(current,previous).has('/a.js?v=a')); +}); diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index 193a31a..48b9909 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -2,7 +2,7 @@ const {test}=require('node:test');const assert=require('node:assert/strict');con function environment(){ const stores=new Map(),listeners={},messages=[],skips=[];const m={buildTag:'next',files:{'/index.html':{h:'index'},'/app.js':{h:'app'}},groups:{core:{files:['/index.html','/app.js']}}}; const storage={async keys(){return [...stores.keys()]},async delete(n){return stores.delete(n)},async open(n){if(!stores.has(n)){const map=new Map();stores.set(n,{async match(k){return map.get(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)?.clone()},async put(k,r){map.set(k,r.clone())},async keys(){return [...map.keys()].map(k=>({url:'https://local'+k}))},async delete(k){return map.delete(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)}})}return stores.get(n)}}; - const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':m.files[u.split('?')[0]]?.h || ''}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; + const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,setTimeout,clearTimeout,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':m.files[u.split('?')[0]]?.h || ''}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; vm.runInNewContext(fs.readFileSync(__dirname+'/sw.js','utf8'),sandbox); async function dispatch(t,e={}){let p;listeners[t]({...e,waitUntil:v=>p=v});await p} async function request(url,mode='cors',clientId='new'){let p;listeners.fetch({request:{url:'https://local'+url,method:'GET',mode},clientId,respondWith:v=>p=v});return p} @@ -10,3 +10,28 @@ function environment(){ } test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal(reply.missing,1);assert.equal(reply.version,'next');assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);assert.equal((await e.request('/app.js?v=stale')).status,409);}); test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); + +test('staged same-contract responses use verified N-1 without poisoning the new URL',async()=>{ + const e=environment(); const cache=await e.storage.open(core.CACHE); + const old={buildTag:'old',files:{'/extra.js':{h:'old'}},groups:{core:{files:[],contract:1},'feature:extra':{files:['/extra.js'],contract:1,background:true}}}; + e.m.groups.core.contract=1; e.m.groups['feature:extra']={files:['/extra.js'],contract:1,background:true}; e.m.files['/extra.js']={h:'new'}; + await cache.put(core.STATE,Response.json({current:old})); await cache.put('/extra.js?v=old',new Response('old body',{headers:{'X-Asset-Hash':'old'}})); + await e.dispatch('install'); await e.dispatch('activate'); + assert.equal(await cache.match('/extra.js?v=new'),undefined); + const stale=await e.request('/extra.js?v=new'); assert.equal(await stale.text(),'old body');assert.equal(stale.headers.get('X-Asset-Hash'),'old');assert.equal(await cache.match('/extra.js?v=new'),undefined); + await e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:true}}); assert.equal(await cache.match('/extra.js?v=new'),undefined); + await e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}}); assert.equal((await cache.match('/extra.js?v=new')).headers.get('X-Asset-Hash'),'new'); + assert.equal((await e.request('/extra.js?v=new')).headers.get('X-Asset-Hash'),'new'); +}); + +test('a changed background contract is downloaded before ready and cannot fall back after commit',async()=>{ + const e=environment(),cache=await e.storage.open(core.CACHE); + const old={buildTag:'old',files:{'/extra.js':{h:'old'}},groups:{core:{files:[],contract:1},'feature:extra':{files:['/extra.js'],contract:1,background:true}}}; + e.m.groups.core.contract=1;e.m.groups['feature:extra']={files:['/extra.js'],contract:2,background:true};e.m.files['/extra.js']={h:'new'}; + await cache.put(core.STATE,Response.json({current:old}));await cache.put('/extra.js?v=old',new Response('old body',{headers:{'X-Asset-Hash':'old'}})); + await e.dispatch('install');assert.equal((await core.state(cache)).current.buildTag,'old'); + assert.equal((await cache.match('/extra.js?v=new')).headers.get('X-Asset-Hash'),'new'); + let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true); + await e.dispatch('activate');await cache.delete('/extra.js?v=new'); + const response=await e.request('/extra.js?v=new');assert.equal(response.headers.get('X-Asset-Hash'),'new');assert.notEqual(await response.text(),'old body'); +}); diff --git a/frontend/assets.json b/frontend/assets.json index 1326222..e845dec 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -51,18 +51,26 @@ "/fonts/HankenGrotesk-latin-ext.woff2", "/fonts/HankenGrotesk-latin.woff2", "/fonts/JetBrainsMono-latin-ext.woff2", - "/fonts/JetBrainsMono-latin.woff2" - ] + "/fonts/JetBrainsMono-latin.woff2", + "/lazy.js", + "/feature-bootstrap.js", + "/eq-parameters.js", + "/assets.json", + "/device-db.js" + ], + "background": false }, "layout:glass-stage": { "contract": 1, "eager": false, "files": [ "/theme-glass.css", - "/theme-glass-controls.css", - "/glass-controls.js", "/theme-glass-panel.css", "/glass-panel-layout.js" + ], + "background": true, + "dependencies": [ + "feature:layout-controls" ] }, "layout:classic": { @@ -70,7 +78,8 @@ "eager": false, "files": [ "/theme-classic.css" - ] + ], + "background": true }, "layout:bento-hub": { "contract": 1, @@ -80,6 +89,10 @@ "/bento-hub.js", "/fonts/PlusJakartaSans-latin.woff2", "/fonts/PlusJakartaSans-latin-ext.woff2" + ], + "background": true, + "dependencies": [ + "feature:layout-controls" ] }, "layout:f7-swipe": { @@ -87,9 +100,10 @@ "eager": false, "files": [ "/theme-f7.css", - "/f7-layout.js", - "/vendor/framework7-swipe.min.js" - ] + "/vendor/framework7-swipe.min.js", + "/f7-layout.js" + ], + "background": true }, "feature:piano": { "contract": 1, @@ -98,28 +112,32 @@ "/piano-core.js", "/piano.js", "/piano-engine.mjs" - ] + ], + "background": true }, "feature:midi": { "contract": 1, "eager": false, "files": [ "/midi.js" - ] + ], + "background": true }, "feature:party-dj": { "contract": 1, "eager": false, "files": [ "/party-dj.js" - ] + ], + "background": true }, "feature:lyrics-window": { "contract": 1, "eager": false, "files": [ "/lyrics-window.js" - ] + ], + "background": true }, "feature:lower-third": { "contract": 1, @@ -127,28 +145,32 @@ "files": [ "/lower-third.js", "/lower-third.css" - ] + ], + "background": true }, "feature:vocal-reducer": { "contract": 1, "eager": false, "files": [ "/vocal-reducer.js" - ] + ], + "background": true }, "feature:eq-core": { "contract": 1, "eager": false, "files": [ "/eq-core.js" - ] + ], + "background": true }, "feature:setlist-import": { "contract": 1, "eager": false, "files": [ "/setlist-import.js" - ] + ], + "background": true }, "feature:car-mode": { "contract": 1, @@ -156,19 +178,20 @@ "files": [ "/car-mode.js", "/car-mode.css" - ] + ], + "background": true }, "feature:p2p": { "contract": 1, "eager": false, "files": [ - "/p2p-client.js", "/p2p-core.js", + "/p2p-client.js", "/p2p-transfer.js", "/p2p-recv-worker.js", - "/hash-worker.js", - "/device-db.js" - ] + "/hash-worker.js" + ], + "background": true }, "feature:direct": { "contract": 1, @@ -179,6 +202,10 @@ "/direct-media.js", "/direct-media.css", "/direct-recv-worker.js" + ], + "background": true, + "dependencies": [ + "feature:p2p" ] }, "feature:video-edit": { @@ -186,21 +213,24 @@ "eager": false, "files": [ "/video-edit.js" - ] + ], + "background": true }, "feature:stats": { "contract": 1, "eager": false, "files": [ "/stats-core.js" - ] + ], + "background": true }, "feature:export": { "contract": 1, "eager": false, "files": [ "/export.js" - ] + ], + "background": true }, "feature:playlist": { "contract": 1, @@ -208,7 +238,8 @@ "files": [], "embeddedIn": [ "/app.js" - ] + ], + "background": false }, "feature:settings": { "contract": 1, @@ -218,7 +249,8 @@ "/app.js", "/settings-sections.js", "/settings-sections.css" - ] + ], + "background": false }, "feature:service-mode": { "contract": 1, @@ -227,7 +259,8 @@ "embeddedIn": [ "/app.js", "/service-ui.css" - ] + ], + "background": false }, "feature:lyrics-editor": { "contract": 1, @@ -237,7 +270,47 @@ "/app.js", "/lyrics-core.js", "/lyrics-display.js" + ], + "background": false + }, + "feature:layout-controls": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/theme-glass-controls.css", + "/glass-controls.js" ] + }, + "layout:sanctuary-stage": { + "contract": 1, + "eager": false, + "background": true, + "files": [] + }, + "layout:liturgical": { + "contract": 1, + "eager": false, + "background": true, + "files": [] + }, + "layout:living-hymnal": { + "contract": 1, + "eager": false, + "background": true, + "files": [] + }, + "layout:broadcaster": { + "contract": 1, + "eager": false, + "background": true, + "files": [] + }, + "layout:contemplative": { + "contract": 1, + "eager": false, + "background": true, + "files": [] } } } diff --git a/frontend/car-mode.js b/frontend/car-mode.js index 9785ce1..b5e7234 100644 --- a/frontend/car-mode.js +++ b/frontend/car-mode.js @@ -10,7 +10,7 @@ overlay = doc.createElement('section'); overlay.className = 'car-mode'; overlay.setAttribute('role', 'dialog'); overlay.setAttribute('aria-modal', 'true'); overlay.setAttribute('aria-label', 'Car mode'); const exit = doc.createElement('button'); exit.type = 'button'; exit.className = 'car-exit'; exit.textContent = 'Exit Car mode'; exit.onclick = close; const title = doc.createElement('h1'); const controls = doc.createElement('div'); controls.className = 'car-controls'; let toggle; - for (const [label, action] of [['Previous', 'prev'], ['Play / Pause', 'toggle'], ['15 s back', 'back'], ['Next', 'next']]) { const b = doc.createElement('button'); b.type = 'button'; b.textContent = label; b.setAttribute('aria-label', label); b.onclick = () => adapter.action(action); if (action === 'toggle') toggle = b; controls.append(b); } + for (const [label, action] of [['Previous', 'prev'], ['Play / Pause', 'toggle'], ['15 s back', 'back'], ['Next', 'next']]) { const b = doc.getElementById('voiceSearchBtn') || doc.createElement('button'); b.id='voiceSearchBtn'; b.type = 'button'; b.textContent = label; b.setAttribute('aria-label', label); b.onclick = () => adapter.action(action); if (action === 'toggle') toggle = b; controls.append(b); } const update = () => { const state = adapter.state(); title.textContent = state.title || 'Choose a song before entering Car mode'; toggle.textContent = state.paused ? 'Play' : 'Pause'; }; update(); overlay.append(exit, title, controls); doc.body.append(overlay); timer = setInterval(update, 500); exit.focus(); overlay.onkeydown = e => { if (e.key === 'Escape') { e.preventDefault(); close(); } else if (e.key === 'Tab') { const buttons = [...overlay.querySelectorAll('button')], first = buttons[0], last = buttons.at(-1); if (e.shiftKey && doc.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && doc.activeElement === last) { e.preventDefault(); first.focus(); } } e.stopPropagation(); }; @@ -18,12 +18,12 @@ function configure(options) { adapter = options; const doc = root.document, Recognition = root.SpeechRecognition || root.webkitSpeechRecognition; if (Recognition) { - const b = doc.createElement('button'); b.type = 'button'; b.className = 'icon-btn voice-search'; b.title = 'Voice search'; b.setAttribute('aria-label', 'Voice search'); b.innerHTML = ''; adapter.input.after(b); + const b = doc.getElementById('voiceSearchBtn') || doc.createElement('button'); b.id='voiceSearchBtn'; b.type = 'button'; b.className = 'icon-btn voice-search'; b.title = 'Voice search'; b.setAttribute('aria-label', 'Voice search'); b.innerHTML = ''; if(!b.isConnected)adapter.input.after(b); let recognition, listening = false; b.onclick = () => { if (listening) { recognition.abort(); return; } recognition = new Recognition(); recognition.lang = doc.documentElement.lang || root.navigator.language || 'en-US'; recognition.continuous = false; recognition.interimResults = false; recognition.onstart = () => { listening = true; b.setAttribute('aria-pressed', 'true'); b.title = 'Listening… tap to cancel'; }; recognition.onend = () => { listening = false; b.setAttribute('aria-pressed', 'false'); b.title = 'Voice search'; }; recognition.onerror = e => adapter.toast(`Voice search: ${e.error === 'not-allowed' ? 'microphone permission was denied' : e.error}`); recognition.onresult = e => { const query = transcript(e); if (query) { adapter.input.value = query; adapter.search(); } }; try { recognition.start(); } catch (error) { adapter.toast(error.message); } }; } - const car = doc.createElement('button'); car.type = 'button'; car.className = 'icon-btn'; car.title = 'Car mode'; car.setAttribute('aria-label', 'Car mode'); car.innerHTML = ''; doc.getElementById('searchForm').after(car); car.onclick = open; - root.SettingsSections.register({ id: 'voice-car', title: 'Voice & Car mode', cluster: 'Listening', summary: () => Recognition ? 'Voice search available · Car mode' : 'Car mode · voice unavailable', render(container) { const p = doc.createElement('p'); p.textContent = Recognition ? 'Use the microphone beside Search to speak a query. Recognition availability and processing depend on your browser.' : 'Voice search is unavailable in this browser.'; const b = doc.createElement('button'); b.type = 'button'; b.className = 'settings-back'; b.textContent = 'Enter Car mode'; b.onclick = open; container.append(p, b); } }); + const car = doc.getElementById('carModeBtn') || doc.createElement('button'); car.id='carModeBtn'; car.type = 'button'; car.className = 'icon-btn'; car.title = 'Car mode'; car.setAttribute('aria-label', 'Car mode'); car.innerHTML = ''; if(!car.isConnected)doc.getElementById('searchForm').after(car); car.onclick = open; + root.SettingsSections.register({ id: 'voice-car', title: 'Voice & Car mode', cluster: 'Listening', summary: () => Recognition ? 'Voice search available · Car mode' : 'Car mode · voice unavailable', render(container) { const p = doc.createElement('p'); p.textContent = Recognition ? 'Use the microphone beside Search to speak a query. Recognition availability and processing depend on your browser.' : 'Voice search is unavailable in this browser.'; const b = doc.getElementById('voiceSearchBtn') || doc.createElement('button'); b.id='voiceSearchBtn'; b.type = 'button'; b.className = 'settings-back'; b.textContent = 'Enter Car mode'; b.onclick = open; container.append(p, b); } }); } const api = { transcript, configure, open, close }; if (typeof module !== 'undefined') module.exports = api; else root.CarMode = api; })(typeof window !== 'undefined' ? window : globalThis); diff --git a/frontend/direct-media.js b/frontend/direct-media.js index be308a6..1e5843c 100644 --- a/frontend/direct-media.js +++ b/frontend/direct-media.js @@ -77,7 +77,7 @@ s.preview = m.file.streamMime ? root.DirectStream?.create(m.file.streamMime, m.file.title) : null; const wait = waiting.get(m.file.id); if (wait) clearTimeout(wait.timer); send(key, { type: 'direct', action: 'accept', token: m.token }); - s.worker = new Worker('/direct-recv-worker.js'); + s.worker = window.Lazy ? window.Lazy.worker('/direct-recv-worker.js') : new Worker('/direct-recv-worker.js'); s.worker.onmessage = async e => { const result = e.data; if (result.op === 'opened') { diff --git a/frontend/direct-recv-worker.js b/frontend/direct-recv-worker.js index da6c14e..94ed130 100644 --- a/frontend/direct-recv-worker.js +++ b/frontend/direct-recv-worker.js @@ -1,11 +1,11 @@ 'use strict'; -importScripts('/sha256.js'); let dir, handle, access, hash, pos = 0, claim, name; let chain = Promise.resolve(); self.onmessage = e => { chain = chain.then(() => run(e.data)); }; async function close() { if (access) { access.flush(); access.close(); access = null; } } async function run(m) { try { + if (!self.Sha256) { self.__ASSET_URLS__=m.assetUrls || {}; importScripts(self.__ASSET_URLS__.sha256 || '/sha256.js'); } if (m.op === 'open') { claim = m.file; if (!/^[A-Za-z0-9_-]{1,128}$/.test(claim.id) || !/^[a-f0-9]{64}$/.test(claim.cid)) throw Error('Invalid file identity'); diff --git a/frontend/eq-core.js b/frontend/eq-core.js index 2e84752..25d946c 100644 --- a/frontend/eq-core.js +++ b/frontend/eq-core.js @@ -1,24 +1,7 @@ /* Shared live/offline EQ definitions and legacy curve migration. */ (function(root) { 'use strict'; - const frequencies = [31,62,125,250,500,1000,2000,4000,8000,16000]; - const bands = frequencies.map((f,i) => ({ f, label: f >= 1000 ? `${f/1000}k` : String(f), type: i === 0 ? 'lowshelf' : i === 9 ? 'highshelf' : 'peaking' })); - const clamp = n => Math.max(-12, Math.min(12, Number(n) || 0)); - function migrate(values) { - if (!Array.isArray(values)) return frequencies.map(() => 0); - if (values.length !== 5) return frequencies.map((_,i) => clamp(values[i])); - const old = [60,250,1000,4000,12000], curve = values.map(clamp); - return frequencies.map(f => { if (f <= old[0]) return curve[0]; if (f >= old[4]) return curve[4]; const i = old.findIndex(x => x >= f), weight = Math.log(f / old[i-1]) / Math.log(old[i] / old[i-1]); return Math.round((curve[i-1] * (1-weight) + curve[i] * weight) * 10) / 10; }); - } - const presets = { - flat: { name: 'Flat', g: frequencies.map(() => 0) }, - bass: { name: 'Bass boost', g: [5,7,5,3,1,0,0,0,0,0] }, - vocal: { name: 'Vocal clarity', g: [-3,-4,-2,0,1,2,3,4,1,0] }, - acoustic: { name: 'Acoustic live', g: [-2,-1,0,-2,-1,1,2,2,1,0] }, - classical: { name: 'Classical', g: migrate([4,2,-1,1,3]) }, - treble: { name: 'Treble boost', g: [0,0,0,0,0,0,1,3,5,6] }, - }; - const width = value => Math.max(0, Math.min(100, Number(value) || 0)); + const { bands, presets, migrate, width } = typeof module !== 'undefined' ? require('./eq-parameters') : root.EqParameters; function createWidener(context, source, value = 0) { const splitter = context.createChannelSplitter(2), output = context.createChannelMerger(2), delay = context.createDelay(.05); source.connect(splitter); splitter.connect(output, 0, 0); splitter.connect(delay, 1); delay.connect(output, 0, 1); diff --git a/frontend/eq-parameters.js b/frontend/eq-parameters.js new file mode 100644 index 0000000..1adce32 --- /dev/null +++ b/frontend/eq-parameters.js @@ -0,0 +1,25 @@ +/* Eager settings values; audio graphs remain in lazy feature groups. */ +(function(root) { + 'use strict'; + const frequencies = [31,62,125,250,500,1000,2000,4000,8000,16000]; + const bands = frequencies.map((f,i) => ({ f, label: f >= 1000 ? `${f/1000}k` : String(f), type: i === 0 ? 'lowshelf' : i === 9 ? 'highshelf' : 'peaking' })); + const clamp = n => Math.max(-12, Math.min(12, Number(n) || 0)); + function migrate(values) { + if (!Array.isArray(values)) return frequencies.map(() => 0); + if (values.length !== 5) return frequencies.map((_,i) => clamp(values[i])); + const old = [60,250,1000,4000,12000], curve = values.map(clamp); + return frequencies.map(f => { if (f <= old[0]) return curve[0]; if (f >= old[4]) return curve[4]; const i = old.findIndex(x => x >= f), weight = Math.log(f / old[i-1]) / Math.log(old[i] / old[i-1]); return Math.round((curve[i-1] * (1-weight) + curve[i] * weight) * 10) / 10; }); + } + const presets = { + flat: { name: 'Flat', g: frequencies.map(() => 0) }, + bass: { name: 'Bass boost', g: [5,7,5,3,1,0,0,0,0,0] }, + vocal: { name: 'Vocal clarity', g: [-3,-4,-2,0,1,2,3,4,1,0] }, + acoustic: { name: 'Acoustic live', g: [-2,-1,0,-2,-1,1,2,2,1,0] }, + classical: { name: 'Classical', g: migrate([4,2,-1,1,3]) }, + treble: { name: 'Treble boost', g: [0,0,0,0,0,0,1,3,5,6] }, + }; + const width = value => Math.max(0, Math.min(100, Number(value) || 0)); + const amount = value => Math.max(0, Math.min(100, Number.isFinite(Number(value)) ? Number(value) : 100)); + const api = { bands, presets, migrate, width, amount }; + if (typeof module !== 'undefined') module.exports = api; else root.EqParameters = api; +})(typeof window !== 'undefined' ? window : globalThis); diff --git a/frontend/f7-layout.js b/frontend/f7-layout.js index 234c19a..e0f07ed 100644 --- a/frontend/f7-layout.js +++ b/frontend/f7-layout.js @@ -35,7 +35,7 @@ function loadF7(){ if(root.Framework7)return Promise.resolve(root.Framework7); - if(!loading)loading=new Promise((res,rej)=>{const s=doc.createElement('script');s.src=F7_SRC;s.onload=()=>res(root.Framework7);s.onerror=()=>{loading=null;rej(new Error('Framework7 failed to load'));};doc.head.append(s);}); + if(!loading)loading=new Promise((res,rej)=>{const s=doc.createElement('script');s.src=root.Lazy?.url('/vendor/framework7-swipe.min.js')||F7_SRC;s.onload=()=>res(root.Framework7);s.onerror=()=>{loading=null;rej(new Error('Framework7 failed to load'));};doc.head.append(s);}); return loading; } function ensureApp(){ diff --git a/frontend/feature-bootstrap.js b/frontend/feature-bootstrap.js new file mode 100644 index 0000000..7442dd3 --- /dev/null +++ b/frontend/feature-bootstrap.js @@ -0,0 +1,77 @@ +/* Thin eager entries and configuration for optional, stateful feature modules. */ +(function(root) { + 'use strict'; + const Lazy = root.Lazy, doc = root.document; + if (!Lazy) return; + const specs = [ + ['Piano','piano','configure','piano','Piano transcription','Live & worship','Off · load model on request'], + ['MidiPedals','midi','configure','midi','MIDI pedalboard','Live & worship','Off'], + ['PartyDJ','party-dj','register','party-dj','Watch party','Live & worship','Shared suggestions · host approval'], + ['LyricsWindow','lyrics-window','configure','floating-lyrics','Floating lyrics','Live & worship','Floating lyrics window'], + ['LowerThird','lower-third','register','broadcast','Presenter & broadcast','Live & worship','Projector · OBS lower third'], + ['EqCore','eq-core','register','equalizer','Equalizer & stereo','Listening','Flat · Original stereo'], + ['VocalReducer','vocal-reducer','register','vocal-reducer','Vocal reducer','Listening','100% · centre-panned vocals'], + ['SetlistImport','setlist-import','configure','setlist-import','Setlist import','Library & storage','Planning Center · SongSelect · ChordPro'], + ['CarMode','car-mode','configure','voice-car','Voice & Car mode','Listening','Voice search · Car mode'], + ['DirectMedia','direct','configure','direct-transfer','Direct device transfer','Library & storage','Paired devices only'], + ]; + function button(id, text, anchor, name, action, className='np-btn') { + if (!anchor || doc.getElementById(id)) return; + const b=doc.createElement('button'); b.id=id; b.type='button'; b.className=className; b.textContent=text; b.setAttribute('aria-label',text); + if(id==='carModeBtn')b.innerHTML=''; + if(id==='voiceSearchBtn')b.innerHTML=''; + if(id.startsWith('floating-')){b.title='Open floating lyrics';b.setAttribute('aria-label','Open floating lyrics window');} + b.title ||= text; + b.onclick=()=>Lazy.load(name).then(action).catch(error=>root.dispatchEvent(new CustomEvent('ytp-lazy-error',{detail:{error}}))); + anchor.after(b); Lazy.intent(b,name); + } + for (const [globalName, suffix, setup, id, title, cluster, summary] of specs) { + const group='feature:'+suffix; + const facade=Lazy.proxy(group,['open','close','obtain','publish','attach','handle','offer','paint','fade'],globalName); + let configured=false; + facade[setup]=options=>{ + if (configured) return; configured=true; + Lazy.onLoad(group,()=>root[globalName][setup](options)); + root.SettingsSections.register({id,title,cluster,lazyGroup:group,summary:()=>{ + const s=options?.settings?.() || {}; + if(globalName==='Piano')return s.pianoEnabled?'On · browser or optional worker':'Off · load model on request'; + if(globalName==='MidiPedals')return s.midiEnabled?'On · pedal mappings':'Off'; + if(globalName==='EqCore')return `${root.EqParameters.presets[s.eq?.preset]?.name || 'Custom'} · ${root.EqParameters.width(s.stereoWidth)?'Widened':'Original stereo'}`; + if(globalName==='VocalReducer')return `${root.EqParameters.amount(s.vocalLevel ?? 100)}% · centre-panned vocals`; + if(globalName==='DirectMedia')return facade.enabled()?'On · paired devices only':'Off or unsupported'; + if(globalName==='CarMode')return root.SpeechRecognition||root.webkitSpeechRecognition?'Voice search available · Car mode':'Car mode · voice unavailable'; + if(globalName==='LyricsWindow')return root.documentPictureInPicture?.requestWindow?'Interactive window available':root.HTMLCanvasElement?.prototype.captureStream&&doc.pictureInPictureEnabled?'Lyric video PiP available':'Not supported on this browser'; + return summary; + }, + render(container,context) { + let disposed=false, cleanup; + container.textContent='Loading…'; + Lazy.load(group).then(()=>{ + if (disposed || !container.isConnected) return; + container.replaceChildren(); cleanup=root.SettingsSections.get(id).render(container,context); + }).catch(error=>{if(!disposed)container.textContent=error.message;}); + return ()=>{disposed=true; if(typeof cleanup==='function')cleanup();}; + }, + }); + if (globalName==='CarMode') { + button('carModeBtn','Car mode',doc.getElementById('searchForm'),group,()=>root.CarMode.open(),'icon-btn'); + if(root.SpeechRecognition||root.webkitSpeechRecognition)button('voiceSearchBtn','Voice search',options.input,group,()=>doc.getElementById('voiceSearchBtn').click(),'icon-btn voice-search'); + } + if (globalName==='LyricsWindow' && (root.documentPictureInPicture?.requestWindow || (root.HTMLCanvasElement?.prototype.captureStream && doc.pictureInPictureEnabled))) { + for(const anchor of ['stageLyricsAuto','serviceAutoscrollBtn','pipBtn'])button('floating-'+anchor,'⧉ Lyrics',doc.getElementById(anchor),group,()=>doc.getElementById('floating-'+anchor).click()); + } + }; + if(globalName==='LowerThird') { + facade.active=()=>new URLSearchParams(root.location.search).get('overlay')==='lowerthird'; + facade.url=(origin,code)=>{const u=new URL('/',origin);u.searchParams.set('overlay','lowerthird');u.searchParams.set('code',String(code));return u.href;}; + } + if(globalName==='DirectMedia') { + let settings=()=>({}); const configure=facade.configure; + facade.configure=options=>{settings=options.settings;configure(options);}; + facade.enabled=()=>settings().directTransfer!==false && !!root.RTCPeerConnection; + facade.hasSource=()=>false; + } + if(globalName==='LyricsWindow')facade.element=()=>null; + root[globalName]=facade; + } +})(typeof window !== 'undefined' ? window : globalThis); diff --git a/frontend/hash-worker.js b/frontend/hash-worker.js index 455dab6..5d10f89 100644 --- a/frontend/hash-worker.js +++ b/frontend/hash-worker.js @@ -6,11 +6,11 @@ ^ * Out: { ok: true, sha256, size, engine } | { ok: false, error } * ========================================================================== */ 'use strict'; -importScripts('/sha256.js'); self.onmessage = async (e) => { const { name } = e.data || {}; try { + if (!self.Sha256) { self.__ASSET_URLS__=e.data.assetUrls || {}; importScripts(self.__ASSET_URLS__.sha256 || '/sha256.js'); } const root = await navigator.storage.getDirectory(); const dir = await root.getDirectoryHandle('videos'); const file = await (await dir.getFileHandle(String(name))).getFile(); diff --git a/frontend/index.html b/frontend/index.html index f55934d..bfc7c2a 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -24,22 +24,15 @@ - - + + - - - - - - -
@@ -650,20 +643,14 @@ - - - - - - @@ -671,31 +658,16 @@ - - - - - - - - - - - - - - - - - + + diff --git a/frontend/lazy.js b/frontend/lazy.js index 3811cbc..a10e2bd 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -4,15 +4,22 @@ const doc = root.document; let manifest; try { manifest = JSON.parse(doc.getElementById('ytp-assets').textContent); } - catch { return; } // Native/static shells retain their eager script path. + catch { return; } // The index must supply this map; never fetch one during boot. const assets = new Map(), groups = new Map(), hooks = new Map(); const css = new Set([...doc.querySelectorAll('link[data-lazy-css]')].map(link => link.dataset.lazyCss)); const selected = new Map(); - const url = path => selected.get(path) || (manifest.files[path]?.h ? path + '?v=' + manifest.files[path].h : path); + const url = path => selected.get(path) || (manifest.files[path]?.h ? path + '?v=' + manifest.files[path].h : './' + path.replace(/^\//,'')); function reloadRequired(name) { api.reloadRequired = true; if (root.CustomEvent) root.dispatchEvent?.(new root.CustomEvent('ytp-reload-required', { detail: { group: name } })); } + function compatible(name, current, seen = new Set()) { + if(seen.has(name))return true; + seen.add(name); + const built=manifest.groups[name], newer=current.groups[name]; + if(!built || !newer || built.contract!==newer.contract)return false; + return (newer.dependencies || []).every(dependency=>(built.dependencies || []).includes(dependency)&&compatible(dependency,current,seen)); + } async function select(name) { if (!root.caches) return; try { @@ -20,15 +27,22 @@ const response = await cache.match('/__ytp_asset_state'); const current = response && (await response.json()).current; const built = manifest.groups[name], newer = current?.groups[name]; + // The active layout's CSS already executed in the parser before app boot. + if(name === 'layout:'+api.layout) return; if (!newer || current.buildTag === manifest.buildTag) return; - if (newer.contract !== built.contract) { reloadRequired(name); return; } - for (const path of built.files) { + if (!compatible(name,current)) { reloadRequired(name); return; } + const changedList = newer.files.join('\n') !== built.files.join('\n'); + const available = new Map(); + for (const path of changedList ? newer.files : built.files) { // Membership and contract must both match the running core's expectation. if (!newer.files.includes(path) || !current.files[path]) continue; const key = path + '?v=' + current.files[path].h; const held = await cache.match(key); - if (held?.headers.get('X-Asset-Hash') === current.files[path].h) selected.set(path, key); + if (held?.headers.get('X-Asset-Hash') === current.files[path].h) available.set(path, key); } + if(changedList && available.size !== newer.files.length)return; + for(const [path,key] of available)selected.set(path,key); + if(changedList)return newer; } catch { /* Private browsing/cache eviction: keep the embedded build-local map. */ } } function inject(path) { @@ -54,8 +68,8 @@ if (!group) return Promise.reject(new Error('Unknown asset group: ' + name)); const task = (async () => { for (const dependency of group.dependencies || []) await load(dependency); - await select(name); - for (const path of group.files) if (!/-worker\.js$/.test(path)) await inject(path); + const selectedGroup = await select(name) || group; + for (const path of selectedGroup.files) if (!/-worker\.js$/.test(path)) await inject(path); for (const fn of hooks.get(name) || []) await fn(); group.executed = true; })(); @@ -69,7 +83,31 @@ const api = { load, prefetch: load, loaded: name => !!manifest.groups[name]?.executed, url, manifest, layout: 'classic', reloadRequired: false, - onLoad(name, fn) { const list = hooks.get(name) || []; list.push(fn); hooks.set(name, list); }, + worker(path) { + const worker=new root.Worker(url(path)), post=worker.postMessage.bind(worker); let first=true; + worker.postMessage=(message,transfer)=>{ + if(first) { first=false; message={...message,assetUrls:{sha256:url('/sha256.js'),wasm:url('/sha256-wasm.js'),resume:url('/resume-core.js')}}; } + post(message,transfer); + }; + return worker; + }, + reportLayout(registration) { + const send = reg => { + const workers = new Set([root.navigator.serviceWorker.controller, reg?.installing, reg?.waiting, reg?.active]); + for(const worker of workers) worker?.postMessage({type:'LAYOUT',value:api.layout}); + }; + if(registration)send(registration); + else root.navigator.serviceWorker?.getRegistration().then(send).catch(()=>{}); + }, + warm() { + if(root.navigator.connection?.saveData || !root.navigator.serviceWorker) return; + const idle = root.requestIdleCallback || (fn => root.setTimeout(fn,1000)); + idle(()=>root.navigator.serviceWorker.ready.then(reg=>reg.active?.postMessage({type:'WARM_ASSETS',saveData:!!root.navigator.connection?.saveData})).catch(()=>{})); + }, + onLoad(name, fn) { + if(api.loaded(name)) { Promise.resolve().then(fn).catch(error=>{if(root.CustomEvent)root.dispatchEvent?.(new root.CustomEvent('ytp-lazy-error',{detail:{group:name,error}}));}); return; } + const list = hooks.get(name) || []; list.push(fn); hooks.set(name, list); + }, proxy(name, methods, globalName) { return Object.fromEntries(methods.map(method => [method, async (...args) => { await load(name); @@ -84,10 +122,18 @@ }, }; root.Lazy = api; - try { api.layout = JSON.parse(root.localStorage.getItem('_ytpdata') || '{}').settings?.layout || 'classic'; } catch {} - doc.documentElement.dataset.layout = api.layout; - const layout = manifest.groups['layout:' + api.layout] || manifest.groups['layout:classic']; - if (doc.readyState === 'loading') for (const path of layout?.files || []) { + root.navigator.serviceWorker?.addEventListener('message',event=>{ + if(event.data?.type==='ASSET_LAYOUT_REQUEST') event.source?.postMessage({type:'LAYOUT',value:api.layout}); + if(event.data?.type==='SW_UPDATE_AVAILABLE') api.warm(); + }); + root.navigator.serviceWorker?.addEventListener('controllerchange',()=>{api.reportLayout();api.warm();}); + let settings={}; + try { settings=JSON.parse(root.localStorage.getItem('_ytpdata') || '{}').settings || {}; api.layout=settings.layout || 'classic'; } catch {} + Object.assign(doc.documentElement.dataset,{layout:api.layout,theme:settings.theme || 'dark',font:settings.fontScale || 'normal',density:settings.density || 'comfortable',perf:settings.perfMode?'on':'off',motion:settings.reduceMotion?'reduced':'full'}); + const layoutName = manifest.groups['layout:' + api.layout] ? 'layout:'+api.layout : 'layout:classic'; + const layoutGroups = new Set([layoutName]); + for(const name of layoutGroups) for(const dependency of manifest.groups[name]?.dependencies || []) layoutGroups.add(dependency); + if (doc.readyState === 'loading') for (const path of [...layoutGroups].flatMap(name=>manifest.groups[name]?.files || [])) { if (!/\.css$/.test(path) || css.has(path)) continue; // Parser-inserted CSS blocks rendering; dynamic head links do not on all WebKit versions. css.add(path); diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index bbd0d34..8265580 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -63,3 +63,16 @@ test('unexecuted incompatible group keeps its running-build N-1 URLs and require assert.equal(f.root.Lazy.reloadRequired,true); assert.ok(events.includes('ytp-reload-required')); }); + +test('workers receive the pinned import URL map in their first message', () => { + const f=fixture(), sent=[]; f.root.Worker=class { constructor(url){this.url=url;} postMessage(message,transfer){sent.push({message,transfer});} }; + f.manifest.files['/worker.js']={h:'w'}; f.root.Lazy.manifest.files['/worker.js']={h:'w'}; + const worker=f.root.Lazy.worker('/worker.js');worker.postMessage({op:'open'},['transfer']);worker.postMessage({op:'finish'}); + assert.equal(worker.url,'/worker.js?v=w');assert.equal(sent[0].message.assetUrls.sha256,f.root.Lazy.url('/sha256.js'));assert.equal(sent[0].message.assetUrls.wasm,f.root.Lazy.url('/sha256-wasm.js'));assert.deepEqual(sent[0].transfer,['transfer']);assert.equal(sent[1].message.assetUrls,undefined); +}); + +test('new group files with a changed dependency contract cannot run against the old dependency',async()=>{ + const next=fixture().manifest;next.buildTag='next';next.groups['feature:test'].dependencies=['feature:dep'];next.groups['feature:dep']={contract:2,files:[]};next.files['/one.js'].h='new'; + const f=fixture(next,['/one.js?v=new','/two.js?v=2']);f.root.Lazy.manifest.groups['feature:test'].dependencies=['feature:dep'];f.root.Lazy.manifest.groups['feature:dep']={contract:1,files:[]}; + await f.root.Lazy.load('feature:test');assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']);assert.equal(f.root.Lazy.reloadRequired,true); +}); diff --git a/frontend/lyrics-window.js b/frontend/lyrics-window.js index 7bc2c02..4c32a07 100644 --- a/frontend/lyrics-window.js +++ b/frontend/lyrics-window.js @@ -33,7 +33,7 @@ } function configure(options) { adapter = options; const supported = !!mode(); - for (const id of ['stageLyricsAuto', 'serviceAutoscrollBtn', 'pipBtn']) { const anchor = root.document.getElementById(id); if (!anchor || !supported) continue; const button = root.document.createElement('button'); button.type = 'button'; button.className = 'np-btn'; button.textContent = '⧉ Lyrics'; button.title = 'Open floating lyrics'; button.setAttribute('aria-label', 'Open floating lyrics window'); button.onclick = open; anchor.after(button); } + for (const id of ['stageLyricsAuto', 'serviceAutoscrollBtn', 'pipBtn']) { const anchor = root.document.getElementById(id); if (!anchor || !supported) continue; const button = root.document.getElementById('floating-'+id) || root.document.createElement('button'); button.id='floating-'+id; button.type = 'button'; button.className = 'np-btn'; button.textContent = '⧉ Lyrics'; button.title = 'Open floating lyrics'; button.setAttribute('aria-label', 'Open floating lyrics window'); button.onclick = open; if(!button.isConnected)anchor.after(button); } root.SettingsSections.register({ id: 'floating-lyrics', title: 'Floating lyrics', cluster: 'Live & worship', summary: () => mode() === 'document' ? 'Interactive window available' : mode() ? 'Lyric video PiP available' : 'Not supported on this browser', render(container) { const p = container.ownerDocument.createElement('p'); p.textContent = mode() === 'document' ? 'Open synced lyrics with seeking, Play/Pause and Next in an always-on-top window.' : mode() ? 'This browser supports a lyric-video window. Playback controls remain in the player.' : 'Floating lyrics are not supported on this browser.'; container.append(p); if (supported) { const b = container.ownerDocument.createElement('button'); b.type = 'button'; b.className = 'settings-back'; b.textContent = 'Open floating lyrics'; b.onclick = open; container.append(b); } } }); } const api = { configure, support, wrap, element: id => pipWindow?.document.getElementById(id) || null }; if (typeof module !== 'undefined') module.exports = api; else root.LyricsWindow = api; diff --git a/frontend/opfs-worker.js b/frontend/opfs-worker.js index e7fd0c4..a140730 100644 --- a/frontend/opfs-worker.js +++ b/frontend/opfs-worker.js @@ -34,8 +34,7 @@ // Incremental SHA-256 (frontend/sha256.js): the file is hashed while it is // written, so the device knows its content id without re-reading the file. -try { importScripts('/sha256.js'); } catch { /* hashing unavailable — save still works */ } -importScripts('/resume-core.js'); + async function getVideosDir() { const root = await navigator.storage.getDirectory(); @@ -203,6 +202,10 @@ async function writeFile(dirName, name, buffer) { } self.onmessage = async (e) => { + self.__ASSET_URLS__=e.data?.assetUrls || {}; + try { if(!self.Sha256)importScripts(self.__ASSET_URLS__.sha256 || '/sha256.js'); } catch { /* hashing unavailable — legacy save still works */ } + try { if(!self.ResumeCore)importScripts(self.__ASSET_URLS__.resume || '/resume-core.js'); } + catch(error) { self.postMessage({type:'error',error:error.message}); return; } if (e.data && e.data.op === 'write') { try { await writeFile(e.data.dir, e.data.name, e.data.buffer); self.postMessage({ type: 'written' }); } catch (err) { self.postMessage({ type: 'error', error: err && err.message ? err.message : String(err) }); } diff --git a/frontend/opfs.js b/frontend/opfs.js index 268a30b..b81b52c 100644 --- a/frontend/opfs.js +++ b/frontend/opfs.js @@ -151,7 +151,7 @@ return new Promise((resolve) => { let worker; try { - worker = new Worker('/opfs-worker.js'); + worker = window.Lazy ? window.Lazy.worker('/opfs-worker.js') : new Worker('/opfs-worker.js'); } catch { resolve({ ok: false, fallback: true }); return; diff --git a/frontend/p2p-client.js b/frontend/p2p-client.js index 7ab5834..adf5b76 100644 --- a/frontend/p2p-client.js +++ b/frontend/p2p-client.js @@ -72,7 +72,7 @@ function hashInWorker(name) { return new Promise((resolve) => { let w; - try { w = new Worker('/hash-worker.js'); } catch { resolve(null); return; } + try { w = window.Lazy ? window.Lazy.worker('/hash-worker.js') : new Worker('/hash-worker.js'); } catch { resolve(null); return; } w.onmessage = (e) => { w.terminate(); resolve(e.data && e.data.ok ? e.data : null); }; w.onerror = () => { w.terminate(); resolve(null); }; w.postMessage({ name }); @@ -296,7 +296,7 @@ function start(h) { hooks = { ...hooks, ...(h || {}) }; const idle = window.requestIdleCallback || ((fn) => setTimeout(fn, 1)); - setTimeout(() => idle(() => sync()), 8000); + setTimeout(() => idle(() => sync()), h?.initialDelay ?? 8000); document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible' && Date.now() - lastSync > RESYNC_MS) sync(); }); diff --git a/frontend/p2p-recv-worker.js b/frontend/p2p-recv-worker.js index 66f76d8..f9ee489 100644 --- a/frontend/p2p-recv-worker.js +++ b/frontend/p2p-recv-worker.js @@ -12,7 +12,6 @@ * The ".part" suffix keeps OPFS.listVideos() from ever listing a partial file. * ========================================================================== */ 'use strict'; -importScripts('/sha256.js'); let dir = null; let handle = null; @@ -36,6 +35,7 @@ self.onmessage = (e) => { chain = chain.then(() => onOp(e.data || {})); }; async function onOp(m) { try { + if (!self.Sha256) { self.__ASSET_URLS__=m.assetUrls || {}; importScripts(self.__ASSET_URLS__.sha256 || '/sha256.js'); } if (m.op === 'open') { const root = await navigator.storage.getDirectory(); dir = await root.getDirectoryHandle('videos', { create: true }); diff --git a/frontend/p2p-transfer.js b/frontend/p2p-transfer.js index 74c8c21..dfe87e6 100644 --- a/frontend/p2p-transfer.js +++ b/frontend/p2p-transfer.js @@ -99,7 +99,7 @@ return new Promise((resolve) => { const xid = newXid(); const pc = new RTCPeerConnection({ iceServers }); - const worker = new Worker('/p2p-recv-worker.js'); + const worker = window.Lazy ? window.Lazy.worker('/p2p-recv-worker.js') : new Worker('/p2p-recv-worker.js'); let settled = false; let idle = null; let expected = size; diff --git a/frontend/piano.js b/frontend/piano.js index f3ae236..a492c53 100644 --- a/frontend/piano.js +++ b/frontend/piano.js @@ -200,7 +200,7 @@ button('Transcribe in browser', () => run(async (id) => { const buffer = await audio(id, file.files[0]); - const engine = await import('./piano-engine.mjs'); + const engine = await import(root.Lazy?.url('/piano-engine.mjs') || './piano-engine.mjs'); const result = await engine.transcribe(buffer, (text) => { if (alive) status.textContent = text; }); diff --git a/frontend/settings-sections.js b/frontend/settings-sections.js index 31095ba..d5e7f3e 100644 --- a/frontend/settings-sections.js +++ b/frontend/settings-sections.js @@ -45,14 +45,23 @@ const text = document.createElement('span'), title = document.createElement('b'), summary = document.createElement('small'); title.textContent = section.title; text.append(title, summary); button.append(text); button.setAttribute('aria-controls', 'settings-section-' + section.id); navigation.append(button); rows.set(section.id, { button, summary }); const panel = document.createElement('section'); panel.id = 'settings-section-' + section.id; panel.className = 'settings-section'; panel.setAttribute('aria-label', section.title); panels.set(section.id, panel); detail.append(panel); - const cleanup = section.render(panel, context); if (typeof cleanup === 'function') cleanups.push(cleanup); + if (!section.lazyGroup) { + const cleanup = section.render(panel, context); if (typeof cleanup === 'function') cleanups.push(cleanup); + } button.addEventListener('click', () => open(section.id)); + if(section.lazyGroup)root.Lazy.intent(button,section.lazyGroup); } } grid.append(navigation, detail); host.replaceChildren(toolbar, results, empty, grid); function summaries() { for (const section of sections) { try { rows.get(section.id).summary.textContent = section.summary(context) || ''; } catch {} } } function show(id, inDetail, focusId) { if (registry.get(id)) active = id; + const section = sections.find(section => section.id === active); + const panel = panels.get(active); + if ((inDetail || win.matchMedia?.('(min-width: 861px)').matches) && section?.lazyGroup && !panel.dataset.rendered) { + panel.dataset.rendered = '1'; + const cleanup = section.render(panel, context); if (typeof cleanup === 'function') cleanups.push(cleanup); + } host.dataset.detail = inDetail ? '1' : '0'; for (const [key, panel] of panels) panel.hidden = key !== active; for (const [key, row] of rows) row.button.setAttribute('aria-current', key === active ? 'true' : 'false'); diff --git a/frontend/sha256.js b/frontend/sha256.js index 931d248..318656e 100644 --- a/frontend/sha256.js +++ b/frontend/sha256.js @@ -36,7 +36,7 @@ wasm = null; try { if (typeof WebAssembly === 'undefined') return wasm; - if (!root.SHA256_WASM_B64 && typeof importScripts === 'function') importScripts('/sha256-wasm.js'); + if (!root.SHA256_WASM_B64 && typeof importScripts === 'function') importScripts(root.__ASSET_URLS__?.wasm || '/sha256-wasm.js'); let b64 = root.SHA256_WASM_B64; if (!b64 && typeof require === 'function') b64 = require('./sha256-wasm.js'); if (!b64) return wasm; diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 547c292..92080a7 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -53,9 +53,10 @@ test('assets.json describes the complete existing shell exactly once with eager test('the selected glass-stage layout includes its controls and panel dependencies', () => { const { groups } = JSON.parse(readFileSync(join(__dirname, 'assets.json'), 'utf8')); assert.deepEqual(groups['layout:glass-stage'].files, [ - '/theme-glass.css', '/theme-glass-controls.css', '/glass-controls.js', - '/theme-glass-panel.css', '/glass-panel-layout.js', + '/theme-glass.css', '/theme-glass-panel.css', '/glass-panel-layout.js', ]); + assert.deepEqual(groups['layout:glass-stage'].dependencies,['feature:layout-controls']); + assert.ok(groups['feature:layout-controls'].files.includes('/glass-controls.js')); }); test('the shared sync core is eager and loads before the update helper',()=>{ @@ -64,3 +65,16 @@ test('the shared sync core is eager and loads before the update helper',()=>{ assert.ok(html.indexOf('src="asset-sync-core.js"') { + const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); + const background=new Set(Object.values(groups).filter(g=>g.background).flatMap(g=>g.files)); + for(const match of html.matchAll(/<(?:script\b[^>]*\bsrc|link\b[^>]*\bhref)="([^"]+)"/gi)) { + const path='/'+match[1].replace(/^\//,'').split(/[?#]/)[0]; + assert.ok(!background.has(path),`${path} is not eager`); + } + assert.ok(html.indexOf('id="ytp-assets"')')); + assert.deepEqual(JSON.parse(html.match(/id="ytp-assets">([^<]+)<\/script>/)[1]).groups,groups); + for(const name of ['playlist','settings','service-mode','lyrics-editor'])assert.ok(groups['feature:'+name].eager); +}); diff --git a/frontend/sw-update.js b/frontend/sw-update.js index 5853665..974baa7 100644 --- a/frontend/sw-update.js +++ b/frontend/sw-update.js @@ -165,8 +165,9 @@ // legacy refresh followed by a reload into the old persistent manifest. if (worker && !status) throw new Error('Worker update status unavailable; try again'); if (status && status.assetSync) { - const result = await core.syncAssets(m,{cache,fetchFn:opts.fetchFn}); - if (!reg.waiting) await core.commit(m,cache); + const activeLayout = root.Lazy?.layout || 'classic'; + const result = await core.syncAssets(m,{cache,fetchFn:opts.fetchFn,activeLayout}); + if (!reg.waiting) await core.commit(m,cache,{activeLayout}); return result; } } @@ -210,7 +211,7 @@ try { const ch = new Ctor(); ch.port1.onmessage = (ev) => finish(ev && ev.data ? ev.data : null); - worker.postMessage({ type: 'CACHE_STATUS' }, [ch.port2]); + worker.postMessage({ type: 'CACHE_STATUS', activeLayout: root.Lazy?.layout }, [ch.port2]); } catch { finish(null); return; } if (schedule) schedule(() => finish(null), timeoutMs); }); diff --git a/frontend/sw.js b/frontend/sw.js index 266ef71..b86a59c 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -74,6 +74,10 @@ const SHELL = [ '/async-guard.js', '/visible-timer.js', '/asset-sync-core.js', + '/lazy.js', + '/feature-bootstrap.js', + '/eq-parameters.js', + '/assets.json', '/sw-update.js', '/fingerprint.js', '/opfs.js', @@ -287,7 +291,27 @@ self.addEventListener('fetch', (e) => { // ---- Message: handle SKIP_WAITING from the client ---- const playingClients = new Map(), deferredClients = new Set(); +let activeLayout = 'classic', layoutReply; self.addEventListener('message', (e) => { + if (ASSET_SYNC && e.data?.type === 'LAYOUT' && e.source && typeof e.data.value === 'string') { + activeLayout = e.data.value; + layoutReply?.(); + e.waitUntil((async()=>{ + const cache=await caches.open(AssetSyncCore.CACHE); + await cache.put('/__ytp_layout',Response.json({layout:activeLayout})); + const m=await candidate(cache); + if(m && m.activeLayout!==activeLayout) { + await AssetSyncCore.syncAssets(m,{cache,fetchFn:fetch,activeLayout}); + m.activeLayout=activeLayout; await cache.put(candidateKey,Response.json(m)); + } + })()); + } + if (ASSET_SYNC && e.data?.type === 'WARM_ASSETS' && !e.data.saveData) { + e.waitUntil((async()=>{ + const cache=await caches.open(AssetSyncCore.CACHE), m=(await AssetSyncCore.state(cache))?.current; + if(m)await AssetSyncCore.syncAssets(m,{cache,fetchFn:fetch,groups:Object.keys(m.groups).filter(name=>m.groups[name].background)}); + })().catch(error=>console.warn('[asset-sync] idle warm interrupted',error.message))); + } if (e.data && e.data.type === 'PLAYING' && e.source) { playingClients.set(e.source.id, !!e.data.value); if (!e.data.value && deferredClients.delete(e.source.id)) self.skipWaiting(); @@ -306,7 +330,11 @@ self.addEventListener('message', (e) => { e.waitUntil((async () => { if (ASSET_SYNC) { let reply = { ready: false, missing: -1, version: VERSION }; - try { const cache = await caches.open(AssetSyncCore.CACHE); const m = await candidate(cache) || (await AssetSyncCore.state(cache))?.current; if(m) reply = await AssetSyncCore.status(m,cache); } catch {} + try { + const cache = await caches.open(AssetSyncCore.CACHE), state = await AssetSyncCore.state(cache); + const pending = await candidate(cache), m = pending || state?.current; + if(m) reply = await AssetSyncCore.status(m,cache,{previous:pending ? state?.current : state?.previous,activeLayout:e.data.activeLayout || (pending ? m.activeLayout : activeLayout) || 'classic'}); + } catch {} reply.type = 'CACHE_STATUS'; reply.assetSync = true; if(e.ports && e.ports[0]) e.ports[0].postMessage(reply); else if(e.source) e.source.postMessage(reply); return; @@ -446,6 +474,15 @@ async function installAssets() { const m = await r.json(); if (m.buildTag !== VERSION) throw Error('Deployment changed during install'); const cache = await caches.open(AssetSyncCore.CACHE); + const remembered = await cache.match('/__ytp_layout'); + if(remembered)activeLayout=(await remembered.json()).layout || 'classic'; + let layoutKnown = !!remembered; + const clients = await self.clients.matchAll({type:'window',includeUncontrolled:true}); + await new Promise(resolve=>{ + const timer=setTimeout(resolve,500); layoutReply=()=>{layoutKnown=true;clearTimeout(timer);resolve();}; + for(const client of clients)client.postMessage({type:'ASSET_LAYOUT_REQUEST'}); + }); + layoutReply=null; m.activeLayout=activeLayout; const freshInstall = !(await AssetSyncCore.state(cache)); const fetchAsset = async (url,init) => { // Fonts/icons still use plain URLs in CSS/manifest. On first install reuse @@ -456,7 +493,14 @@ async function installAssets() { } return fetch(url,init); }; - await AssetSyncCore.syncAssets(m, { cache, fetchFn: fetchAsset }); + await AssetSyncCore.syncAssets(m, { cache, fetchFn: fetchAsset, activeLayout }); + // Older pages cannot report their saved choice. Keep every layout ready for + // that one migration so an immediate offline reload cannot lose its theme. + if(!layoutKnown && ((await AssetSyncCore.state(cache)) || (await caches.keys()).some(isVersionedShellCache))) { + const layouts=new Set(Object.keys(m.groups).filter(name=>name.startsWith('layout:'))); + for(const name of layouts)for(const dependency of m.groups[name].dependencies || [])layouts.add(dependency); + await AssetSyncCore.syncAssets(m,{cache,fetchFn:fetchAsset,groups:[...layouts]}); + } await cache.put(candidateKey, new Response(JSON.stringify(m))); } async function migrateLegacy(cache, m) { @@ -489,7 +533,7 @@ async function activateAssets() { if (!m) throw Error('Missing candidate manifest'); const names = await migrateLegacy(cache,m), old = await AssetSyncCore.state(cache); const previousClients = (await self.clients.matchAll({type:'window'})).map(c=>c.id); - await AssetSyncCore.commit(m,cache,{previousClients}); + await AssetSyncCore.commit(m,cache,{previousClients,activeLayout:m.activeLayout || activeLayout}); // Legacy deletion occurs strictly after verified commit. await Promise.all(names.map(n => caches.delete(n))); for (const req of await cache.keys()) if(new URL(req.url).pathname.startsWith('/__ytp_candidate/')) await cache.delete(req); @@ -516,6 +560,11 @@ async function assetFetch(request, clientId) { const cached = await cache.match(key); const h = new URL(key,self.location.origin).searchParams.get('v'); if(cached && cached.headers.get('X-Asset-Hash') === h) return cached; + if(state.current.files[path]?.h === h) { + const previousKey=AssetSyncCore.fallback(state.current,state.previous,path); + const previousResponse=previousKey && await cache.match(previousKey); + if(previousResponse && previousResponse.headers.get('X-Asset-Hash')===state.previous.files[path].h) return previousResponse; + } try { const r = await fetch(key); if(r.ok && r.headers.get('X-Asset-Hash') !== h) return new Response('Asset version unavailable',{status:409}); if(r.ok && request.method !== 'HEAD') await cache.put(key,r.clone()); return r; } catch { return new Response('Offline',{status:503}); } } try { return await fetch(request); } catch { return new Response('Offline',{status:503}); } diff --git a/frontend/worker-imports.test.js b/frontend/worker-imports.test.js new file mode 100644 index 0000000..25641b5 --- /dev/null +++ b/frontend/worker-imports.test.js @@ -0,0 +1,12 @@ +const {test}=require('node:test'), assert=require('node:assert/strict'), vm=require('node:vm'), fs=require('node:fs'); +for(const name of ['hash-worker','direct-recv-worker','p2p-recv-worker','opfs-worker'])test(name+' imports its originating page hashes before handling the first operation',async()=>{ + const urls=[], replies=[];const self={postMessage:m=>replies.push(m)}; + const sandbox={self,console,URL,setTimeout,clearTimeout,Promise,TextEncoder,FileSystemFileHandle:class {createSyncAccessHandle(){}},navigator:{storage:{getDirectory:async()=>{throw Error('fixture: no disk writes')}}},fetch:async()=>{throw Error('fixture: no network')},importScripts:u=>{urls.push(u);if(u.includes('/sha256.js'))self.Sha256={create:()=>({})};if(u.includes('/resume-core.js'))self.ResumeCore={};}}; + vm.runInNewContext(fs.readFileSync(__dirname+'/'+name+'.js','utf8'),sandbox); + assert.deepEqual(urls,[]); + await self.onmessage({data:{name:'x',op:'open',videoId:'x',url:'/fixture',file:{id:'x',cid:'a'.repeat(64)},assetUrls:{sha256:'/sha256.js?v=sha',wasm:'/sha256-wasm.js?v=wasm',resume:'/resume-core.js?v=resume'}}}); + await new Promise(r=>setImmediate(r)); + assert.equal(urls[0],'/sha256.js?v=sha');assert.equal(self.__ASSET_URLS__.wasm,'/sha256-wasm.js?v=wasm'); + if(name==='opfs-worker')assert.ok(urls.includes('/resume-core.js?v=resume')); + assert.ok(replies.length>0); +}); diff --git a/server/static-delivery.test.js b/server/static-delivery.test.js index 0a6fff0..ed0661e 100644 --- a/server/static-delivery.test.js +++ b/server/static-delivery.test.js @@ -13,7 +13,7 @@ mkdirSync(publicDir); mkdirSync(dataDir); mkdirSync(join(publicDir, 'fonts')); mkdirSync(join(publicDir, 'icons')); -writeFileSync(join(publicDir, 'index.html'), ''); +writeFileSync(join(publicDir, 'index.html'), ''); writeFileSync(join(publicDir, 'app.css'), 'body{}'); writeFileSync(join(publicDir, 'app.js'), 'window.app=true;'); writeFileSync(join(publicDir, 'root.css'), 'body{color:red}'); @@ -219,6 +219,20 @@ describe('static delivery characterization', () => { } }); + test('all index routes carry the identical embedded build-local map', async () => { + const manifest=await (await fetch(`${server.base}/api/manifest`)).json(); + let expected; + for(const path of ['/', '/index.html','/search','/playlist/x']) { + const html=await (await fetch(`${server.base}${path}`)).text(); + const map=JSON.parse(html.match(/id="ytp-assets">([^<]+)<\/script>/)[1]); + expect(map.buildTag).toBe(manifest.buildTag); + expect(map.groups).toEqual(manifest.groups); + expect(map.files['/app.js'].h).toBe(manifest.files['/app.js'].h); + expect(map.files['/index.html']).toBeUndefined(); + if(expected)expect(html).toBe(expected);else expected=html; + } + }); + test('SPA routes fall back to the stamped index', async () => { const { buildTag } = await (await fetch(`${server.base}/api/version`)).json(); for (const path of ['/search', '/playlist/x']) { From ccfb7d90ba75e9ed4a4c9cbf271815ecf2b57fa5 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 01:32:43 +0800 Subject: [PATCH 22/81] Preserve separate Car mode and voice controls during lazy setup --- frontend/car-mode.js | 4 ++-- frontend/car-mode.test.js | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/frontend/car-mode.js b/frontend/car-mode.js index b5e7234..8c683ab 100644 --- a/frontend/car-mode.js +++ b/frontend/car-mode.js @@ -10,7 +10,7 @@ overlay = doc.createElement('section'); overlay.className = 'car-mode'; overlay.setAttribute('role', 'dialog'); overlay.setAttribute('aria-modal', 'true'); overlay.setAttribute('aria-label', 'Car mode'); const exit = doc.createElement('button'); exit.type = 'button'; exit.className = 'car-exit'; exit.textContent = 'Exit Car mode'; exit.onclick = close; const title = doc.createElement('h1'); const controls = doc.createElement('div'); controls.className = 'car-controls'; let toggle; - for (const [label, action] of [['Previous', 'prev'], ['Play / Pause', 'toggle'], ['15 s back', 'back'], ['Next', 'next']]) { const b = doc.getElementById('voiceSearchBtn') || doc.createElement('button'); b.id='voiceSearchBtn'; b.type = 'button'; b.textContent = label; b.setAttribute('aria-label', label); b.onclick = () => adapter.action(action); if (action === 'toggle') toggle = b; controls.append(b); } + for (const [label, action] of [['Previous', 'prev'], ['Play / Pause', 'toggle'], ['15 s back', 'back'], ['Next', 'next']]) { const b = doc.createElement('button'); b.type = 'button'; b.textContent = label; b.setAttribute('aria-label', label); b.onclick = () => adapter.action(action); if (action === 'toggle') toggle = b; controls.append(b); } const update = () => { const state = adapter.state(); title.textContent = state.title || 'Choose a song before entering Car mode'; toggle.textContent = state.paused ? 'Play' : 'Pause'; }; update(); overlay.append(exit, title, controls); doc.body.append(overlay); timer = setInterval(update, 500); exit.focus(); overlay.onkeydown = e => { if (e.key === 'Escape') { e.preventDefault(); close(); } else if (e.key === 'Tab') { const buttons = [...overlay.querySelectorAll('button')], first = buttons[0], last = buttons.at(-1); if (e.shiftKey && doc.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && doc.activeElement === last) { e.preventDefault(); first.focus(); } } e.stopPropagation(); }; @@ -23,7 +23,7 @@ b.onclick = () => { if (listening) { recognition.abort(); return; } recognition = new Recognition(); recognition.lang = doc.documentElement.lang || root.navigator.language || 'en-US'; recognition.continuous = false; recognition.interimResults = false; recognition.onstart = () => { listening = true; b.setAttribute('aria-pressed', 'true'); b.title = 'Listening… tap to cancel'; }; recognition.onend = () => { listening = false; b.setAttribute('aria-pressed', 'false'); b.title = 'Voice search'; }; recognition.onerror = e => adapter.toast(`Voice search: ${e.error === 'not-allowed' ? 'microphone permission was denied' : e.error}`); recognition.onresult = e => { const query = transcript(e); if (query) { adapter.input.value = query; adapter.search(); } }; try { recognition.start(); } catch (error) { adapter.toast(error.message); } }; } const car = doc.getElementById('carModeBtn') || doc.createElement('button'); car.id='carModeBtn'; car.type = 'button'; car.className = 'icon-btn'; car.title = 'Car mode'; car.setAttribute('aria-label', 'Car mode'); car.innerHTML = ''; if(!car.isConnected)doc.getElementById('searchForm').after(car); car.onclick = open; - root.SettingsSections.register({ id: 'voice-car', title: 'Voice & Car mode', cluster: 'Listening', summary: () => Recognition ? 'Voice search available · Car mode' : 'Car mode · voice unavailable', render(container) { const p = doc.createElement('p'); p.textContent = Recognition ? 'Use the microphone beside Search to speak a query. Recognition availability and processing depend on your browser.' : 'Voice search is unavailable in this browser.'; const b = doc.getElementById('voiceSearchBtn') || doc.createElement('button'); b.id='voiceSearchBtn'; b.type = 'button'; b.className = 'settings-back'; b.textContent = 'Enter Car mode'; b.onclick = open; container.append(p, b); } }); + root.SettingsSections.register({ id: 'voice-car', title: 'Voice & Car mode', cluster: 'Listening', summary: () => Recognition ? 'Voice search available · Car mode' : 'Car mode · voice unavailable', render(container) { const p = doc.createElement('p'); p.textContent = Recognition ? 'Use the microphone beside Search to speak a query. Recognition availability and processing depend on your browser.' : 'Voice search is unavailable in this browser.'; const b = doc.createElement('button'); b.type = 'button'; b.className = 'settings-back'; b.textContent = 'Enter Car mode'; b.onclick = open; container.append(p, b); } }); } const api = { transcript, configure, open, close }; if (typeof module !== 'undefined') module.exports = api; else root.CarMode = api; })(typeof window !== 'undefined' ? window : globalThis); diff --git a/frontend/car-mode.test.js b/frontend/car-mode.test.js index ae51c4e..3c77194 100644 --- a/frontend/car-mode.test.js +++ b/frontend/car-mode.test.js @@ -1,2 +1,26 @@ const { test } = require('node:test'), assert = require('node:assert/strict'); const { transcript } = require('./car-mode'); test('voice search submits only final results from the result index', () => { const interim = [{transcript:'wrong'}]; interim.isFinal = false; const final = [{transcript:'Amazing Grace'}]; final.isFinal = true; assert.equal(transcript({results:[interim, final]}), 'Amazing Grace'); assert.equal(transcript({resultIndex:2,results:[final,final]}), ''); assert.equal(transcript({}), ''); }); + +test('lazy Car mode keeps four independent transport buttons and the voice entry in place', () => { + const vm=require('node:vm'),fs=require('node:fs'); + class Element { + constructor(tag){this.tag=tag;this.children=[];this.inert=false;} + append(...nodes){for(const node of nodes){node.remove();node.parent=this;this.children.push(node);}} + remove(){if(this.parent){this.parent.children=this.parent.children.filter(n=>n!==this);this.parent=null;}} + after(node){this.parent.append(node);} + setAttribute(name,value){this[name]=value;} + focus(){} + get isConnected(){return !!this.parent;} + } + const body=new Element('body'),input=new Element('input'),form=new Element('form'),voice=new Element('button');form.id='searchForm';voice.id='voiceSearchBtn';body.append(form,input,voice); + const all=node=>[node,...node.children.flatMap(all)],doc={body,documentElement:{lang:'en'},createElement:tag=>new Element(tag),getElementById:id=>all(body).find(n=>n.id===id)}; + let section;const actions=[],root={document:doc,navigator:{},SpeechRecognition:function(){},SettingsSections:{register:s=>section=s}}; + vm.runInNewContext(fs.readFileSync(__dirname+'/car-mode.js','utf8'),{window:root,setInterval:()=>1,clearInterval:()=>{}}); + root.CarMode.configure({input,action:action=>actions.push(action),state:()=>({paused:true,title:'Song'})}); + root.CarMode.open();const overlay=body.children.find(n=>n.className==='car-mode'),controls=overlay.children.find(n=>n.className==='car-controls'); + assert.equal(controls.children.length,4);assert.equal(new Set(controls.children).size,4);assert.equal(voice.parent,body); + controls.children.forEach(b=>b.onclick());assert.deepEqual(actions,['prev','toggle','back','next']); + root.CarMode.close();assert.equal(voice.parent,body);assert.equal(body.inert,false); + const panel=new Element('section');body.append(panel);section.render(panel); + assert.equal(voice.parent,body,'settings must not steal the voice entry');assert.equal(panel.children.at(-1).textContent,'Enter Car mode'); +}); From 173eab8026094977996c115485be73aa285a9871 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 01:36:47 +0800 Subject: [PATCH 23/81] Preserve Settings control search with lazy feature panels --- frontend/settings-sections.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/frontend/settings-sections.js b/frontend/settings-sections.js index d5e7f3e..20a21c8 100644 --- a/frontend/settings-sections.js +++ b/frontend/settings-sections.js @@ -24,7 +24,8 @@ const icon = paths => ``; function mount(host, context = {}) { dispose(); - const document = host.ownerDocument, win = document.defaultView, sections = registry.list(), panels = new Map(), rows = new Map(), cleanups = []; + const document = host.ownerDocument, win = document.defaultView, sections = registry.list(), panels = new Map(), rows = new Map(), cleanups = [], searchLoads = new Set(); + let mounted = true; let remembered = ''; try { remembered = win.sessionStorage.getItem('ytpSettingsSection') || ''; } catch {} let active = registry.get(remembered) ? remembered : sections[0]?.id; host.classList.add('settings-browser'); @@ -80,6 +81,19 @@ function filter() { const query = input.value.trim(); results.replaceChildren(); results.hidden = !query; grid.hidden = !!query; if (!query) { empty.hidden = true; return; } + // Searching is explicit feature intent. Mount optional controls so their + // existing labels/help remain searchable without parsing them on opening Settings. + for (const section of sections) { + const panel=panels.get(section.id); + if(!section.lazyGroup || panel.dataset.rendered || searchLoads.has(section.id))continue; + searchLoads.add(section.id); + root.Lazy.load(section.lazyGroup).then(()=>{ + if(!mounted || !host.isConnected || panel.dataset.rendered)return; + panel.dataset.rendered='1'; + const cleanup=registry.get(section.id).render(panel,context);if(typeof cleanup==='function')cleanups.push(cleanup); + filter(); + }).catch(()=>searchLoads.delete(section.id)); + } const entries = []; for (const section of sections) { entries.push({ title: section.title, description: section.description || '', section: section.id }); @@ -101,11 +115,11 @@ const pop = event => { if (!host.isConnected) return; show(event.state?.ytpSettingsSection || active, !!event.state?.ytpSettingsSection); if (!event.state?.ytpSettingsSection) rows.get(active)?.button.focus({ preventScroll: true }); }; win.addEventListener('popstate', pop); input.addEventListener('input', filter); host.addEventListener('change', summaries); host.addEventListener('input', summaries); - const observer = new win.MutationObserver(summaries); observer.observe(detail, { childList: true, subtree: true, characterData: true }); + const observer = new win.MutationObserver(()=>{summaries();if(input.value.trim())filter();}); observer.observe(detail, { childList: true, subtree: true, characterData: true }); const state = win.history.state?.ytpSettingsSection; if (!state) win.history.replaceState({ ...win.history.state, ytpSettingsSection: null }, '', win.location.href); show(state || active, !!state); summaries(); - dispose = () => { observer.disconnect(); win.removeEventListener('popstate', pop); cleanups.forEach(fn => fn()); }; + dispose = () => { mounted=false;observer.disconnect(); win.removeEventListener('popstate', pop); cleanups.forEach(fn => fn()); }; return { open, refresh: summaries, dispose }; } const api = { ...registry, mount, search, normalize, createRegistry, clusters }; From 524a7b7f1d57cb63ee6c16486b04c1143730408b Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 01:40:48 +0800 Subject: [PATCH 24/81] Share the background asset warm pool across idle requests --- frontend/asset-worker.test.js | 13 ++++++++++--- frontend/sw.js | 9 ++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index 48b9909..c3be060 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -1,12 +1,12 @@ const {test}=require('node:test');const assert=require('node:assert/strict');const vm=require('node:vm');const fs=require('node:fs');const core=require('./asset-sync-core'); function environment(){ - const stores=new Map(),listeners={},messages=[],skips=[];const m={buildTag:'next',files:{'/index.html':{h:'index'},'/app.js':{h:'app'}},groups:{core:{files:['/index.html','/app.js']}}}; + const stores=new Map(),listeners={},messages=[],skips=[],fetches=[];const m={buildTag:'next',files:{'/index.html':{h:'index'},'/app.js':{h:'app'}},groups:{core:{files:['/index.html','/app.js']}}}; const storage={async keys(){return [...stores.keys()]},async delete(n){return stores.delete(n)},async open(n){if(!stores.has(n)){const map=new Map();stores.set(n,{async match(k){return map.get(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)?.clone()},async put(k,r){map.set(k,r.clone())},async keys(){return [...map.keys()].map(k=>({url:'https://local'+k}))},async delete(k){return map.delete(typeof k==='string'?k:new URL(k.url).pathname+new URL(k.url).search)}})}return stores.get(n)}}; - const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,setTimeout,clearTimeout,crypto:require('node:crypto').webcrypto,console,fetch:async u=>u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':m.files[u.split('?')[0]]?.h || ''}}),self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; + const sandbox={__BUILD_TAG__:'next',__ASSET_SYNC__:true,AssetSyncCore:core,importScripts:()=>{},caches:storage,URL,Response,Request,Headers,setTimeout,clearTimeout,crypto:require('node:crypto').webcrypto,console,fetch:async u=>{fetches.push(u);return u==='/api/manifest'?Response.json(m):new Response(u,{headers:{'X-Asset-Hash':m.files[u.split('?')[0]]?.h || ''}})},self:{location:{origin:'https://local'},addEventListener:(t,f)=>listeners[t]=f,skipWaiting:()=>skips.push(1),clients:{claim:async()=>{},matchAll:async()=>[{id:'old',postMessage:x=>messages.push(x)}]}}}; vm.runInNewContext(fs.readFileSync(__dirname+'/sw.js','utf8'),sandbox); async function dispatch(t,e={}){let p;listeners[t]({...e,waitUntil:v=>p=v});await p} async function request(url,mode='cors',clientId='new'){let p;listeners.fetch({request:{url:'https://local'+url,method:'GET',mode},clientId,respondWith:v=>p=v});return p} - return {storage,m,skips,dispatch,request}; + return {storage,m,skips,fetches,dispatch,request}; } test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal(reply.missing,1);assert.equal(reply.version,'next');assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);assert.equal((await e.request('/app.js?v=stale')).status,409);}); test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); @@ -35,3 +35,10 @@ test('a changed background contract is downloaded before ready and cannot fall b await e.dispatch('activate');await cache.delete('/extra.js?v=new'); const response=await e.request('/extra.js?v=new');assert.equal(response.headers.get('X-Asset-Hash'),'new');assert.notEqual(await response.text(),'old body'); }); + +test('overlapping idle warm messages share one download pool',async()=>{ + const e=environment();e.m.files['/extra.js']={h:'extra'};e.m.groups['feature:extra']={files:['/extra.js'],contract:1,background:true}; + await e.dispatch('install');await e.dispatch('activate'); + await Promise.all([e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}}),e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}})]); + assert.equal(e.fetches.filter(url=>url==='/extra.js?v=extra').length,1); +}); diff --git a/frontend/sw.js b/frontend/sw.js index b86a59c..d41a5c3 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -291,7 +291,7 @@ self.addEventListener('fetch', (e) => { // ---- Message: handle SKIP_WAITING from the client ---- const playingClients = new Map(), deferredClients = new Set(); -let activeLayout = 'classic', layoutReply; +let activeLayout = 'classic', layoutReply, warmTask; self.addEventListener('message', (e) => { if (ASSET_SYNC && e.data?.type === 'LAYOUT' && e.source && typeof e.data.value === 'string') { activeLayout = e.data.value; @@ -307,10 +307,13 @@ self.addEventListener('message', (e) => { })()); } if (ASSET_SYNC && e.data?.type === 'WARM_ASSETS' && !e.data.saveData) { - e.waitUntil((async()=>{ + // Boot, activation and multiple tabs can report idle together. Share the + // verified pool so they never download the same missing group twice. + warmTask ||= (async()=>{ const cache=await caches.open(AssetSyncCore.CACHE), m=(await AssetSyncCore.state(cache))?.current; if(m)await AssetSyncCore.syncAssets(m,{cache,fetchFn:fetch,groups:Object.keys(m.groups).filter(name=>m.groups[name].background)}); - })().catch(error=>console.warn('[asset-sync] idle warm interrupted',error.message))); + })().catch(error=>console.warn('[asset-sync] idle warm interrupted',error.message)).finally(()=>{warmTask=null;}); + e.waitUntil(warmTask); } if (e.data && e.data.type === 'PLAYING' && e.source) { playingClients.set(e.source.id, !!e.data.value); From 40b92ebc0dc50c522827830fccacb2b96613a1d0 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 03:50:57 +0800 Subject: [PATCH 25/81] Request selected layout styles before common CSS blocks the bootstrap --- frontend/index.html | 4 ++-- frontend/shell-consistency.test.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index bfc7c2a..377fb1b 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -16,6 +16,8 @@ content="default-src 'self'; img-src 'self' https: data: asset: http://asset.localhost blob:; media-src 'self' https: blob: asset: http://asset.localhost; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; script-src 'self' 'wasm-unsafe-eval' https://esm.sh; connect-src 'self' https: ipc: http://ipc.localhost blob:; worker-src 'self';" /> YT Player + + @@ -24,8 +26,6 @@ - - diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 92080a7..f42dc57 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -75,6 +75,7 @@ test('only core scripts and styles remain eager; native fallback and active layo } assert.ok(html.indexOf('id="ytp-assets"')')); + assert.ok(html.indexOf('src="lazy.js"')([^<]+)<\/script>/)[1]).groups,groups); for(const name of ['playlist','settings','service-mode','lyrics-editor'])assert.ok(groups['feature:'+name].eager); }); From c1a546a5c673d94ad129945850f9a2698eba3568 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 03:56:47 +0800 Subject: [PATCH 26/81] Keep shared layout visibility defaults in eager styles --- frontend/assets.json | 1 + frontend/index.html | 3 ++- frontend/layout-base.css | 11 +++++++++++ frontend/shell-consistency.test.js | 8 ++++++++ frontend/sw.js | 1 + frontend/theme-glass.css | 10 ---------- 6 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 frontend/layout-base.css diff --git a/frontend/assets.json b/frontend/assets.json index e845dec..253339a 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -8,6 +8,7 @@ "/styles.css", "/service-ui.css", "/refresh.css", + "/layout-base.css", "/recommendations.css", "/flag-ui.js", "/async-guard.js", diff --git a/frontend/index.html b/frontend/index.html index 377fb1b..5ffd4f6 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -16,7 +16,7 @@ content="default-src 'self'; img-src 'self' https: data: asset: http://asset.localhost blob:; media-src 'self' https: blob: asset: http://asset.localhost; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; script-src 'self' 'wasm-unsafe-eval' https://esm.sh; connect-src 'self' https: ipc: http://ipc.localhost blob:; worker-src 'self';" /> YT Player - + @@ -26,6 +26,7 @@ + diff --git a/frontend/layout-base.css b/frontend/layout-base.css new file mode 100644 index 0000000..2a0a1b1 --- /dev/null +++ b/frontend/layout-base.css @@ -0,0 +1,11 @@ +/* Shared markup defaults stay eager when individual layouts load on demand. */ +.stg-overlay, .skip10, .deck-chips, .vol-pct, .mode-name { display: none; } +.np-btn .ti, .np-btn .tl { pointer-events: none; } +.np-btn .ti { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; } +.np-btn .i-done { display: none; } +.np-btn.done .i-save { display: none; } +.np-btn.done .i-done { display: inline; } +.stg-bot, .ch-badge, .upnext-clear, .list-sub, .p2p-strip { display: none; } +.sleep-status .sl-ic, .sleep-status .sl-sub { display: none; } +.ab-group { display: contents; } +.mc-tune { display: none; } diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index f42dc57..d44f109 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -79,3 +79,11 @@ test('only core scripts and styles remain eager; native fallback and active layo assert.deepEqual(JSON.parse(html.match(/id="ytp-assets">([^<]+)<\/script>/)[1]).groups,groups); for(const name of ['playlist','settings','service-mode','lyrics-editor'])assert.ok(groups['feature:'+name].eager); }); + +test('layout-independent visibility and transport defaults stay in eager CSS',()=>{ + const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); + assert.ok(groups.core.files.includes('/layout-base.css')); + const shared=readFileSync(join(__dirname,'layout-base.css'),'utf8'); + for(const selector of ['.stg-overlay','.deck-chips','.np-btn.done .i-save','.sleep-status .sl-ic','.ab-group','.mc-tune'])assert.ok(shared.includes(selector)); + assert.ok(html.includes('href="layout-base.css"')); +}); diff --git a/frontend/sw.js b/frontend/sw.js index d41a5c3..efca9b4 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -60,6 +60,7 @@ const SHELL = [ '/styles.css', '/service-ui.css', '/refresh.css', + '/layout-base.css', '/theme-glass.css', '/theme-bento-hub.css', '/theme-f7.css', diff --git a/frontend/theme-glass.css b/frontend/theme-glass.css index c2f289f..090285a 100644 --- a/frontend/theme-glass.css +++ b/frontend/theme-glass.css @@ -14,12 +14,6 @@ * ========================================================================== */ /* Elements that only exist for this theme stay hidden elsewhere. */ -.stg-overlay, .skip10, .deck-chips, .vol-pct, .mode-name { display: none; } -.np-btn .ti, .np-btn .tl { pointer-events: none; } -.np-btn .ti { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; } -.np-btn .i-done { display: none; } -.np-btn.done .i-save { display: none; } -.np-btn.done .i-done { display: inline; } html[data-layout="glass-stage"] { --bg: #121317; @@ -202,8 +196,6 @@ html[data-layout="glass-stage"] .stg-overlay { justify-content: flex-start; } html[data-layout="glass-stage"] .stg-mid { margin: auto 0; } /* =========================== fidelity pass (matches the approved mockup) =========================== */ -.stg-bot, .ch-badge, .upnext-clear, .list-sub, .p2p-strip { display: none; } -.sleep-status .sl-ic, .sleep-status .sl-sub { display: none; } /* stage HUD */ html[data-layout="glass-stage"] .stg-bot { display: flex; position: absolute; left: 12px; right: 12px; bottom: 12px; justify-content: space-between; pointer-events: none; } @@ -292,7 +284,6 @@ html[data-layout="glass-stage"] .ps-txt small { font: 400 10px var(--mono); colo html[data-layout="glass-stage"] .ps-dl { width: 34px; height: 34px; border-radius: 12px; border: 0; background: rgba(255, 255, 255, 0.07); color: var(--accent-bright); font-size: 16px; cursor: pointer; } /* ===== quick row (clean rebuild): [A | B | ↺] [Fullscreen] [More] ===== */ -.ab-group { display: contents; } html[data-layout="glass-stage"] #controls .dk-quick { display: flex; flex-wrap: nowrap; align-items: center; justify-content: space-between; gap: 8px; } html[data-layout="glass-stage"] #controls .ab-group { display: inline-flex; align-items: stretch; gap: 2px; padding: 3px; border-radius: 14px; background: var(--tile); border: 1px solid var(--glass-line); flex: 0 1 auto; min-width: 0; } html[data-layout="glass-stage"] #controls .ab-group .ctrl { @@ -339,7 +330,6 @@ html[data-layout="glass-stage"] #controls .ab-group .ctrl { padding: 0 7px !impo html[data-layout="glass-stage"] #controls .ab-group #abClearBtn { padding: 0 7px !important; font-size: 13px !important; } /* ===== A-B · Fullscreen · More — styled like the mockup ===== */ -.mc-tune { display: none; } html[data-layout="glass-stage"] #controls .dk-quick { flex-wrap: wrap; justify-content: space-between; gap: 8px; } html[data-layout="glass-stage"] #controls .ab-group { padding: 2px; border-radius: 12px; gap: 0; background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.05); } html[data-layout="glass-stage"] #controls .ab-group .ctrl { height: 26px !important; padding: 0 10px !important; border-radius: 8px !important; font: 500 10px var(--mono) !important; color: var(--text-dim); } From 46ec9ab2ca0f1b5365b5b05b08052df967d6fcfc Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:02:43 +0800 Subject: [PATCH 27/81] Report layouts selected through imported settings to the worker --- frontend/app.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/app.js b/frontend/app.js index 26c2594..b6650e4 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -1669,7 +1669,10 @@ function applyAppearance() { const desiredLayout=s.layout || 'classic'; if(root.dataset.layout!==desiredLayout && !Lazy.loaded('layout:'+desiredLayout)) { Lazy.load('layout:'+desiredLayout).then(()=>{if((data.settings.layout||'classic')===desiredLayout)applyAppearance();}).catch(error=>toast(error.message)); - } else root.dataset.layout=desiredLayout; + } else { + root.dataset.layout=desiredLayout; + if(Lazy.layout!==desiredLayout) { Lazy.layout=desiredLayout; Lazy.reportLayout?.(); } + } } function fmtBytes(n) { if (!n) return '0 B'; From fab444b7b88435e07c017d9d561d1bed27077340 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:12:16 +0800 Subject: [PATCH 28/81] Start font preloads before the layout bootstrap --- frontend/index.html | 4 ++-- frontend/shell-consistency.test.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 5ffd4f6..e0cb08b 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -16,11 +16,11 @@ content="default-src 'self'; img-src 'self' https: data: asset: http://asset.localhost blob:; media-src 'self' https: blob: asset: http://asset.localhost; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:; script-src 'self' 'wasm-unsafe-eval' https://esm.sh; connect-src 'self' https: ipc: http://ipc.localhost blob:; worker-src 'self';" /> YT Player - - + + diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index d44f109..bbdfbff 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -76,6 +76,7 @@ test('only core scripts and styles remain eager; native fallback and active layo assert.ok(html.indexOf('id="ytp-assets"')')); assert.ok(html.indexOf('src="lazy.js"')([^<]+)<\/script>/)[1]).groups,groups); for(const name of ['playlist','settings','service-mode','lyrics-editor'])assert.ok(groups['feature:'+name].eager); }); From b84050578b3d75e9adb0b7b6632cbf7b276ba37a Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:19:02 +0800 Subject: [PATCH 29/81] Verify staged lazy loading and record Phase 3 measurements --- perf/README.md | 63 +- perf/baseline.mjs | 47 +- perf/lazy.mjs | 135 + perf/migration.mjs | 5 +- perf/results/phase3-final-2026-10-08.json | 2349 ++++++++++++++++ .../phase3-hashing-rollback-2026-10-08.json | 132 + perf/results/phase3-lazy-2026-10-08.json | 79 + .../phase3-migration-lossy-2026-10-08.json | 41 + ...ase3-migration-unthrottled-2026-10-08.json | 41 + .../phase3-phase0-initial-2026-10-08.json | 2420 +++++++++++++++++ .../phase3-sync-rollback-2026-10-08.json | 132 + plans/phase3-staged-apply-decision.md | 64 +- 12 files changed, 5462 insertions(+), 46 deletions(-) create mode 100644 perf/lazy.mjs create mode 100644 perf/results/phase3-final-2026-10-08.json create mode 100644 perf/results/phase3-hashing-rollback-2026-10-08.json create mode 100644 perf/results/phase3-lazy-2026-10-08.json create mode 100644 perf/results/phase3-migration-lossy-2026-10-08.json create mode 100644 perf/results/phase3-migration-unthrottled-2026-10-08.json create mode 100644 perf/results/phase3-phase0-initial-2026-10-08.json create mode 100644 perf/results/phase3-sync-rollback-2026-10-08.json diff --git a/perf/README.md b/perf/README.md index 32a4606..90fbbb7 100644 --- a/perf/README.md +++ b/perf/README.md @@ -209,6 +209,65 @@ inspect individual responses to distinguish those from app asset downloads. Migration results are `phase2-migration--2026-10-07.json`. `ASSET_SYNC=0` selects the legacy path while preserving the persistent utility cache. `ASSET_HASHING=0` also selects legacy sync because single-tag URLs cannot -pass per-file hash checks. Current assets.json groups all block; idle loading and -lazy parsing await Phase 3. Incremental mode now caches the manifested +pass per-file hash checks. In Phase 2 all assets.json groups blocked; Phase 3 selects core plus the active +layout and warms background groups at idle. Incremental mode now caches the manifested `piano-engine.mjs` even though it remains absent from the legacy SHELL. + + +## Phase 3 lazy loading and staged apply + +```bash +node perf/lazy.mjs --browser all +node perf/migration.mjs --browser all --profile lossy +node perf/migration.mjs --browser all --profile unthrottled +node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all \ + --out perf/results/phase3-final-2026-10-08.json \ + --compare perf/results/after-phase0-2026-10-07.json +node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario cold \ + --frontend-commit 7bc5b4f8b50d78ece3cca5100d54a97fece2748a \ + --out perf/results/phase3-phase0-initial-2026-10-08.json +ASSET_SYNC=0 node perf/baseline.mjs --runs 1 --browser all --profile lte \ + --scenario offline --out perf/results/phase3-sync-rollback-2026-10-08.json +ASSET_HASHING=0 node perf/baseline.mjs --runs 1 --browser all --profile lte \ + --scenario offline --out perf/results/phase3-hashing-rollback-2026-10-08.json +``` + +`initialJsCss` sums compressed Resource Timing bodies for page JS/CSS initiated +before DOMContentLoaded, excluding SW precache and later idle feature parsing. +The saved Phase 0 results lack that metric: `--frontend-commit` reconstructs its +frontend in scratch using the current delivery backend for a matched initial-byte +comparison. Historical boot/FCP comparisons still use `after-phase0`. Reduced +single-run measurements are directional; Phase 5 supplies repeated medians. +Update scenarios now wait for every build-N group to finish idle caching before +starting the counter, excluding unfinished initial downloads. Waiting-worker +bytes represent blocking readiness; an inactive layout's changed CSS downloads +later at idle after activation. + +The browser harness checks pre-body layout selection, immediate offline reload, +four distinct Car mode controls, optional Settings search, all extension panels, +zero network for warmed first use/layout switches, contract guards and pinned +instances. Known WebKit disconnected API transport errors are recorded separately; +script errors still fail. Save-Data prevents automatic warming. + +The index contains inert JSON and an external head bootstrap under unchanged +CSP. Source JSON mirrors assets.json for native/static shells; the server replaces +it with hashed build-local URLs. No boot-time manifest network request is added. +Shared layout visibility defaults remain eager in layout-base.css. +Pure EQ settings metadata and DeviceDB remain eager to preserve synchronous +player defaults and offline file bookkeeping. P2P/direct parse on actual use or +the existing eight-second sharing startup. Searching Settings explicitly loads +optional panels so their original labels remain searchable. + +| JS-requested assets | Phase 3 URL treatment | +|---|---| +| opfs-worker.js, hash-worker.js, direct-recv-worker.js, p2p-recv-worker.js | Lazy.worker uses embedded per-file URL | +| Workers' sha256.js, resume-core.js, sha256-wasm.js | First postMessage carries originating build URLs; importScripts uses them | +| piano-engine.mjs | Dynamic import uses Lazy.url; incremental cache warms it | +| vendor/framework7-swipe.min.js | Ordered layout group and fallback use Lazy.url | +| loudness-wasm.js | Remains an eager stamped script; embedded binary needs no separate URL | +| fonts/fonts.css and font preloads; webmanifest/icons | Plain URLs stay aligned with CSS/manifest references; all belong to manifested cache groups | + +Legacy pages cannot report their selected layout. Their one-time migration blocks +all layouts to preserve immediate offline selection; modern pages block only the +reported layout and its shared controls. Executing groups never re-evaluate live. +See plans/phase3-staged-apply-decision.md: Phase 4 must add disposal/state handoff. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index b4c893c..f3d4bbf 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -25,7 +25,7 @@ * --compare Compare results against a previous baseline JSON */ -import { spawn, spawnSync } from 'node:child_process'; +import { spawn, spawnSync, execFileSync } from 'node:child_process'; import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -58,6 +58,7 @@ function parseArgs() { scenario: 'all', // 'cold', 'warm', 'offline', 'update-js', 'update-css', or 'all' out: null, compare: null, + frontendCommit: null, }; for (let i = 0; i < args.length; i++) { @@ -67,6 +68,7 @@ function parseArgs() { else if (a === '--profile' && i + 1 < args.length) options.profile = args[++i]; else if (a === '--scenario' && i + 1 < args.length) options.scenario = args[++i]; else if (a === '--out' && i + 1 < args.length) options.out = args[++i]; + else if (a === '--frontend-commit' && i + 1 < args.length) options.frontendCommit = args[++i]; else if (a === '--compare' && i + 1 < args.length) options.compare = args[++i]; } @@ -365,6 +367,8 @@ async function runColdScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -393,6 +397,8 @@ async function runColdScenario({ browserType, server, proxy, profile }) { bootDone: pageMetrics.bootDone, longTaskTotal: pageMetrics.longTaskTotal, requests: stats.requests, + initialJsCss: pageMetrics.initialJsCss, + initialAssetRequests: pageMetrics.initialAssetRequests, swInstallDuration, swInstallBytes: stats.totalWireBytes, storageEstimate: storage, @@ -465,6 +471,8 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -542,6 +550,8 @@ async function runOfflineScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -602,6 +612,27 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi await sleep(50); } + // Phase 3 activation precedes idle feature caching. Measure updates from a + // genuinely warm build, rather than counting unfinished first-install bytes. + if (await page.evaluate(()=>!!window.Lazy && !!window.Lazy.warm)) { + await page.evaluate(()=>Lazy.warm()); + const end=Date.now()+90000; + while (true) { + const ready=await page.evaluate(async()=>{ + const c=await caches.open('ytplayer-assets'),r=await c.match('/__ytp_asset_state'); + if(!r)return false; + const m=(await r.json()).current; + return (await Promise.all(Object.values(m.groups).flatMap(g=>g.files).map(async p=>{ + const response=await c.match(p+'?v='+m.files[p].h); + return response?.headers.get('X-Asset-Hash')===m.files[p].h; + }))).every(Boolean); + }); + if(ready)break; + if(Date.now()>end)throw Error('Idle warm did not complete before update benchmark'); + await sleep(100); + } + } + // Switch server to Tree N+1 (app.js or theme-glass.css modification) const targetTree = updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss; await server.restartWithPublic(targetTree); @@ -666,9 +697,14 @@ async function main() { const treeUpdateJs = path.join(tmpRoot, 'tree-update-js'); const treeUpdateCss = path.join(tmpRoot, 'tree-update-css'); - cpSync(path.join(REPO_ROOT, 'frontend'), treeBase, { recursive: true }); - cpSync(path.join(REPO_ROOT, 'frontend'), treeUpdateJs, { recursive: true }); - cpSync(path.join(REPO_ROOT, 'frontend'), treeUpdateCss, { recursive: true }); + let frontendSource=path.join(REPO_ROOT,'frontend'); + if(options.frontendCommit) { + const archive=path.join(tmpRoot,'frontend.tar'); + writeFileSync(archive,execFileSync('git',['archive',options.frontendCommit,'frontend'],{cwd:REPO_ROOT,maxBuffer:20*1024*1024})); + execFileSync('tar',['-xf',archive,'-C',tmpRoot]); + frontendSource=path.join(tmpRoot,'frontend'); + } + for(const tree of [treeBase,treeUpdateJs,treeUpdateCss])cpSync(frontendSource,tree,{recursive:true}); // Append 1 comment line to app.js in treeUpdateJs appendFileSync(path.join(treeUpdateJs, 'app.js'), '\n// baseline bench: 1-line app.js comment\n'); @@ -684,6 +720,7 @@ async function main() { const results = { date: new Date().toISOString(), + frontendCommit: options.frontendCommit, commit: spawnSync('git', ['rev-parse', 'HEAD'], { cwd: REPO_ROOT }).stdout.toString().trim(), runsConfigured: options.runs, browsers: {}, @@ -729,6 +766,8 @@ async function main() { autoplayBlocked: coldRuns.some((r) => r.autoplayBlocked), wireBytesByType: coldRuns[0]?.wireBytesByType || {}, requests: coldRuns[0]?.requests || [], + initialJsCss: summarizeList(coldRuns.map(r=>r.initialJsCss)), + initialAssetRequests: coldRuns[0]?.initialAssetRequests || [], }; } diff --git a/perf/lazy.mjs b/perf/lazy.mjs new file mode 100644 index 0000000..6b6092a --- /dev/null +++ b/perf/lazy.mjs @@ -0,0 +1,135 @@ +#!/usr/bin/env node +// Phase 3 checks against the real Bun server, a same-origin restart and real workers. +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { mkdtempSync, cpSync, mkdirSync, symlinkSync, readFileSync, writeFileSync, rmSync } from 'node:fs'; +import { resolve, join } from 'node:path'; +import { createServer } from 'node:net'; +import { chromium, webkit } from 'playwright'; +import { createThrottleProxy } from './proxy.mjs'; +const repo=resolve(new URL('..',import.meta.url).pathname), scratch=mkdtempSync(join(repo,'perf/.tmp/lazy-')); +const sleep=ms=>new Promise(r=>setTimeout(r,ms)); +async function wait(page,fn,arg,timeout=90000){const end=Date.now()+timeout;while(Date.now(){ + await Lazy.load('layout:'+Lazy.layout); + const settle=()=>new Promise(resolve=>setTimeout(resolve,300));await settle(); + const nodes=[...document.querySelectorAll('body,body *')],props=['display','position','color','background-color','font-family','font-size','padding','margin','border-radius','--bg','--text','--radius']; + const snapshot=()=>nodes.map(n=>props.map(p=>getComputedStyle(n).getPropertyValue(p))); + const links=[...document.querySelectorAll('link[data-lazy-css]')],positions=links.map(n=>[n,n.nextSibling]),before=snapshot(); + const loaded=()=>new Promise((resolve,reject)=>{let tries=0;function poll(){if(links.every(n=>n.sheet))return resolve();if(tries++>120)return reject(Error('Reordered CSS did not load'));requestAnimationFrame(poll);}poll();}); + links.forEach(n=>document.head.append(n));await loaded();await settle();const after=snapshot(); + for(const [n,next] of positions.reverse())document.head.insertBefore(n,next); + await loaded();await settle(); + return before.flatMap((values,i)=>values.flatMap((v,j)=>v===after[i][j]?[]:[{element:nodes[i].id||nodes[i].className,property:props[j],before:v,after:after[i][j]}])); + }); + assert.deepEqual(changes,[],'requesting scoped layout CSS earlier preserves its computed appearance'); +} +const args=process.argv.slice(2), requested=args.includes('--browser')?args[args.indexOf('--browser')+1]:'all'; +const results=[]; +async function run(name){ + const cwd=join(scratch,name);mkdirSync(cwd);cpSync(join(repo,'frontend'),join(cwd,'public'),{recursive:true}); + const portServer=createServer();await new Promise(r=>portServer.listen(0,'127.0.0.1',r));const port=portServer.address().port;await new Promise(r=>portServer.close(r)); + let child,browser,proxy,log=''; + async function stop(){if(!child)return;const p=child;child=null;if(p.exitCode===null){p.kill('SIGTERM');await new Promise(r=>p.once('exit',r));}} + async function start(){log='';child=spawn('bun',[join(repo,'server/server.js')],{cwd,env:{...process.env,PORT:String(port),ASSET_HASHING:'1',ASSET_SYNC:'1',BUILD_TAG:'',DB_PATH:join(cwd,'db.sqlite'),DATA_DIR:join(cwd,'data'),MEDIA_DIR:join(cwd,'media'),UPLOAD_DIR:join(cwd,'uploads')},stdio:['ignore','pipe','pipe']});for(const stream of [child.stdout,child.stderr])stream.on('data',c=>log=(log+c).slice(-15000));for(let i=0;i<200;i++){if(child.exitCode!==null)throw Error(log);try{if((await fetch('http://127.0.0.1:'+port+'/api/version')).ok)return;}catch{}await sleep(100);}throw Error(log);} + try { + await start();proxy=createThrottleProxy({targetPort:port,profile:'unthrottled'});const origin='http://127.0.0.1:'+await proxy.listen();proxy.startTracking(); + browser=await ({chromium,webkit}[name]).launch({headless:true});const context=await browser.newContext();let disconnected=false; + await context.route('**/*',r=>r.request().url().startsWith(origin)?r.continue():r.abort()); + await context.addInitScript(()=>{window.__saveData=localStorage.getItem('perf-save-data')==='1';const observer=new MutationObserver(()=>{if(document.body){window.__firstBodyLayout=document.documentElement.dataset.layout;observer.disconnect();}});observer.observe(document,{childList:true,subtree:true});Object.defineProperty(navigator,'onLine',{configurable:true,get:()=>localStorage.getItem('perf-offline')!=='1'});Object.defineProperty(navigator,'connection',{configurable:true,value:{get saveData(){return window.__saveData;}}});}); + const page=await context.newPage(),errors=[],failedRequests=[];page.on('requestfailed',request=>{if(disconnected)failedRequests.push(request.url());});page.on('pageerror',e=>errors.push({message:e.message,disconnected}));page.on('console',m=>{if(m.type()==='error')console.log(name,'console:',m.text());}); + console.log(name,'initial boot');await page.goto(origin);await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn')); + await wait(page,async()=>!!(await navigator.serviceWorker.getRegistration())?.active); + await page.evaluate(()=>Lazy.warm()); + await wait(page,async()=>{const c=await caches.open('ytplayer-assets'),r=await c.match('/__ytp_asset_state');if(!r)return false;const s=await r.json();return !(await Promise.all(Object.values(s.current.groups).flatMap(g=>g.files).map(async p=>!!await c.match(p+'?v='+s.current.files[p].h)))).includes(false);}); + console.log(name,'warm complete');assert.equal(await page.evaluate(()=>Lazy.loaded('feature:car-mode')),false); + assert.equal(await page.evaluate(()=>[...document.querySelectorAll('.stg-overlay,.deck-chips,.vol-pct,.mode-name,.stg-bot,.ch-badge,.upnext-clear,.list-sub,.p2p-strip,.sleep-status .sl-ic,.sleep-status .sl-sub,.mc-tune')].every(n=>getComputedStyle(n).display==='none')),true,'classic retains shared visibility defaults without loading Glass CSS'); + await checkCssOrder(page); + assert.equal(await page.evaluate(()=>Lazy.loaded('feature:piano')),false); + assert.equal(await page.evaluate(()=>[typeof newPlaylist,typeof renderSettings,typeof enterServiceMode,typeof Notes.load,typeof LyricsCore.fromText].every(type=>type==='function')),true,'playlist, settings, service mode and lyric core remain in RAM'); + // Profile/imported settings use applyAppearance, not the Settings select handler. + await page.evaluate(()=>{data.settings.layout='glass-stage';applyAppearance();}); + await wait(page,()=>document.documentElement.dataset.layout==='glass-stage'&&Lazy.layout==='glass-stage'); + await page.evaluate(()=>{data.settings.layout='classic';applyAppearance();}); + await wait(page,()=>document.documentElement.dataset.layout==='classic'&&Lazy.layout==='classic'); + // Eager application panels stay usable without executing optional settings modules. + await page.click('[data-view="settings"]');await page.click('[data-section="appearance"]');await page.waitForSelector('#setLayout'); + assert.equal(await page.evaluate(()=>Lazy.loaded('feature:piano')),false); + await page.selectOption('#setLayout','glass-stage');await page.waitForFunction(()=>document.documentElement.dataset.layout==='glass-stage'); + await page.evaluate(()=>{window.__saveData=true;localStorage.setItem('perf-save-data','1');localStorage.setItem('perf-offline','1');}); + await stop();disconnected=true;await proxy.setOffline(true); + console.log(name,'offline reload');await page.reload();await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn')); + assert.equal(await page.evaluate(()=>document.documentElement.dataset.layout),'glass-stage'); + assert.equal(await page.evaluate(()=>window.__firstBodyLayout),'glass-stage','selected layout is established before body/first paint'); + await checkCssOrder(page); + const before=proxy.getStats().requestCount; + await page.getByRole('button',{name:'Car mode',exact:true}).click();await page.waitForSelector('.car-mode'); + assert.equal(await page.locator('.car-controls button').count(),4,'all transport controls survive lazy setup'); + assert.equal(await page.locator('.car-controls #voiceSearchBtn').count(),0,'voice search stays outside transport'); + await page.getByRole('button',{name:'Exit Car mode'}).click(); + assert.equal(proxy.getStats().requestCount,before,'warmed feature first use reaches no network'); + await page.click('[data-view="settings"]');await page.click('[data-section="appearance"]');await page.selectOption('#setLayout','bento-hub');await page.waitForFunction(()=>document.documentElement.dataset.layout==='bento-hub'); + await page.selectOption('#setLayout','f7-swipe');await page.waitForFunction(()=>document.documentElement.dataset.layout==='f7-swipe'&&!!window.Framework7); + await page.selectOption('#setLayout','classic');await page.waitForFunction(()=>document.documentElement.dataset.layout==='classic'); + assert.equal(proxy.getStats().requestCount,before,'offline layout changes reach no network'); + await page.getByRole('searchbox',{name:'Search settings and controls'}).fill('Enable piano transcription'); + await page.locator('.settings-results button').first().waitFor(); + await page.getByRole('searchbox',{name:'Search settings and controls'}).fill(''); + // Every extension panel renders from disk without executing other panels eagerly. + for(const id of ['piano','midi','floating-lyrics','vocal-reducer','equalizer','setlist-import','broadcast']) { + await page.evaluate(id=>document.querySelector('[data-section="'+id+'"]').click(),id); + await wait(page,async id=>{const section=SettingsSections.get(id);return !section.lazyGroup;},id); + } + await page.evaluate(async()=>{await Lazy.load('feature:export');await Lazy.load('feature:video-edit');}); + assert.equal(proxy.getStats().requestCount,before,'all warmed extension assets stay offline'); + await start();disconnected=false;await proxy.setOffline(false);await page.evaluate(()=>localStorage.removeItem('perf-offline')); + // Keep an old tab whose core and group contracts remain those of build N. + const old=await context.newPage();old.on('pageerror',e=>errors.push({message:e.message,disconnected}));await old.goto(origin);await old.waitForSelector('#carModeBtn'); + await old.evaluate(async()=>{window.__saveData=true;await Lazy.load('feature:setlist-import');window.__pinned=window.SetlistImport;}); + await page.evaluate(()=>window.__saveData=true); + const previous=await page.evaluate(()=>Lazy.manifest); + await stop(); + for(const file of ['video-edit.js','setlist-import.js','car-mode.js'])writeFileSync(join(cwd,'public',file),readFileSync(join(cwd,'public',file),'utf8')+'\n// phase3 new file\n'); + const defs=JSON.parse(readFileSync(join(cwd,'public/assets.json')));defs.groups['feature:car-mode'].contract=2;writeFileSync(join(cwd,'public/assets.json'),JSON.stringify(defs)); + // Production stamping replaces the source-only native map with these updated groups. + await start();const target=await(await fetch(origin+'/api/manifest')).json(); + await page.evaluate(async()=>{window.__saveData=true;const r=await navigator.serviceWorker.getRegistration();await r.update();}); + await wait(page,async target=>{const r=await navigator.serviceWorker.getRegistration();if(!r?.waiting)return false;return(await SwUpdate.askCacheStatus(r.waiting))?.version===target;},target.buildTag); + // No automatic navigation; a real playing flag blocks the real apply flow. + let navs=0;page.on('framenavigated',f=>{if(f===page.mainFrame())navs++;}); + await sleep(1000);assert.equal(navs,0); + await page.evaluate(()=>Player._wantsPlaying=true); + page.once('dialog',d=>d.dismiss()); + const guard=await page.evaluate(async()=>{try{await SwUpdate.applyUpdate({getRegistration:()=>navigator.serviceWorker.getRegistration(),askStatus:SwUpdate.askCacheStatus,reload:()=>location.reload()});return false;}catch{return true;}}); + assert.equal(guard,true);assert.equal(navs,0); + await page.evaluate(()=>Player._wantsPlaying=false); + // Explicit worker message, then explicit navigation into new stamped core. + await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});}); + await wait(page,async tag=>{const c=await caches.open('ytplayer-assets');return(await(await c.match('/__ytp_asset_state')).json()).current.buildTag===tag;},target.buildTag); + await page.reload();await page.waitForSelector('#carModeBtn');assert.equal(await page.evaluate(()=>Lazy.manifest.buildTag),target.buildTag); + // No warm: the new page gets a same-contract N-1 file immediately from disk. + const cacheKey='/video-edit.js?v='+target.files['/video-edit.js'].h; + assert.equal(await page.evaluate(async key=>!!await(await caches.open('ytplayer-assets')).match(key),cacheKey),false); + const stale=await page.evaluate(async key=>{const r=await fetch(key);return {h:r.headers.get('X-Asset-Hash'),body:await r.text()};},cacheKey); + assert.equal(stale.h,previous.files['/video-edit.js'].h);assert.ok(!stale.body.includes('// phase3 new file')); + await page.evaluate(()=>Lazy.load('feature:video-edit'));const pinned=await page.evaluate(()=>{window.__videoPinned=VideoEdit;return Lazy.loaded('feature:video-edit');});assert.equal(pinned,true); + // Different contract is already downloaded before commit, but the old core must keep N-1. + const oldRequests=[];old.on('request',r=>oldRequests.push(r.url())); + await old.evaluate(()=>Lazy.load('feature:car-mode'));assert.equal(await old.evaluate(()=>Lazy.reloadRequired),true); + await old.getByRole('button',{name:'Refresh UI',exact:true}).waitFor(); + assert.ok(oldRequests.some(u=>u.includes('/car-mode.js?v='+previous.files['/car-mode.js'].h))); + await old.evaluate(()=>Lazy.load('feature:setlist-import'));assert.equal(await old.evaluate(()=>window.SetlistImport===window.__pinned),true); + // Warm new files explicitly; compatible, unexecuted old-page group selects new cached URL. + await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.active.postMessage({type:'WARM_ASSETS',saveData:false});}); + await wait(page,async key=>!!await(await caches.open('ytplayer-assets')).match(key),cacheKey); + await old.evaluate(()=>Lazy.load('feature:video-edit'));assert.ok(oldRequests.some(u=>u.includes(cacheKey))); + await page.evaluate(()=>Lazy.load('feature:video-edit'));assert.equal(await page.evaluate(()=>window.VideoEdit===window.__videoPinned),true); + const offlineTransportErrors=errors.filter(error=>name==='webkit'&&error.disconnected&&(error.message==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(error.message))); + assert.deepEqual(errors.filter(error=>!offlineTransportErrors.includes(error)),[]); + if(offlineTransportErrors.length)assert.ok(failedRequests.some(url=>/\/api\/(?:recommendations|version)/.test(url))); + results.push({browser:name,sourceBuildTag:previous.buildTag,classicSharedDefaults:true,cssOrderPreserved:true,settingsSearch:true,carControls:4,offlineFeature:true,firstUseNetwork:0,layoutsOffline:['glass-stage','bento-hub','f7-swipe','classic'],pinned:true,compatibleUnexecutedNewURL:true,incompatibleN1ReloadRequired:true,stagedN1:true,playbackGuard:true,prePaintLayout:true,offlineSettingsPanels:true,scriptErrors:[],offlineTransportErrors}); + console.log(name,'PASS'); + } finally {await browser?.close();await proxy?.close();await stop();} +} +try{for(const name of requested==='all'?['chromium','webkit']:[requested])await run(name);writeFileSync(join(repo,'perf/results/phase3-lazy-2026-10-08.json'),JSON.stringify({results},null,2)+'\n');}finally{rmSync(scratch,{recursive:true,force:true});} diff --git a/perf/migration.mjs b/perf/migration.mjs index 1a455b0..18b2683 100644 --- a/perf/migration.mjs +++ b/perf/migration.mjs @@ -153,6 +153,9 @@ async function run(name) { assert.equal(banners, 1, 'no banner after applying the current build'); assert.equal(await oldTab.evaluate(async()=>await (await fetch('/app.js')).text()),oldBytes,'open legacy tab keeps N-1 plain assets'); await oldTab.close(); + // Phase 3 commits core + layout first; idle warming must fill the retained full shell before offline feature checks. + await page.evaluate(()=>Lazy.warm()); + await waitAsync(page,async files=>{const cache=await caches.open('ytplayer-assets');return (await Promise.all(Object.keys(files).map(async path=>{const response=await cache.match(path+'?v='+files[path].h);return !!response&&response.headers.get('X-Asset-Hash')===files[path].h;}))).every(Boolean);},Object.fromEntries(shell.map(path=>[path==='/'?'/index.html':path,manifest.files[path==='/'?'/index.html':path]]))); const cacheResult = await page.evaluate(async ({ tag, shell, files }) => { const cache = await caches.open('ytplayer-assets'); const missing = [], incorrect = []; @@ -231,5 +234,5 @@ async function run(name) { try { const results = []; for (const name of browserName === 'all' ? ['chromium', 'webkit'] : [browserName]) results.push(await run(name)); - writeFileSync(join(repo, `perf/results/phase2-migration-${profile}-2026-10-07.json`), JSON.stringify({ commit, results }, null, 2) + '\n'); + writeFileSync(join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n'); } finally { rmSync(scratch, { recursive: true, force: true }); } diff --git a/perf/results/phase3-final-2026-10-08.json b/perf/results/phase3-final-2026-10-08.json new file mode 100644 index 0000000..ba2015f --- /dev/null +++ b/perf/results/phase3-final-2026-10-08.json @@ -0,0 +1,2349 @@ +{ + "date": "2026-10-07T20:12:26.084Z", + "frontendCommit": null, + "commit": "fab444b7b88435e07c017d9d561d1bed27077340", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 107, + "min": 107, + "max": 107, + "values": [ + 107 + ] + }, + "wireBytes": { + "median": 637636, + "min": 637636, + "max": 637636, + "values": [ + 637636 + ] + }, + "fcp": { + "median": 1356, + "min": 1356, + "max": 1356, + "values": [ + 1356 + ] + }, + "lcp": { + "median": 1356, + "min": 1356, + "max": 1356, + "values": [ + 1356 + ] + }, + "domContentLoaded": { + "median": 7171, + "min": 7171, + "max": 7171, + "values": [ + 7171 + ] + }, + "bootDone": { + "median": 7193, + "min": 7193, + "max": 7193, + "values": [ + 7193 + ] + }, + "longTaskTotal": { + "median": 287, + "min": 287, + "max": 287, + "values": [ + 287 + ] + }, + "swInstallDuration": { + "median": 36696, + "min": 36696, + "max": 36696, + "values": [ + 36696 + ] + }, + "swInstallBytes": { + "median": 637636, + "min": 637636, + "max": 637636, + "values": [ + 637636 + ] + }, + "storageEstimate": { + "usage": 2905100, + "quota": 5371614220 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 22486, + "js": 283987, + "css": 65916, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 4290, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/?v=benchmedia01", + "status": 200, + "bytes": 11243 + }, + { + "url": "http://127.0.0.1:6134/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6134/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6134/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 2534 + }, + { + "url": "http://127.0.0.1:6134/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6134/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6134/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6134/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6134/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6134/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6134/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6134/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6134/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6134/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6134/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6134/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6134/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6134/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6134/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6134/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6134/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6134/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6134/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6134/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6134/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6134/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6134/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6134/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6134/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6134/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6134/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6134/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6134/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6134/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6134/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6134/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6134/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6134/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6134/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 130118 + }, + { + "url": "http://127.0.0.1:6134/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6134/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7729 + }, + { + "url": "http://127.0.0.1:6134/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 2990 + }, + { + "url": "http://127.0.0.1:6134/assets.json?v=aa3952024e", + "status": 200, + "bytes": 964 + }, + { + "url": "http://127.0.0.1:6134/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:6134/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:6134/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:6134/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:6134/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6134/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:6134/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=b9eda89698", + "status": 200, + "bytes": 11243 + }, + { + "url": "http://127.0.0.1:6134/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6134/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:6134/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 3487 + }, + { + "url": "http://127.0.0.1:6134/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7729 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6134/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:6134/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:6134/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 1727 + }, + { + "url": "http://127.0.0.1:6134/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:6134/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 3697 + }, + { + "url": "http://127.0.0.1:6134/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:6134/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 875 + }, + { + "url": "http://127.0.0.1:6134/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6134/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:6134/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4158 + }, + { + "url": "http://127.0.0.1:6134/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:6134/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:6134/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:6134/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:6134/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:6134/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 542 + }, + { + "url": "http://127.0.0.1:6134/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:6134/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:6134/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2048 + }, + { + "url": "http://127.0.0.1:6134/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:6134/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 3850 + }, + { + "url": "http://127.0.0.1:6134/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1267 + }, + { + "url": "http://127.0.0.1:6134/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:6134/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2431 + }, + { + "url": "http://127.0.0.1:6134/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:6134/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:6134/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:6134/piano.js?v=e82bc30884", + "status": 200, + "bytes": 3453 + }, + { + "url": "http://127.0.0.1:6134/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:6134/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:6134/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:6134/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:6134/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:6134/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:6134/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:6134/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:6134/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:6134/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5068 + }, + { + "url": "http://127.0.0.1:6134/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:6134/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:6134/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 221307, + "min": 221307, + "max": 221307, + "values": [ + 221307 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:6134/lazy.js?v=98f6a419c3", + "bytes": 2534 + }, + { + "url": "http://127.0.0.1:6134/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6134/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6134/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6134/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6134/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6134/layout-base.css?v=4f3307cd3b", + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6134/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6134/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6134/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6134/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6134/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6134/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6134/opfs.js?v=df7a8d0391", + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6134/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6134/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6134/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6134/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6134/sha256.js?v=cd9b980e6f", + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6134/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6134/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6134/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6134/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6134/sw-update.js?v=772c123c20", + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6134/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6134/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.js?v=1101425859", + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6134/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6134/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6134/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6134/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6134/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6134/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6134/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6134/prewarm-next.js?v=ed16a51424", + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6134/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6134/feature-bootstrap.js?v=33779ecef7", + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=1d399bd3ef", + "bytes": 130118 + } + ] + }, + "warm": { + "requestCount": { + "median": 42, + "min": 42, + "max": 42, + "values": [ + 42 + ] + }, + "wireBytes": { + "median": 165400, + "min": 165400, + "max": 165400, + "values": [ + 165400 + ] + }, + "fcp": { + "median": 132, + "min": 132, + "max": 132, + "values": [ + 132 + ] + }, + "lcp": { + "median": 168, + "min": 168, + "max": 168, + "values": [ + 168 + ] + }, + "domContentLoaded": { + "median": 401, + "min": 401, + "max": 401, + "values": [ + 401 + ] + }, + "bootDone": { + "median": 419, + "min": 419, + "max": 419, + "values": [ + 419 + ] + }, + "longTaskTotal": { + "median": 59, + "min": 59, + "max": 59, + "values": [ + 59 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 52, + "min": 52, + "max": 52, + "values": [ + 52 + ] + }, + "lcp": { + "median": 52, + "min": 52, + "max": 52, + "values": [ + 52 + ] + }, + "domContentLoaded": { + "median": 163, + "min": 163, + "max": 163, + "values": [ + 163 + ] + }, + "bootDone": { + "median": 166, + "min": 166, + "max": 166, + "values": [ + 166 + ] + }, + "reloadDuration": { + "median": 187, + "min": 187, + "max": 187, + "values": [ + 187 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8 + ] + }, + "wireBytes": { + "median": 159905, + "min": 159905, + "max": 159905, + "values": [ + 159905 + ] + }, + "duration": { + "median": 964, + "min": 964, + "max": 964, + "values": [ + 964 + ] + }, + "wireBytesByType": { + "html": 11229, + "js": 145619, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3057, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7720 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 2995 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=4d214d16f1", + "status": 200, + "bytes": 130179 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=98e7f379a2", + "status": 200, + "bytes": 11229 + }, + { + "url": "http://127.0.0.1:6134/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7720 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + }, + "updateCss": { + "requestCount": { + "median": 7, + "min": 7, + "max": 7, + "values": [ + 7 + ] + }, + "wireBytes": { + "median": 29724, + "min": 29724, + "max": 29724, + "values": [ + 29724 + ] + }, + "duration": { + "median": 218, + "min": 218, + "max": 218, + "values": [ + 218 + ] + }, + "wireBytesByType": { + "html": 11233, + "js": 15440, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3051, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7720 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 2989 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=3a342efd0b", + "status": 200, + "bytes": 11233 + }, + { + "url": "http://127.0.0.1:6134/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 7720 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + } + } + }, + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 148, + "min": 148, + "max": 148, + "values": [ + 148 + ] + }, + "wireBytes": { + "median": 1108218, + "min": 1108218, + "max": 1108218, + "values": [ + 1108218 + ] + }, + "fcp": { + "median": 2467, + "min": 2467, + "max": 2467, + "values": [ + 2467 + ] + }, + "lcp": { + "median": 2539, + "min": 2539, + "max": 2539, + "values": [ + 2539 + ] + }, + "domContentLoaded": { + "median": 3287, + "min": 3287, + "max": 3287, + "values": [ + 3287 + ] + }, + "bootDone": { + "median": 3293, + "min": 3293, + "max": 3293, + "values": [ + 3293 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "swInstallDuration": { + "median": 32729, + "min": 32729, + "max": 32729, + "values": [ + 32729 + ] + }, + "swInstallBytes": { + "median": 1108218, + "min": 1108218, + "max": 1108218, + "values": [ + 1108218 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 27456, + "js": 568878, + "css": 133708, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 4692, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/?v=benchmedia01", + "status": 200, + "bytes": 13728 + }, + { + "url": "http://127.0.0.1:6134/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6134/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6134/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007 + }, + { + "url": "http://127.0.0.1:6134/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6134/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6134/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6134/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6134/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6134/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6134/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6134/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6134/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6134/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6134/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6134/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6134/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6134/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6134/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6134/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6134/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6134/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6134/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6134/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6134/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6134/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6134/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6134/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6134/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6134/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6134/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6134/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6134/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6134/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6134/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6134/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6134/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918 + }, + { + "url": "http://127.0.0.1:6134/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:6134/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:6134/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6134/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6134/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 8941 + }, + { + "url": "http://127.0.0.1:6134/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 3459 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/assets.json?v=aa3952024e", + "status": 200, + "bytes": 1112 + }, + { + "url": "http://127.0.0.1:6134/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6134/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6134/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6134/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6134/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6134/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6134/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6134/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6134/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6134/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6134/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6134/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6134/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:6134/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6134/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:6134/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6134/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:6134/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:6134/fonts/fonts.css", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6134/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:6134/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=3a342efd0b", + "status": 200, + "bytes": 13728 + }, + { + "url": "http://127.0.0.1:6134/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6134/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007 + }, + { + "url": "http://127.0.0.1:6134/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6134/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6134/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6134/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6134/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:6134/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6134/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042 + }, + { + "url": "http://127.0.0.1:6134/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6134/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6134/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6134/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6134/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6134/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6134/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915 + }, + { + "url": "http://127.0.0.1:6134/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6134/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6134/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6134/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6134/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6134/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6134/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6134/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6134/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:6134/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 8941 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:6134/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:6134/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080 + }, + { + "url": "http://127.0.0.1:6134/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:6134/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252 + }, + { + "url": "http://127.0.0.1:6134/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:6134/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216 + }, + { + "url": "http://127.0.0.1:6134/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:6134/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071 + }, + { + "url": "http://127.0.0.1:6134/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:6134/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763 + }, + { + "url": "http://127.0.0.1:6134/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:6134/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:6134/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:6134/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:6134/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624 + }, + { + "url": "http://127.0.0.1:6134/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:6134/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:6134/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474 + }, + { + "url": "http://127.0.0.1:6134/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:6134/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444 + }, + { + "url": "http://127.0.0.1:6134/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:6134/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475 + }, + { + "url": "http://127.0.0.1:6134/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773 + }, + { + "url": "http://127.0.0.1:6134/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:6134/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:6134/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:6134/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003 + }, + { + "url": "http://127.0.0.1:6134/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:6134/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:6134/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:6134/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:6134/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:6134/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:6134/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5939 + }, + { + "url": "http://127.0.0.1:6134/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829 + }, + { + "url": "http://127.0.0.1:6134/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:6134/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397 + } + ], + "initialJsCss": { + "median": 274813, + "min": 274813, + "max": 274813, + "values": [ + 274813 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:6134/fonts/fonts.css?v=dda3dfb804", + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6134/lazy.js?v=98f6a419c3", + "bytes": 3007 + }, + { + "url": "http://127.0.0.1:6134/layout-base.css?v=4f3307cd3b", + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6134/service-ui.css?v=b9bf96a3a8", + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6134/refresh.css?v=62498384f1", + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6134/recommendations.css?v=055101368d", + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6134/styles.css?v=9f3a5dea41", + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.css?v=055507ab85", + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6134/offline-pages.css?v=2889456261", + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6134/saved-page.css?v=3ff576a784", + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6134/related-videos.css?v=5a616b1be8", + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6134/download-actions.css?v=12d3bcfe3e", + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6134/fingerprint.js?v=a635143269", + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6134/opfs.js?v=df7a8d0391", + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6134/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6134/lyrics-display.js?v=48e8550175", + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6134/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6134/sha256-wasm.js?v=393c50ba56", + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6134/sha256.js?v=cd9b980e6f", + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6134/loudness-wasm.js?v=c6102d7844", + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6134/loudness.js?v=01b3da88dd", + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6134/device-db.js?v=880c5cd70e", + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6134/async-guard.js?v=e4afa1f2be", + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/related-videos.js?v=3eec0ebd4c", + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6134/sw-update.js?v=772c123c20", + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6134/audio-continuity.js?v=63b5464dd5", + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6134/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6134/download-actions.js?v=388c7edecb", + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6134/settings-sections.js?v=1101425859", + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6134/download-errors.js?v=bb6a4c887a", + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6134/downloads.js?v=f2d3e7d212", + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6134/downloads-page.js?v=c1a3a218c0", + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6134/saved-page.js?v=f1518c50fb", + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6134/server-backfill.js?v=294b103023", + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6134/visible-timer.js?v=5322e86ef4", + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6134/prewarm-next.js?v=ed16a51424", + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6134/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6134/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=1d399bd3ef", + "bytes": 165918 + }, + { + "url": "http://127.0.0.1:6134/theme-classic.css?v=d420fcfb12", + "bytes": 4079 + } + ] + }, + "warm": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 52, + "min": 52, + "max": 52, + "values": [ + 52 + ] + }, + "lcp": { + "median": 79, + "min": 79, + "max": 79, + "values": [ + 79 + ] + }, + "domContentLoaded": { + "median": 78, + "min": 78, + "max": 78, + "values": [ + 78 + ] + }, + "bootDone": { + "median": 81, + "min": 81, + "max": 81, + "values": [ + 81 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 54, + "min": 54, + "max": 54, + "values": [ + 54 + ] + }, + "lcp": { + "median": 82, + "min": 82, + "max": 82, + "values": [ + 82 + ] + }, + "domContentLoaded": { + "median": 81, + "min": 81, + "max": 81, + "values": [ + 81 + ] + }, + "bootDone": { + "median": 84, + "min": 84, + "max": 84, + "values": [ + 84 + ] + }, + "reloadDuration": { + "median": 100, + "min": 100, + "max": 100, + "values": [ + 100 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5 + ] + }, + "wireBytes": { + "median": 194026, + "min": 194026, + "max": 194026, + "values": [ + 194026 + ] + }, + "duration": { + "median": 2313, + "min": 2313, + "max": 2313, + "values": [ + 2313 + ] + }, + "wireBytesByType": { + "html": 13730, + "js": 176837, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3459, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 8942 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 3459 + }, + { + "url": "http://127.0.0.1:6134/app.js?v=4d214d16f1", + "status": 200, + "bytes": 165941 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=98e7f379a2", + "status": 200, + "bytes": 13730 + } + ] + }, + "updateCss": { + "requestCount": { + "median": 4, + "min": 4, + "max": 4, + "values": [ + 4 + ] + }, + "wireBytes": { + "median": 28082, + "min": 28082, + "max": 28082, + "values": [ + 28082 + ] + }, + "duration": { + "median": 931, + "min": 931, + "max": 931, + "values": [ + 931 + ] + }, + "wireBytesByType": { + "html": 13728, + "js": 10895, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3459, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6134/sw.js", + "status": 200, + "bytes": 8941 + }, + { + "url": "http://127.0.0.1:6134/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6134/api/manifest", + "status": 200, + "bytes": 3459 + }, + { + "url": "http://127.0.0.1:6134/index.html?v=3a342efd0b", + "status": 200, + "bytes": 13728 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase3-hashing-rollback-2026-10-08.json b/perf/results/phase3-hashing-rollback-2026-10-08.json new file mode 100644 index 0000000..535e017 --- /dev/null +++ b/perf/results/phase3-hashing-rollback-2026-10-08.json @@ -0,0 +1,132 @@ +{ + "date": "2026-10-07T20:10:25.561Z", + "frontendCommit": null, + "commit": "46ec9ab2ca0f1b5365b5b05b08052df967d6fcfc", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 48, + "min": 48, + "max": 48, + "values": [ + 48 + ] + }, + "lcp": { + "median": 48, + "min": 48, + "max": 48, + "values": [ + 48 + ] + }, + "domContentLoaded": { + "median": 165, + "min": 165, + "max": 165, + "values": [ + 165 + ] + }, + "bootDone": { + "median": 170, + "min": 170, + "max": 170, + "values": [ + 170 + ] + }, + "reloadDuration": { + "median": 187, + "min": 187, + "max": 187, + "values": [ + 187 + ] + } + } + } + }, + "webkit": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 80, + "min": 80, + "max": 80, + "values": [ + 80 + ] + }, + "lcp": { + "median": 136, + "min": 136, + "max": 136, + "values": [ + 136 + ] + }, + "domContentLoaded": { + "median": 134, + "min": 134, + "max": 134, + "values": [ + 134 + ] + }, + "bootDone": { + "median": 140, + "min": 140, + "max": 140, + "values": [ + 140 + ] + }, + "reloadDuration": { + "median": 163, + "min": 163, + "max": 163, + "values": [ + 163 + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase3-lazy-2026-10-08.json b/perf/results/phase3-lazy-2026-10-08.json new file mode 100644 index 0000000..8a9e836 --- /dev/null +++ b/perf/results/phase3-lazy-2026-10-08.json @@ -0,0 +1,79 @@ +{ + "results": [ + { + "browser": "chromium", + "sourceBuildTag": "bea1f63eba85", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [] + }, + { + "browser": "webkit", + "sourceBuildTag": "bea1f63eba85", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [ + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38845/api/version.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38845/api/recommendations?fp=163577c02a53bc40.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38845/api/version.", + "disconnected": true + } + ] + } + ] +} diff --git a/perf/results/phase3-migration-lossy-2026-10-08.json b/perf/results/phase3-migration-lossy-2026-10-08.json new file mode 100644 index 0000000..7ec206f --- /dev/null +++ b/perf/results/phase3-migration-lossy-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "bea1f63eba85", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 114, + "durationMs": 24356, + "wireBytes": 607853, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "bea1f63eba85", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 114, + "durationMs": 20402, + "wireBytes": 729652, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase3-migration-unthrottled-2026-10-08.json b/perf/results/phase3-migration-unthrottled-2026-10-08.json new file mode 100644 index 0000000..c01239f --- /dev/null +++ b/perf/results/phase3-migration-unthrottled-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "bea1f63eba85", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 114, + "durationMs": 10864, + "wireBytes": 625216, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "bea1f63eba85", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 114, + "durationMs": 9584, + "wireBytes": 743322, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase3-phase0-initial-2026-10-08.json b/perf/results/phase3-phase0-initial-2026-10-08.json new file mode 100644 index 0000000..c7ce2e6 --- /dev/null +++ b/perf/results/phase3-phase0-initial-2026-10-08.json @@ -0,0 +1,2420 @@ +{ + "date": "2026-10-07T20:04:55.178Z", + "frontendCommit": "7bc5b4f8b50d78ece3cca5100d54a97fece2748a", + "commit": "46ec9ab2ca0f1b5365b5b05b08052df967d6fcfc", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 166, + "min": 166, + "max": 166, + "values": [ + 166 + ] + }, + "wireBytes": { + "median": 1041605, + "min": 1041605, + "max": 1041605, + "values": [ + 1041605 + ] + }, + "fcp": { + "median": 1564, + "min": 1564, + "max": 1564, + "values": [ + 1564 + ] + }, + "lcp": { + "median": 1920, + "min": 1920, + "max": 1920, + "values": [ + 1920 + ] + }, + "domContentLoaded": { + "median": 10770, + "min": 10770, + "max": 10770, + "values": [ + 10770 + ] + }, + "bootDone": { + "median": 10902, + "min": 10902, + "max": 10902, + "values": [ + 10902 + ] + }, + "longTaskTotal": { + "median": 432, + "min": 432, + "max": 432, + "values": [ + 432 + ] + }, + "swInstallDuration": { + "median": 40411, + "min": 40411, + "max": 40411, + "values": [ + 40411 + ] + }, + "swInstallBytes": { + "median": 1041605, + "min": 1041605, + "max": 1041605, + "values": [ + 1041605 + ] + }, + "storageEstimate": { + "usage": 3486392, + "quota": 5372195512 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28461, + "js": 478109, + "css": 130718, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 336, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:5271/?v=benchmedia01", + "status": 200, + "bytes": 9487 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5271/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5271/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5271/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 5180 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5271/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 3905 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5271/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5271/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 2718 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5271/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5271/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 3822 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2420 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js?v=1c30917179", + "status": 200, + "bytes": 3549 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2373 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 3684 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5271/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4138 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2024 + }, + { + "url": "http://127.0.0.1:5271/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1341 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:5271/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3436 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 1678 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5271/app.js?v=341e4a973f", + "status": 200, + "bytes": 129398 + }, + { + "url": "http://127.0.0.1:5271/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5271/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5271/sw.js", + "status": 200, + "bytes": 5236 + }, + { + "url": "http://127.0.0.1:5271/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5271/", + "status": 200, + "bytes": 9487 + }, + { + "url": "http://127.0.0.1:5271/index.html", + "status": 200, + "bytes": 9487 + }, + { + "url": "http://127.0.0.1:5271/styles.css", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5271/refresh.css", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css", + "status": 200, + "bytes": 5180 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:5271/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5271/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5271/export.js", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js", + "status": 200, + "bytes": 3549 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5271/opfs.js", + "status": 200, + "bytes": 3905 + }, + { + "url": "http://127.0.0.1:5271/opfs-worker.js", + "status": 200, + "bytes": 3418 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:5271/sha256.js", + "status": 200, + "bytes": 2718 + }, + { + "url": "http://127.0.0.1:5271/resume-core.js", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5271/loudness.js", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5271/device-db.js", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5271/hash-worker.js", + "status": 200, + "bytes": 496 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js", + "status": 200, + "bytes": 3822 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js", + "status": 200, + "bytes": 3684 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:5271/direct-recv-worker.js", + "status": 200, + "bytes": 1012 + }, + { + "url": "http://127.0.0.1:5271/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js", + "status": 200, + "bytes": 2420 + }, + { + "url": "http://127.0.0.1:5271/p2p-recv-worker.js", + "status": 200, + "bytes": 1247 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js", + "status": 200, + "bytes": 2373 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5271/downloads.js", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js", + "status": 200, + "bytes": 4138 + }, + { + "url": "http://127.0.0.1:5271/vendor/framework7-swipe.min.js", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js", + "status": 200, + "bytes": 2024 + }, + { + "url": "http://127.0.0.1:5271/midi.js", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js", + "status": 200, + "bytes": 1341 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:5271/piano.js", + "status": 200, + "bytes": 3436 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js", + "status": 200, + "bytes": 1678 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5271/app.js", + "status": 200, + "bytes": 129398 + }, + { + "url": "http://127.0.0.1:5271/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:5271/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5271/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5271/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5271/sw.js", + "status": 200, + "bytes": 5236 + }, + { + "url": "http://127.0.0.1:5271/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:5271/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:5271/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 276414, + "min": 276414, + "max": 276414, + "values": [ + 276414 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5271/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5271/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5271/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css?v=2c482caf77", + "bytes": 5180 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css?v=19b8428bfd", + "bytes": 291 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css?v=031f8e0ead", + "bytes": 375 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css?v=7d421630b3", + "bytes": 385 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css?v=3354ad9631", + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 848 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css?v=02ba226f82", + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5271/opfs.js?v=0922d5004c", + "bytes": 3905 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js?v=90c5dd1eb6", + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5271/export.js?v=5b7cdcd7a3", + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js?v=3de0591d83", + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5271/sha256.js?v=68566d2e65", + "bytes": 2718 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5271/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5271/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js?v=0c59fc208b", + "bytes": 3822 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js?v=168a879219", + "bytes": 989 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js?v=2186d77fae", + "bytes": 2420 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js?v=1c30917179", + "bytes": 3549 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js?v=870249a743", + "bytes": 2373 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js?v=87a73be90f", + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js?v=d7f9871605", + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js?v=5c93a4508c", + "bytes": 3684 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5271/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js?v=a60ed1fe84", + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js?v=c867882d7e", + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js?v=99c11c557b", + "bytes": 4138 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js?v=d5417786d0", + "bytes": 965 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js?v=1677c38a88", + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js?v=68591e0c78", + "bytes": 2024 + }, + { + "url": "http://127.0.0.1:5271/midi.js?v=dbecfa74e1", + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js?v=7705dcbfb4", + "bytes": 927 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js?v=e9769cb594", + "bytes": 1341 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js?v=77c8269761", + "bytes": 756 + }, + { + "url": "http://127.0.0.1:5271/piano.js?v=79b13f0de0", + "bytes": 3436 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js?v=13bc5cc4a4", + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js?v=19f187c23f", + "bytes": 1678 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5271/app.js?v=341e4a973f", + "bytes": 129398 + } + ] + } + } + }, + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 164, + "min": 164, + "max": 164, + "values": [ + 164 + ] + }, + "wireBytes": { + "median": 1182513, + "min": 1182513, + "max": 1182513, + "values": [ + 1182513 + ] + }, + "fcp": { + "median": 1025, + "min": 1025, + "max": 1025, + "values": [ + 1025 + ] + }, + "lcp": { + "median": 1207, + "min": 1207, + "max": 1207, + "values": [ + 1207 + ] + }, + "domContentLoaded": { + "median": 3114, + "min": 3114, + "max": 3114, + "values": [ + 3114 + ] + }, + "bootDone": { + "median": 3136, + "min": 3136, + "max": 3136, + "values": [ + 3136 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "swInstallDuration": { + "median": 32582, + "min": 32582, + "max": 32582, + "values": [ + 32582 + ] + }, + "swInstallBytes": { + "median": 1182513, + "min": 1182513, + "max": 1182513, + "values": [ + 1182513 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 34392, + "js": 586396, + "css": 156688, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 121, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5271/?v=benchmedia01", + "status": 200, + "bytes": 11464 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5271/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5271/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5271/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5271/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5271/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5271/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5271/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5271/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js?v=1c30917179", + "status": 200, + "bytes": 4191 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5271/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447 + }, + { + "url": "http://127.0.0.1:5271/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:5271/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5271/app.js?v=341e4a973f", + "status": 200, + "bytes": 164771 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5271/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5271/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5271/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5271/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5271/sw.js", + "status": 200, + "bytes": 6162 + }, + { + "url": "http://127.0.0.1:5271/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5271/", + "status": 200, + "bytes": 11464 + }, + { + "url": "http://127.0.0.1:5271/index.html", + "status": 200, + "bytes": 11464 + }, + { + "url": "http://127.0.0.1:5271/styles.css", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5271/refresh.css", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css", + "status": 200, + "bytes": 6039 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:5271/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5271/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5271/export.js", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js", + "status": 200, + "bytes": 4191 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5271/opfs.js", + "status": 200, + "bytes": 4553 + }, + { + "url": "http://127.0.0.1:5271/opfs-worker.js", + "status": 200, + "bytes": 3957 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js", + "status": 200, + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:5271/sha256.js", + "status": 200, + "bytes": 3187 + }, + { + "url": "http://127.0.0.1:5271/resume-core.js", + "status": 200, + "bytes": 915 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5271/loudness.js", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5271/device-db.js", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5271/hash-worker.js", + "status": 200, + "bytes": 576 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js", + "status": 200, + "bytes": 4410 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js", + "status": 200, + "bytes": 4232 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:5271/direct-recv-worker.js", + "status": 200, + "bytes": 1174 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js", + "status": 200, + "bytes": 2758 + }, + { + "url": "http://127.0.0.1:5271/p2p-recv-worker.js", + "status": 200, + "bytes": 1429 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js", + "status": 200, + "bytes": 2811 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5271/downloads.js", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js", + "status": 200, + "bytes": 4747 + }, + { + "url": "http://127.0.0.1:5271/vendor/framework7-swipe.min.js", + "status": 200, + "bytes": 44829 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js", + "status": 200, + "bytes": 2447 + }, + { + "url": "http://127.0.0.1:5271/midi.js", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js", + "status": 200, + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js", + "status": 200, + "bytes": 1567 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:5271/piano.js", + "status": 200, + "bytes": 3986 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js", + "status": 200, + "bytes": 2029 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5271/app.js", + "status": 200, + "bytes": 164771 + }, + { + "url": "http://127.0.0.1:5271/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5271/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5271/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5271/fonts/fonts.css", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5271/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5271/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5271/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5271/sw.js", + "status": 200, + "bytes": 6162 + } + ], + "initialJsCss": { + "median": 338940, + "min": 338940, + "max": 338940, + "values": [ + 338940 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5271/fonts/fonts.css?v=dda3dfb804", + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5271/service-ui.css?v=b9bf96a3a8", + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5271/refresh.css?v=62498384f1", + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5271/theme-glass.css?v=2c482caf77", + "bytes": 6039 + }, + { + "url": "http://127.0.0.1:5271/styles.css?v=9f3a5dea41", + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5271/theme-classic.css?v=d420fcfb12", + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5271/recommendations.css?v=055101368d", + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.css?v=055507ab85", + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5271/direct-media.css?v=19b8428bfd", + "bytes": 370 + }, + { + "url": "http://127.0.0.1:5271/lower-third.css?v=031f8e0ead", + "bytes": 502 + }, + { + "url": "http://127.0.0.1:5271/car-mode.css?v=7d421630b3", + "bytes": 504 + }, + { + "url": "http://127.0.0.1:5271/offline-pages.css?v=2889456261", + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5271/saved-page.css?v=3ff576a784", + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:5271/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5271/related-videos.css?v=5a616b1be8", + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5271/download-actions.css?v=12d3bcfe3e", + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5271/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:5271/theme-f7.css?v=02ba226f82", + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:5271/fingerprint.js?v=a635143269", + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5271/video-edit.js?v=90c5dd1eb6", + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:5271/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5271/opfs.js?v=0922d5004c", + "bytes": 4553 + }, + { + "url": "http://127.0.0.1:5271/lyrics-display.js?v=48e8550175", + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5271/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5271/export.js?v=5b7cdcd7a3", + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:5271/sha256-wasm.js?v=393c50ba56", + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5271/stats-core.js?v=3de0591d83", + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:5271/sha256.js?v=68566d2e65", + "bytes": 3187 + }, + { + "url": "http://127.0.0.1:5271/loudness-wasm.js?v=c6102d7844", + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5271/loudness.js?v=01b3da88dd", + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5271/device-db.js?v=880c5cd70e", + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5271/p2p-core.js?v=168a879219", + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5271/p2p-transfer.js?v=2186d77fae", + "bytes": 2758 + }, + { + "url": "http://127.0.0.1:5271/p2p-client.js?v=0c59fc208b", + "bytes": 4410 + }, + { + "url": "http://127.0.0.1:5271/async-guard.js?v=e4afa1f2be", + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5271/sw-update.js?v=1c30917179", + "bytes": 4191 + }, + { + "url": "http://127.0.0.1:5271/related-videos.js?v=3eec0ebd4c", + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5271/audio-continuity.js?v=63b5464dd5", + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5271/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5271/settings-sections.js?v=870249a743", + "bytes": 2811 + }, + { + "url": "http://127.0.0.1:5271/direct-protocol.js?v=87a73be90f", + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5271/direct-stream.js?v=d7f9871605", + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:5271/direct-media.js?v=5c93a4508c", + "bytes": 4232 + }, + { + "url": "http://127.0.0.1:5271/download-actions.js?v=388c7edecb", + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5271/download-errors.js?v=bb6a4c887a", + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5271/downloads.js?v=f2d3e7d212", + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5271/downloads-page.js?v=c1a3a218c0", + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5271/saved-page.js?v=f1518c50fb", + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5271/server-backfill.js?v=294b103023", + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5271/glass-controls.js?v=a60ed1fe84", + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:5271/bento-hub.js?v=c867882d7e", + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:5271/f7-layout.js?v=99c11c557b", + "bytes": 4747 + }, + { + "url": "http://127.0.0.1:5271/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:5271/party-dj.js?v=1677c38a88", + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:5271/lyrics-window.js?v=68591e0c78", + "bytes": 2447 + }, + { + "url": "http://127.0.0.1:5271/midi.js?v=dbecfa74e1", + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:5271/lower-third.js?v=7705dcbfb4", + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:5271/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:5271/eq-core.js?v=e9769cb594", + "bytes": 1567 + }, + { + "url": "http://127.0.0.1:5271/piano-core.js?v=77c8269761", + "bytes": 867 + }, + { + "url": "http://127.0.0.1:5271/piano.js?v=79b13f0de0", + "bytes": 3986 + }, + { + "url": "http://127.0.0.1:5271/car-mode.js?v=19f187c23f", + "bytes": 2029 + }, + { + "url": "http://127.0.0.1:5271/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:5271/visible-timer.js?v=5322e86ef4", + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5271/app.js?v=341e4a973f", + "bytes": 164771 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase3-sync-rollback-2026-10-08.json b/perf/results/phase3-sync-rollback-2026-10-08.json new file mode 100644 index 0000000..27c179d --- /dev/null +++ b/perf/results/phase3-sync-rollback-2026-10-08.json @@ -0,0 +1,132 @@ +{ + "date": "2026-10-07T20:10:14.094Z", + "frontendCommit": null, + "commit": "46ec9ab2ca0f1b5365b5b05b08052df967d6fcfc", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 44, + "min": 44, + "max": 44, + "values": [ + 44 + ] + }, + "lcp": { + "median": 44, + "min": 44, + "max": 44, + "values": [ + 44 + ] + }, + "domContentLoaded": { + "median": 135, + "min": 135, + "max": 135, + "values": [ + 135 + ] + }, + "bootDone": { + "median": 140, + "min": 140, + "max": 140, + "values": [ + 140 + ] + }, + "reloadDuration": { + "median": 158, + "min": 158, + "max": 158, + "values": [ + 158 + ] + } + } + } + }, + "webkit": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 64, + "min": 64, + "max": 64, + "values": [ + 64 + ] + }, + "lcp": { + "median": 105, + "min": 105, + "max": 105, + "values": [ + 105 + ] + }, + "domContentLoaded": { + "median": 103, + "min": 103, + "max": 103, + "values": [ + 103 + ] + }, + "bootDone": { + "median": 107, + "min": 107, + "max": 107, + "values": [ + 107 + ] + }, + "reloadDuration": { + "median": 124, + "min": 124, + "max": 124, + "values": [ + 124 + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/plans/phase3-staged-apply-decision.md b/plans/phase3-staged-apply-decision.md index bd7bee6..d6935c2 100644 --- a/plans/phase3-staged-apply-decision.md +++ b/plans/phase3-staged-apply-decision.md @@ -1,43 +1,29 @@ -# Phase 3 — decision required before live module replacement +# Phase 3 staged apply — accepted owner decision -COMMON.md says: "If you hit a decision that changes user-visible behaviour or -risks data loss that the documents do not answer, write QUESTION ... and end your -turn instead." This concerns §2c.5's instruction to switch stale modules when -new bytes arrive, after a new build has booted using a same-contract fallback. +The owner accepted this decision on 2026-10-08. It refines master §2c.5: +background downloading never implies that an executing classic script can be +safely replaced. -Concrete finding: direct-media.js creates private rooms, pending, transfers and -waiting maps at module evaluation (lines 4–6). Its public API has no busy, -dispose or state handoff method. Re-evaluation replaces window.DirectMedia, -while WebRTC callbacks/workers still close over the old maps. Later messages -routed by app.js through the new DirectMedia.handle can no longer find those -in-flight transfers. p2p-client.js similarly replaces its public singleton but -retains old sockets, timers and its visibility listener; P2PTransfer exposes -start/download without disposal. Matching contract numbers do not establish -safe runtime state migration. Piano/MIDI/floating-window UI also retains closures. +1. Already executing groups stay pinned until the session ends or the next + user-initiated, playback-guarded reload. P2P/direct and every stateful instance + are never re-evaluated live. Phase 4 must provide disposal and state handoff + before live replacement is allowed. +2. A group that has not executed can immediately use newer verified cached URLs + only when its contract and dependency contracts equal those expected by the + running core's embedded manifest. For a different contract, keep the running + build's N-1 URLs, set `Lazy.reloadRequired`, and request the existing Refresh UI + banner through the unchanged meta-build versus `/api/version` comparison. +3. New core boot may receive a verified N-1 response for an uncached new URL only + when group contracts match. The response retains its actual hash; it is never + stored under the new hash. Contract changes join the blocking download set. -Recommended owner decision: background-download and verify the new URLs -immediately, but pin an already-executing stale module until its feature session -closes and can be safely recreated. Keep P2P/direct instances until the next -explicit user-initiated, playback-guarded page reload. Groups never executed use -the newest cached version immediately. In Phase 4, introduce explicit teardown -and state handoff seams before enabling live replacement of these instances. -This narrows "switch when the new one arrives" for stateful modules; it requires -owner approval rather than silently claiming that caching new bytes replaces -running code. +Reason: direct-media.js owns private room, pending transfer and waiting maps; +WebRTC callbacks retain these closures. Re-evaluating the singleton redirects +messages away from those transfers. P2P sockets/timers and piano/MIDI/floating +windows have similar state. Contract equality alone does not migrate it. -Completed safe prerequisites: plan commit 895f20a; pure contract fallback and -background-group synchronization commit f804a23; ordered build-local loader with -unit tests (not yet wired into index.html). No layout or feature was removed -from the current eager path. Full browser/layout/performance acceptance remains -outstanding. This is a QUESTION checkpoint, not a completed phase report. - -## Accepted owner decision - -The owner accepted pinning on 2026-10-08. Already executing stale groups remain -pinned until their session ends or the next explicit playback-guarded reload. -P2P/direct and other stateful instances are never re-evaluated live; Phase 4 must -add disposal/state handoff before permitting replacement. An unexecuted group -may use newly cached URLs only when its contract equals the running core's -embedded contract. A different contract keeps the running build's N-1 URLs, -marks reload required and prompts the existing build-tag-based Refresh UI banner. -Unit tests cover all three cases. Continue Phase 3 under these rules. +Implemented in 4853c2c and 5d6a154. Node loader tests cover pinned execution, +compatible unexecuted selection, incompatible N-1 plus reload-required, and +incompatible dependencies. Worker tests cover same-contract fallback without +cache poisoning and changed-contract readiness before commit. `perf/lazy.mjs` +checks these decisions with real workers on Chromium and WebKit. From cd4a25ae23f0dd8034b012e4606dec8bf5337de5 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:26:10 +0800 Subject: [PATCH 30/81] Document Phase 3 delivery and remaining paint regression --- plans/phase3-report.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 plans/phase3-report.md diff --git a/plans/phase3-report.md b/plans/phase3-report.md new file mode 100644 index 0000000..df53441 --- /dev/null +++ b/plans/phase3-report.md @@ -0,0 +1,42 @@ +# Phase 3 report + +Shipped on `codex/phase3`: plan `895f20a`; contract synchronization `f804a23`; +pinned loader `4853c2c`; server embedding `d98d444`; integration `5d6a154`; +review fixes `ccfb7d9` through `fab444b`; browser verification/results `b840505`. + +The CSP-safe external head loader reads saved appearance before body creation. +Modern clients block core plus their active layout/dependencies; Settings loads before switching +and saves immediately. Imported settings also report their layout. Shared markup +visibility remains eager. Rare features, stats/export and layout scripts load on +intent; playlist/settings/service mode/lyrics editor remain in RAM. Idle warming +honours Save-Data and shares one six-download pool across tabs. Legacy migration +blocks all layouts because old pages cannot report selection. P2P/direct preserve +eight-second startup; EQ metadata/DeviceDB stay eager. + +Accepted decision: executing groups stay pinned until a playback-guarded user +reload. Unexecuted groups use newer cached URLs only with matching core/dependency +contracts; otherwise retain N-1, mark reload-required and request the existing +Refresh UI banner. Changed contracts block activation. Phase 4 must supply +state disposal/handoff before live replacement; app.js splitting remains there. + +Verification: 190 frontend/183 server tests, no skips. Chromium/WebKit pass warmed +feature first-use with zero network, offline layouts, pre-body selection, +Settings search/extensions, Car controls, imported appearance, stale fallback, +contract/pinning guards and playback protection. Actual b77938a migration passes +both proxy profiles: one user-initiated reload/banner, N-1 tab and offline boot. +Both rollback flags pass offline checks. + +Reduced one-run LTE, Chromium/WebKit (`phase3-final-2026-10-08.json`): initial compressed JS/CSS +221,307/274,813 bytes versus reconstructed Phase 0 276,414/338,940 (−19.9%/−18.9%). +Historical Phase 0 boot 10,480/3,290 ms becomes 7,193/3,293; warm 419/81; +offline 166/84. FCP 1,356/2,467 versus 1,572/1,100: WebKit first paint regresses, +so the paint target remains unmet despite bootstrap/preload reordering. Core JS +updates transfer 159,905/194,026 bytes; inactive CSS readiness 29,724/28,082, +with that CSS downloaded after activation. Warm counters include idle downloads. +WebKit still duplicates cold app transfer; repeated medians await Phase 5. + +Workers/importScripts/WASM, piano engine and F7 now use hashed URLs; fonts/icons/ +webmanifest remain plain and cached (exact matrix in perf/README.md). External +piano model downloads remain on request. Owner iPhone checks: installed/offline +layouts, feature first-use, update guard/override, locked playback 30 minutes, +OPFS/quota coexistence. No deployment. From cdd26b6ae5f2265e7f0f18509ed6e76205727b02 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:35:55 +0800 Subject: [PATCH 31/81] Plan phase 4: Extract eager renderers and five lazy clients --- perf/analyze-app.cjs | 11 ++ plans/phase4-plan.md | 13 ++ plans/phase4-seams.md | 416 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 440 insertions(+) create mode 100644 perf/analyze-app.cjs create mode 100644 plans/phase4-plan.md create mode 100644 plans/phase4-seams.md diff --git a/perf/analyze-app.cjs b/perf/analyze-app.cjs new file mode 100644 index 0000000..6df26e4 --- /dev/null +++ b/perf/analyze-app.cjs @@ -0,0 +1,11 @@ +const fs=require('fs'), acorn=require('./.tmp/analysis/node_modules/acorn'), scope=require('./.tmp/analysis/node_modules/eslint-scope'); +const src=fs.readFileSync('frontend/app.js','utf8'); +function parse(s){return acorn.parse(s,{ecmaVersion:2024,sourceType:'script',locations:true,ranges:true});} +const ast=parse(src), mgr=scope.analyze(ast,{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true}); +const vars=mgr.globalScope.variables, names=new Set(vars.map(v=>v.name)); +const rows=vars.map(v=>{const decl=v.defs[0].parent||v.defs[0].node;const stmt=ast.body.find(n=>n.start<=decl.start&&n.end>=decl.end);return {name:v.name,start:stmt.start,end:stmt.end,line:stmt.loc.start.line,bytes:Buffer.byteLength(src.slice(stmt.start,stmt.end)),outside:v.references.filter(r=>r.identifier.start=stmt.end).map(r=>r.identifier.loc.start.line),imports:[]};}); +for(const row of rows){const deps=new Set();for(const v of vars)if(v.name!==row.name&&v.references.some(r=>r.identifier.start>=row.start&&r.identifier.startf.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(fs.readFileSync('frontend/'+file,'utf8')),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}} +fs.writeFileSync('perf/.tmp/analysis/declarations.json',JSON.stringify(rows,null,2)); +const candidates={shell:['Recommendations','renderSidebar','renderHomePlaylists','updateHomeGridScrollState','updateBottomChrome','setHomeOverPlayer','showMiniBar','updateMiniBar','hideMiniBar','setTile','updateNowPlayingActions','renderSmartSidebar'],presenter:['Presenter'],remote:['Remote'],party:['Party'],share:['Share','External'],stats:['renderStats'],notes:['Notes'],settings:['renderSettings'],service:['ServiceVisual','enterServiceMode','exitServiceMode'],editor:['openVideoEditor'],export:['exportToDevice'],sectionRail:['SectionRail'],gestures:['Gestures']}; +const summary=Object.entries(candidates).map(([name,list])=>{const chosen=rows.filter(r=>list.includes(r.name));const coupling=new Set(chosen.flatMap(r=>r.imports).filter(n=>!list.includes(n)));return {name,bytes:chosen.reduce((s,r)=>s+r.bytes,0),coupling:coupling.size,ratio:Math.round(chosen.reduce((s,r)=>s+r.bytes,0)/Math.max(1,coupling.size)),imports:[...coupling],outside:chosen.flatMap(r=>r.outside),list};}).sort((a,b)=>b.ratio-a.ratio);fs.writeFileSync('perf/.tmp/analysis/candidates.json',JSON.stringify(summary,null,2));console.log(summary.map(r=>[r.name,r.bytes,r.coupling,r.ratio].join(' ')).join('\n')); diff --git a/plans/phase4-plan.md b/plans/phase4-plan.md new file mode 100644 index 0000000..85d4585 --- /dev/null +++ b/plans/phase4-plan.md @@ -0,0 +1,13 @@ +# Phase 4 plan + +Start: cd4a25a, codex/phase3; branch codex/phase4. Master §§3.4, 2c.5, 6/6b and accepted answer03 apply. + +First perform scope-resolved declaration/reference analysis and record rankings in phase4-seams.md. Commit this plan before source changes. + +Implement at most six seams, one green commit each: eager shell/shared renderer files first, then Presenter, Remote, Watch party, Share/External, Stats view. Exact declarations/bytes and synchronous hooks are in phase4-seams.md. Add groups (contract 1), preserve old SHELL compatibility, mirror inert native JSON, extend Lazy.proxy to window.YT registration. Keep player, queue, persistence, boot and required eager features in RAM. Maintain native/Web fallbacks and URL-driven/resumed sessions. + +Tests first: protected playback source fingerprints, eager load-order/manifest consistency, registry proxies and browser cache smoke coverage. After every seam run frontend tests, server bun install/test, hidden-timers, and both-engine cached feature smoke. Use isolated Bun/proxy scratch data, not production. Then run existing lazy/offline/staged guard checks and reduced LTE baseline; add a split-feature update scenario that waits for its background download and proves no unrelated assets transfer. Save actual results and compare with Phase 3/after-phase0. + +Targets: app.js ≥30% raw-byte reduction from 587,029; lower Chromium long-task total; a chunk edit downloads only that chunk plus derived index/manifest/worker checks. WebKit has no long-task observer; report that limit and existing paint regression honestly. + +Risks: classic-script TDZ; synchronous playback hooks must forward without promises; duplicate UI boot/event listeners; stale singleton replacement forbidden. No live replacement without disposal/state handoff. Rollback each seam by reverting its commit; ASSET_SYNC=0 and ASSET_HASHING=0 still supported. Finish self-review against master 6/6b, ≤350-word phase4-report, commit, then overwrite DONE04 signal. Real iPhone audio/quota checks remain manual. No deployment. diff --git a/plans/phase4-seams.md b/plans/phase4-seams.md new file mode 100644 index 0000000..a256383 --- /dev/null +++ b/plans/phase4-seams.md @@ -0,0 +1,416 @@ +# Phase 4 dependency analysis and seams + +Source: `cd4a25a`, 587,029 bytes. Acorn 8 parses classic scripts with source ranges; eslint-scope 8 resolves lexical references, including shadowing. Outside references are references outside the declaration’s owning top-level statement, plus unresolved references from other frontend classic scripts. Property names and strings are not lexical references. Browser globals and other scripts’ globals remain available. Positions below refer to this source, before extraction. + +Reproduce: `npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`, then run `node perf/analyze-app.cjs`. Analysis tools are development-only; no frontend/server import is added. + +## Measured candidate ranking + +Coupling = distinct other app top-level bindings referenced inside the candidate; ratio = source UTF-8 bytes divided by coupling. This is a ranking, not a safety judgment. + +| Candidate | Bytes | Coupling | Bytes/coupling | Decision | +|---|---:|---:|---:|---| +| notes | 56491 | 18 | 3138 | Keep eager; protected owner requirement | +| sectionRail | 10973 | 5 | 2195 | Include in eager shell renderer cut | +| presenter | 9492 | 6 | 1582 | Extract | +| party | 22833 | 18 | 1269 | Extract | +| remote | 30421 | 31 | 981 | Extract | +| share | 13334 | 14 | 952 | Extract | +| editor | 6603 | 8 | 825 | Leave for later; six seam limit | +| stats | 7074 | 9 | 786 | Extract | +| gestures | 5217 | 8 | 652 | Keep playback wiring untouched | +| settings | 31516 | 49 | 643 | Keep eager; protected owner requirement | +| shell | 14608 | 29 | 504 | Extract | +| export | 5159 | 11 | 469 | Leave for later; six seam limit | +| service | 5006 | 15 | 334 | Keep eager; protected owner requirement | + +## Six cuts and ordering + +1. Eager shell/renderers: `shell-core.js` contains homepage/recommendations, sidebar, bottom/mini chrome and now-playing action paint. `views-core.js` contains existing shared list/card/Settings renderers; `section-rail.js` remains eager. These all load before app.js; callbacks read the shared lexical state only after app initializes it. No new asynchronous renderer interface. Move 98,378 source bytes; keep four required features in RAM. +2. Presenter: 9,492 bytes, lazy `feature:presenter`, boot only on presenter/overlay URLs. +3. Remote: 30,421 bytes, lazy `feature:remote-client`; preserve synchronous changed hook, bind entry buttons eagerly, auto-load only for a configured host or pair URL. +4. Watch party: 22,833 bytes, lazy `feature:watch-party`; synchronous no-session defaults for guestActive/intercept/nextDJ, same instance once loaded; resume stored host or party URL. +5. Share/External: 13,334 bytes, lazy `feature:share-external`; open/bootFromUrl are the seam. +6. Stats view: 7,074 bytes, separate `feature:stats-view` depending on pure stats group, so playback tracking does not parse the view. + +Total original source moved: 181,532 bytes (30.92%); facade overhead must keep final reduction ≥30%. Shared lexical scope is intentional; the broader eager view cut retains its existing renderer calls and high outbound coupling rather than inventing a context object or delaying Settings. Player, Transition, sleep/drift/resume, queue, persistence and boot stay in app.js unchanged apart from explicit lazy boot calls. The required now-playing metadata mutation inside Player remains untouched; its markup, mini bar and paint helpers load eagerly. + +Executing stateful chunks remain pinned until playback-guarded reload. No live replacement: no disposal/state handoff is implemented, so Phase 4 does not enable it. New unexecuted chunks obey Phase 3 contracts/N-1 guard. + +## Every top-level declaration + +Outside references use app line numbers or `file:line`; imports name other app bindings (not browser globals). Multiple declarations sharing a statement share its byte count; never sum this table blindly. + +| Declaration | Line | Statement bytes | Other app bindings read/written | Outside references | +|---|---:|---:|---|---| +| sanitizeId | 30 | 124 | — | 602, 603, 607, 607, 610, 611, 616, 617, 1995 | +| TAURI | 34 | 87 | — | 37, 54, 54, 649, 649, 649, 2296 | +| ZERO | 35 | 90 | — | 37, 55, 55 | +| WEB | 37 | 28 | TAURI, ZERO | 572, 575, 579, 582, 585, 590, 593, 597, 601, 606, 609, 612, 615, 618, 628, 698, 867, 873, 954, 981, 1183, 1281, 1296, 1339, 1712, 1743, 1769, 1792, 1811, 1905, 2067, 2287, 2299, 2329, 3029, 3145, 3146, 3198, 3199, 3362, 3475, 4764, 5509, 5698, 5808, 5818, 5826, 5829, 5881, 5890, 5907, 5909, 6100, 6686, 7501, 8919, 9191, 9206, 9240, 9897, 10126, 11983, 12367, 12627, 12678, 12683, 12691, 12698, 12700, 12709, 12711, 12717 | +| APP_VERSION | 38 | 28 | — | 94, 9857, 9880, 10132, 12723 | +| perfMark | 42 | 87 | — | 2265, 11167, 12564 | +| perfMeasure | 43 | 116 | — | 3031, 11217, 12614 | +| call | 53 | 258 | TAURI, ZERO | 574, 584, 587, 592, 595, 599, 603, 611, 614, 617, 620 | +| webFetch | 62 | 274 | — | 573, 580, 583, 586, 591, 5812, 5896, 12630 | +| loadDataFromStorage | 73 | 160 | — | 594 | +| saveDataToStorage | 80 | 851 | APP_VERSION, profileHeaders | 598, 9897 | +| NO_HEVC_KEY | 105 | 32 | — | 107, 1907, 2499 | +| hevcCapable | 106 | 267 | NO_HEVC_KEY | 451, 591, 9192 | +| RecentSearches | 122 | 2371 | SearchLibrary | 11168, 11171, 11212, 11251, 11253, 11266, 11281, 11294 | +| SearchLibrary | 181 | 4754 | collectSearchMetadata | 162, 165, 169, 5820, 9283, 9290, 9875, 9928, 9930, 9941, 9947, 9951, 11181, 11233, 11234, 11252, 11262, 11262, 11266 | +| SaveSlots | 291 | 800 | data | 1849, 1877, 9874, 9874, 9902 | +| saveControllers | 315 | 34 | — | 333, 381, 1845, 1875 | +| SaveQueue | 316 | 3701 | saveControllers, view, cachedIds, downloading, preload, renderList | 1844, 1846, 1851, 1852, 1857, 1859, 1872, 1876, 1878, 9541, 9541, 9542, 9542, 12688, 12688, 12688, 12689, 12689, 12689, 12698 | +| resumableOpfsSave | 401 | 2172 | — | 464 | +| opfsDownload | 440 | 2721 | hevcCapable, resumableOpfsSave | 602 | +| opfsDownloadEdited | 501 | 1261 | — | 607 | +| opfsStatus | 533 | 277 | — | 610 | +| opfsList | 543 | 344 | — | 613 | +| opfsDelete | 554 | 325 | — | 616 | +| opfsClear | 561 | 295 | — | 619 | +| _currentBlobUrl | 569 | 27 | — | 2281, 2282, 2283, 2284, 2301, 2336 | +| API | 571 | 2945 | sanitizeId, WEB, call, webFetch, loadDataFromStorage, saveDataToStorage, hevcCapable, opfsDownload, opfsDownloadEdited, opfsStatus, opfsList, opfsDelete, opfsClear | 776, 889, 910, 1696, 1852, 1910, 2010, 2050, 2297, 2347, 3117, 5279, 5515, 7861, 8669, 9383, 9427, 9487, 10036, 10056, 10073, 10572, 11194, 11203, 11459, 11917, 12572, 12630 | +| warmedAt | 625 | 27 | — | 632, 633 | +| knownServerCachedIds | 626 | 39 | — | 642, 2351 | +| warmStreams | 627 | 435 | WEB, warmedAt, cachedIds | 640, 10249, 11215 | +| warmNextQueue | 638 | 235 | knownServerCachedIds, warmStreams, data, queue, queueIndex, cachedIds | 3034, 8079 | +| toAssetUrl | 648 | 138 | TAURI | 2298 | +| DEFAULT_SETTINGS | 654 | 1577 | — | 675, 908, 12588 | +| data | 675 | 275 | DEFAULT_SETTINGS | 294, 640, 776, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 867, 867, 873, 873, 877, 878, 886, 889, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 947, 954, 954, 956, 956, 962, 967, 968, 969, 981, 981, 982, 1012, 1022, 1022, 1026, 1029, 1030, 1052, 1101, 1101, 1255, 1262, 1262, 1263, 1282, 1282, 1349, 1349, 1350, 1352, 1352, 1353, 1353, 1354, 1354, 1423, 1440, 1449, 1450, 1456, 1456, 1457, 1458, 1465, 1503, 1503, 1549, 1550, 1551, 1556, 1662, 1671, 1731, 1798, 1886, 1915, 1947, 1953, 1955, 2019, 2020, 2020, 2021, 2038, 2052, 2052, 2053, 2054, 2054, 2328, 2328, 2437, 2437, 2438, 2539, 2541, 2697, 2868, 2954, 2980, 3061, 3072, 3144, 3144, 3198, 3199, 3476, 3476, 3484, 3485, 3485, 3488, 3488, 3631, 3743, 4178, 4178, 4184, 4185, 4245, 4246, 4247, 4261, 4374, 4375, 4442, 4450, 4466, 4594, 4594, 4596, 4597, 4630, 4748, 4852, 4857, 4863, 4863, 4913, 5461, 5464, 5468, 5475, 5573, 5579, 5595, 5628, 5635, 5637, 5691, 5835, 5835, 5895, 5927, 5927, 5974, 6004, 6084, 6363, 6366, 6371, 6575, 6602, 6697, 6698, 6865, 6869, 6869, 6869, 6917, 6917, 6923, 6924, 6933, 6933, 6938, 6956, 6956, 7091, 7122, 7123, 7187, 7523, 7523, 7602, 7972, 8055, 8055, 8056, 8056, 8057, 8057, 8058, 8063, 8063, 8078, 8102, 8102, 8103, 8115, 8120, 8129, 8130, 8137, 8137, 8141, 8150, 8157, 8158, 8174, 8220, 8241, 8252, 8252, 8255, 8258, 8258, 8261, 8280, 8288, 8289, 8290, 8296, 8297, 8298, 8442, 8442, 8481, 8483, 8497, 8498, 8499, 8507, 8517, 8531, 8699, 8733, 8740, 8804, 8805, 8809, 8932, 8970, 9022, 9206, 9240, 9433, 9435, 9436, 9437, 9437, 9492, 9492, 9493, 9494, 9494, 9551, 9555, 9557, 9561, 9584, 9596, 9600, 9604, 9608, 9615, 9622, 9634, 9638, 9654, 9658, 9662, 9669, 9676, 9687, 9694, 9716, 9723, 9785, 9789, 9827, 9827, 9827, 9841, 9841, 9842, 9842, 9871, 9871, 9872, 9873, 9874, 9876, 9877, 9879, 9884, 9887, 9888, 9891, 9891, 9894, 9896, 9897, 9897, 9901, 9902, 9903, 9904, 9905, 9906, 9907, 9909, 9915, 9958, 9963, 9970, 9975, 9979, 9984, 9986, 9989, 9994, 10089, 10091, 10102, 10103, 10117, 10272, 10272, 10277, 10307, 10308, 10314, 10378, 10397, 10400, 10493, 10500, 10500, 10501, 10598, 10642, 10678, 10849, 10849, 10850, 10852, 10852, 10856, 10863, 10880, 10880, 10881, 10881, 10965, 11413, 11413, 11415, 11430, 11524, 11537, 11543, 11543, 11543, 11544, 11545, 11554, 11571, 11668, 11680, 11718, 11762, 11784, 11787, 11826, 11844, 11853, 11864, 11876, 11886, 11886, 11983, 11994, 11995, 11998, 12000, 12003, 12009, 12055, 12071, 12079, 12084, 12085, 12086, 12099, 12100, 12101, 12102, 12103, 12104, 12105, 12105, 12106, 12107, 12108, 12109, 12109, 12431, 12434, 12517, 12574, 12630, 12630, 12630, 12631, 12631, 12631, 12632, 12632, 12648, 12650, 12650, 12650, 12652, 12653, 12654, 12655, 12663, 12663, 12664, 12670, 12671, 12672, 12679, 12679, 12679, 12679, 12684, 12690, 12690, 12720, 12720, 12724, 12725, 12725, 12726, 12727 | +| view | 676 | 30 | — | 378, 1730, 1731, 1734, 1734, 1734, 1837, 1884, 1884, 1884, 1885, 1886, 1914, 1915, 2006, 2025, 2025, 2036, 2036, 2036, 2037, 2038, 2059, 2059, 2059, 5967, 6339, 8065, 8133, 8147, 8153, 8167, 8174, 8177, 8177, 8177, 8665, 8670, 8679, 8710, 8710, 8713, 8717, 8721, 8777, 8802, 8803, 8804, 8805, 8806, 8807, 8807, 8808, 8809, 8884, 8887, 8888, 8889, 8890, 8891, 8892, 8893, 8894, 8895, 8896, 8900, 8905, 8919, 8923, 8925, 8927, 8935, 8946, 8947, 8952, 8958, 8969, 8970, 9037, 9046, 9057, 9068, 9075, 9082, 9112, 9245, 9316, 9384, 9530, 9533, 10057, 10129, 10225, 10253, 10253, 10253, 10253, 10261, 10261, 10261, 10261, 10264, 10265, 10265, 10270, 10271, 10271, 10277, 10284, 10284, 10306, 10308, 10312, 10342, 10350, 10350, 10350, 10352, 10366, 10366, 10366, 10541, 10642, 10682, 10833, 10833, 10841, 10841, 10884, 11170, 11232, 11288, 11312, 11319, 11412, 11412, 11414, 11415, 11417, 11654, 11654, 11977, 11977, 11980, 11985, 11987, 12059, 12496, 12541, 12630, f7-layout.js:34 | +| searchResults | 677 | 23 | — | 8803, 8888, 11174, 11197, 11208, 11232, 11234 | +| searchAttempted | 680 | 28 | — | 8888, 9062, 11175, 11198, 11209 | +| searchSeq | 684 | 18 | — | 11166, 11172, 11195, 11205, 11220 | +| channelData | 685 | 78 | — | 8666, 8670, 8672, 8673, 8674, 8675, 8678, 8806, 8959, 8963, 8966, 9046 | +| queue | 686 | 15 | — | 640, 4879, 4895, 4922, 4927, 4933, 4934, 4943, 4944, 4944, 5467, 5468, 5525, 7451, 7478, 8072, 8080, 8091, 8092, 8093, 8098, 8098, 8107, 8109, 8141, 8142, 8185, 8209, 8218, 8220, 8228, 8314, 8377, 8377, 8403, 8403, 8404, 8802, 10314, 10315, 11956, f7-layout.js:34 | +| queueIndex | 687 | 20 | — | 639, 640, 4882, 4885, 4895, 4922, 4944, 5467, 5467, 5467, 7451, 7478, 8073, 8080, 8091, 8093, 8098, 8110, 8142, 8185, 8210, 8218, 8218, 8219, 8221, 8228, 8312, 8313, 8314, 8377, 8377, 8403, 8403, 8404, 10315, 10315, 11956, f7-layout.js:34 | +| queueSource | 688 | 21 | — | 5474, 5474, 8074, 8139, 8173, 8173, 8625, 10253, 10312, 10756, 10756, 11862, 11862, 11863, f7-layout.js:34 | +| playFullMode | 689 | 25 | — | 2434, 3060, 3069, 5468, 5475, 7971, 8075, 8220, 8241, 8243, 8243, 11956 | +| current | 692 | 19 | — | 1842, 1842, 1842, 1882, 1882, 1882, 2057, 2057, 2057, 2073, 2073, 2073, 2307, 2338, 2350, 2351, 2351, 2351, 2353, 2353, 2379, 2380, 2381, 2382, 2390, 2394, 2396, 2407, 2408, 2409, 2409, 2433, 2467, 2479, 2479, 2482, 2483, 2484, 2494, 2494, 2495, 2498, 2501, 2522, 2541, 2541, 2549, 2549, 2556, 2557, 2569, 2575, 2575, 2578, 2584, 2606, 2609, 2619, 2626, 2842, 2842, 2842, 2842, 2868, 2874, 2952, 2965, 3029, 3029, 3055, 3055, 3061, 3069, 3069, 3072, 3121, 3121, 3121, 3123, 3124, 3124, 3124, 3160, 3160, 3160, 3295, 3295, 3296, 3352, 3352, 3353, 3357, 3693, 3693, 3693, 3905, 3905, 3905, 3905, 3914, 3914, 3914, 4181, 4181, 4181, 4181, 4211, 4211, 4211, 4294, 4294, 4294, 4405, 4405, 4405, 4731, 4731, 4849, 4849, 4943, 5473, 5473, 5528, 5532, 5532, 5532, 5609, 5609, 5612, 5691, 5691, 5691, 5739, 5739, 5782, 5791, 5932, 5932, 6309, 6309, 6309, 6444, 6444, 6819, 6867, 6867, 7057, 7073, 7438, 7438, 7599, 7599, 7641, 7641, 7641, 7957, 8011, 8011, 8028, 8028, 8029, 8031, 8032, 8038, 8038, 8106, 8106, 8106, 8140, 8140, 8140, 8165, 8396, 8396, 8549, 8549, 8624, 8624, 8624, 9442, 9497, 9911, 9911, 9911, 9918, 9918, 9918, 10040, 10075, 10075, 10075, 10313, 10313, 10313, 10328, 10328, 10575, 10575, 10575, 10755, 10755, 10755, 10757, 10758, 11002, 11002, 11449, 11449, 11450, 11471, 11478, 11478, 11478, 11480, 11480, 11480, 11483, 11483, 11483, 11486, 11486, 11486, 11487, 11498, 11498, 11498, 11503, 11503, 11503, 11504, 11504, 11508, 11508, 11508, 11509, 11509, 11526, 11556, 11574, 11595, 11595, 11595, 11596, 11597, 11598, 11599, 11601, 11602, 11810, 11817, 11825, 11825, 11826, 11835, 11835, 11844, 11849, 11849, 11853, 11861, 11861, 11866, 11874, 11874, 11876, 11879, 11879, 11880, 11919, 11924, 11924, 12631, 12648, 12654, 12654, 12665 | +| IS_IOS | 693 | 131 | — | 2521, 2539 | +| _currentEqUrl | 695 | 25 | — | 697, 697, 697, 699, 699, 700 | +| useEqRender | 696 | 286 | WEB, _currentEqUrl, EqRender | 2305, 2337 | +| dragSource | 702 | 20 | — | 10288, 10303 | +| listFilter | 703 | 20 | — | 8909, 8910, 9464, 9529, 10354, 11381, 11390, 11390 | +| selectMode | 704 | 23 | — | 8902, 8903, 8915, 9038, 9039, 9040, 10252, 11611, 12024, 12032, 12032, 12035, 12036 | +| selectedIds | 705 | 28 | — | 8903, 10196, 11392, 11393, 11393, 11394, 11395, 11400, 11404, 11408, 11413, 11416, 11418, 11427, 12025, 12033, 12042, 12042, 12042, 12043, 12044 | +| sleepTimerRemaining | 706 | 28 | — | 4859, 11691, 11694, 11695, 11698, 11707, 11745, 11750, 11751, 11799 | +| sleepTimerTick | 707 | 26 | — | 11693, 11705, 11705, 11706 | +| abA | 708 | 15 | — | 2447, 2447, 2450, 4682, 5476, 6482, 6482, 7971, 7971, 7973, 7977, 11811, 11814, 11824, 11836, 11837, 11849, 11854, 11898, 11901, 11908, 12654, 12659 | +| abB | 709 | 15 | — | 5476, 6483, 6483, 6483, 7971, 7971, 7971, 11818, 11821, 11824, 11836, 11837, 11849, 11855, 11898, 11902, 11909, 12654, 12659 | +| relatedVideos | 710 | 23 | — | 11920, 11928, 11942 | +| relatedCollapsed | 711 | 29 | — | 7206, 7209, 7210, 11376, 11930 | +| saveTimer | 712 | 21 | — | 775, 776 | +| cachedIds | 713 | 28 | — | 336, 371, 631, 641, 1699, 1700, 1721, 1722, 1725, 1725, 1728, 1794, 1827, 1863, 1881, 1903, 1911, 1940, 2002, 2012, 2034, 2051, 2287, 2293, 2329, 2332, 3115, 3118, 3182, 3190, 3201, 3366, 3377, 4852, 5508, 6615, 6745, 6795, 6796, 7602, 9181, 9430, 9490, 10037, 10074, 10194, 10562, 10571, 10573, 10816, 11453, 11461, 11491, 12632, 12640 | +| downloading | 714 | 30 | — | 336, 372, 1725, 1827, 1834, 1879, 1926, 2002, 2003, 2032, 3176, 3189, 3373, 10195, 10790, 11452, 12688 | +| downloadMeta | 715 | 31 | — | 1835, 1880, 2004, 2033 | +| removing | 716 | 27 | — | 3369, 11452, 11456 | +| playlistOps | 717 | 30 | — | 10606 | +| runExclusive | 721 | 230 | — | 10606, 11456 | +| $ | 729 | 82 | — | 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 836, 838, 838, 839, 999, 1079, 1087, 1088, 1089, 1146, 1148, 1155, 1301, 1398, 1406, 1483, 1483, 1498, 1498, 1524, 1573, 1589, 1615, 1633, 1732, 1887, 1916, 1927, 1930, 2039, 3092, 3096, 3097, 3142, 3254, 3270, 3328, 3366, 3462, 3517, 3537, 3538, 3539, 3540, 3585, 3586, 3591, 3592, 3593, 3629, 3630, 3632, 3659, 3660, 3663, 3667, 3680, 3684, 3691, 3717, 3724, 3726, 3736, 3934, 3944, 3950, 3953, 3978, 4254, 4263, 4269, 4270, 4272, 4280, 4281, 4283, 4353, 4378, 4386, 4395, 4419, 4447, 4448, 4449, 4457, 4465, 4471, 4478, 4524, 4525, 4531, 4532, 4564, 4565, 4566, 4567, 4576, 4577, 4578, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4604, 4610, 4612, 4612, 4615, 4627, 4628, 4629, 4634, 4657, 4661, 4662, 4663, 4664, 4665, 4694, 4695, 4707, 4709, 4710, 4713, 4720, 4726, 4727, 4727, 4746, 4746, 4749, 4749, 4992, 4997, 5006, 5006, 5098, 5099, 5103, 5104, 5105, 5107, 5108, 5108, 5116, 5117, 5118, 5140, 5174, 5175, 5176, 5177, 5181, 5184, 5185, 5186, 5188, 5189, 5192, 5193, 5194, 5202, 5203, 5209, 5210, 5229, 5303, 5304, 5305, 5311, 5313, 5316, 5326, 5328, 5341, 5357, 5361, 5362, 5363, 5370, 5370, 5371, 5371, 5372, 5376, 5377, 5378, 5382, 5391, 5393, 5397, 5398, 5405, 5406, 5413, 5626, 5670, 5732, 5776, 5789, 5882, 6071, 6099, 6106, 6109, 6126, 6127, 6134, 6140, 6206, 6291, 6292, 6292, 6293, 6293, 6297, 6411, 6812, 6930, 7035, 7583, 7802, 7817, 7820, 7820, 7823, 7824, 7839, 7843, 7865, 7874, 7875, 7882, 7938, 7979, 8029, 8030, 8033, 8041, 8043, 8047, 8121, 8124, 8186, 8187, 8188, 8189, 8234, 8248, 8299, 8325, 8367, 8375, 8386, 8387, 8390, 8397, 8398, 8409, 8427, 8458, 8487, 8522, 8524, 8526, 8526, 8542, 8547, 8550, 8578, 8636, 8650, 8870, 8871, 8886, 8886, 8887, 8901, 8902, 8903, 8905, 8975, 9015, 9029, 9031, 9041, 9043, 9239, 9377, 9387, 9403, 9454, 9522, 9523, 9874, 9894, 9895, 9901, 9902, 9903, 9904, 9905, 9906, 9907, 9908, 9914, 9914, 9925, 9930, 9934, 9935, 9936, 9937, 9940, 9945, 9949, 9957, 9962, 9969, 9974, 9978, 9983, 9988, 9993, 9999, 10000, 10009, 10010, 10031, 10049, 10060, 10061, 10062, 10083, 10088, 10096, 10097, 10098, 10098, 10099, 10102, 10103, 10104, 10105, 10105, 10106, 10109, 10110, 10111, 10112, 10113, 10114, 10115, 10116, 10131, 10133, 10154, 10155, 10163, 10355, 10427, 10436, 10439, 10528, 10704, 10819, 10832, 10840, 10861, 10870, 10895, 10900, 10900, 10901, 10902, 10910, 10911, 10914, 10923, 10925, 10932, 10933, 10970, 10972, 10972, 10972, 11000, 11007, 11117, 11124, 11128, 11129, 11144, 11145, 11148, 11150, 11189, 11231, 11239, 11240, 11357, 11358, 11358, 11359, 11360, 11361, 11362, 11363, 11364, 11367, 11368, 11369, 11370, 11373, 11380, 11386, 11388, 11394, 11396, 11398, 11407, 11425, 11474, 11474, 11475, 11475, 11476, 11476, 11477, 11477, 11478, 11478, 11507, 11518, 11518, 11521, 11521, 11610, 11610, 11616, 11619, 11620, 11621, 11622, 11623, 11624, 11625, 11628, 11629, 11630, 11631, 11645, 11650, 11738, 11739, 11746, 11748, 11752, 11754, 11893, 11899, 11899, 11899, 11900, 11907, 11907, 11927, 11927, 11972, 12026, 12028, 12029, 12034, 12036, 12037, 12038, 12043, 12231, 12629, 12645, 12648, 12648, 12648, 12648, 12714, 12714, 12715, 12715 | +| els | 730 | 1141 | $ | 1549, 1550, 1551, 1607, 1609, 2245, 2261, 2279, 2363, 2369, 2372, 2387, 2388, 2389, 2390, 2391, 2395, 2397, 2398, 2398, 2398, 2399, 2399, 2522, 2525, 2526, 2527, 2528, 2532, 2532, 2558, 2577, 2578, 2586, 2608, 2609, 2618, 2627, 2701, 2704, 2764, 2772, 2782, 2831, 2836, 2844, 2844, 2878, 2878, 2948, 2966, 2970, 2978, 2980, 2985, 2985, 3091, 3209, 3210, 3221, 3229, 3358, 3358, 3359, 3359, 3361, 3362, 3363, 3364, 3367, 4914, 5537, 5884, 5911, 5969, 5971, 5972, 5973, 6326, 6328, 6329, 6330, 6336, 6341, 6353, 6354, 6361, 6362, 6373, 6374, 6808, 6919, 6920, 6996, 6997, 7014, 7015, 7037, 7123, 7648, 7917, 7917, 7958, 7959, 7960, 8009, 8018, 8018, 8167, 8171, 8172, 8296, 8296, 8297, 8297, 8298, 8298, 8459, 8680, 8681, 8682, 8698, 8714, 8746, 8746, 8747, 8747, 8819, 8820, 8831, 8874, 8875, 8876, 8877, 8878, 8879, 8884, 8888, 8914, 8915, 8917, 8919, 8924, 8926, 8928, 8933, 8936, 8944, 8948, 8956, 8959, 8967, 8971, 9007, 9008, 9009, 9010, 9011, 9012, 9030, 9052, 9053, 9061, 9062, 9099, 9102, 9104, 9277, 9279, 9280, 9281, 9300, 9301, 9301, 9308, 9310, 9311, 9312, 9337, 9373, 9375, 9376, 9378, 9516, 9518, 9519, 9520, 9571, 9573, 9574, 9575, 9959, 9964, 9971, 10352, 11090, 11149, 11223, 11224, 11225, 11243, 11244, 11246, 11252, 11254, 11267, 11269, 11270, 11271, 11272, 11274, 11277, 11302, 11307, 11325, 11351, 11352, 11448, 11479, 11482, 11482, 11485, 11485, 11497, 11501, 11501, 11502, 11514, 11515, 11516, 11517, 11519, 11520, 11521, 11523, 11523, 11529, 11531, 11533, 11536, 11537, 11542, 11545, 11551, 11553, 11554, 11570, 11571, 11590, 11591, 11640, 11653, 12521, 12522, 12556, 12557, 12665, 12665, 12670, 12671, 12672, 12706 | +| persist | 774 | 147 | API, data, saveTimer, scheduleProfilePush | 1264, 1424, 1451, 2022, 2055, 3062, 3073, 4186, 4443, 4451, 4467, 4598, 4631, 4917, 5638, 5929, 6939, 7140, 7218, 8064, 8112, 8131, 8145, 8151, 8253, 8259, 8291, 8500, 8532, 8932, 9438, 9495, 9888, 9891, 9894, 9897, 9901, 9902, 9903, 9904, 9905, 9906, 9907, 9910, 9916, 9960, 9967, 9972, 9976, 9980, 9985, 9990, 9995, 10092, 10102, 10103, 10119, 10273, 10278, 10318, 10404, 10502, 10621, 10643, 10680, 10711, 10763, 10853, 10857, 10882, 11420, 11435, 11524, 11540, 11548, 11555, 11572, 11784, 11787, 11829, 11845, 11888, 12057, 12080, 12110, 12483, 12630, 12631, 12632, 12650, 12652, 12653, 12654, 12655 | +| profilePayload | 786 | 528 | data | 878, 1415 | +| ProfileSecret | 806 | 671 | — | 817, 846, 859, 1030, 1444, 1448, 1448, 1458, 1504, 1507, 1536, 10118, 12679 | +| profileHeaders | 816 | 143 | ProfileSecret | 87, 877, 956, 1314, 1328, 5896, 12720 | +| askProfileSecret | 822 | 1307 | $, importProfileCredentials, escapeHtml, showModal, closeModal | 855 | +| fetchProfile | 845 | 740 | ProfileSecret, askProfileSecret | 1373, 1534, 1577 | +| profilePushTimer | 865 | 28 | — | 868, 869 | +| scheduleProfilePush | 866 | 179 | WEB, data, profilePushTimer, pushProfile | 777, 972 | +| pushProfile | 872 | 947 | WEB, API, data, profilePayload, profileHeaders, toast | 869 | +| applyProfileData | 895 | 1432 | API, DEFAULT_SETTINGS, data | 970, 1545 | +| _syncBusy | 917 | 18 | — | 919, 919, 921 | +| setSyncing | 918 | 192 | _syncBusy | 926, 934 | +| syncOnLaunch | 925 | 637 | setSyncing, playlistFingerprint, pullProfileIfNewer, updateProfileStatus, checkPlaylistInbox, render, renderSmartSidebar | 12618 | +| playlistFingerprint | 945 | 189 | data | 927, 937 | +| pullProfileIfNewer | 953 | 1123 | WEB, data, profileHeaders, scheduleProfilePush, applyProfileData, toast | 929 | +| profileShareUrl | 980 | 175 | WEB, data | 986, 1006, 1023, 9829, 9834, 9839, 9840 | +| copyProfileLink | 985 | 759 | $, profileShareUrl, escapeHtml, toast, showModal, closeModal | 1008, 10111, 11144 | +| shareProfileLink | 1005 | 427 | data, profileShareUrl, copyProfileLink | 10112, 11145 | +| updateProfileStatus | 1021 | 1681 | data, ProfileSecret, profileShareUrl | 941, 1425, 1452, 1555, 10120, 10123, 12666 | +| showSharedPlaylistModal | 1057 | 3747 | data, $, escapeHtml, toast, showModal, closeModal | 1174 | +| sharePlaylist | 1160 | 696 | showSharedPlaylistModal, toast | 9014 | +| adoptSharedPlaylistFromUrl | 1182 | 555 | WEB, adoptSharedPlaylistByCode | 12605 | +| adoptSharedPlaylistByCode | 1205 | 2628 | data, persist, escapeHtml, toast, uid, renderSidebar, render, slim, showModal, closeModal | 1198, 1324 | +| inboxCheckRunning | 1278 | 30 | — | 1281, 1284, 1289 | +| inboxLastCheck | 1279 | 23 | — | 1285, 1299 | +| checkPlaylistInbox | 1280 | 352 | WEB, data, inboxCheckRunning, inboxLastCheck, drainPlaylistInbox | 932, 1303 | +| INBOX_POLL_MS | 1293 | 36 | — | 1307 | +| INBOX_MIN_GAP_MS | 1294 | 35 | — | 1299 | +| startPlaylistInboxWatch | 1295 | 547 | WEB, $, inboxLastCheck, checkPlaylistInbox, INBOX_POLL_MS, INBOX_MIN_GAP_MS | 12619 | +| drainPlaylistInbox | 1310 | 853 | profileHeaders, adoptSharedPlaylistByCode | 1287 | +| adoptProfileFromUrl | 1338 | 1712 | WEB, data, fetchProfile, finishProfileLoad, escapeHtml, toast, showModal, closeModal | 12606 | +| createProfileFlow | 1385 | 1098 | $, requestCreateProfile, toast, showModal, closeModal | 10109 | +| requestCreateProfile | 1410 | 756 | data, persist, profilePayload, updateProfileStatus, toast, closeModal | 1396, 1403 | +| randomProfileKey | 1433 | 193 | — | 1476 | +| setProfileSecretOnServer | 1439 | 639 | data, persist, ProfileSecret, updateProfileStatus | 1476, 1487, 1494 | +| protectProfileFlow | 1455 | 2453 | data, $, ProfileSecret, randomProfileKey, setProfileSecretOnServer, exportProfileCredentials, escapeHtml, toast, showModal, closeModal | 10113 | +| exportProfileCredentials | 1502 | 1276 | data, ProfileSecret, toast | 1479, 10114 | +| importProfileCredentials | 1523 | 1125 | $, ProfileSecret, fetchProfile, finishProfileLoad, toast | 835, 10115 | +| finishProfileLoad | 1544 | 623 | data, els, applyProfileData, updateProfileStatus, toast, applyAppearance, preloadPlaylist, preloadPinnedPlaylists, updateQueueBadge, updateLoopRepeatButtons, renderSidebar, render, renderSmartSidebar | 1379, 1537, 1583 | +| loadProfileFlow | 1561 | 1120 | $, fetchProfile, finishProfileLoad, toast, showModal, closeModal | 10110 | +| escapeHtml | 1595 | 187 | — | 828, 997, 1061, 1063, 1233, 1241, 1360, 1465, 3589, 3613, 3616, 3664, 3665, 3673, 3674, 3779, 3841, 4018, 4019, 4295, 4406, 4552, 5031, 5038, 5038, 5215, 5216, 5284, 5285, 5285, 6012, 6030, 6031, 6039, 6039, 6041, 6041, 6209, 6209, 6389, 6390, 6390, 6392, 6394, 6394, 6506, 6510, 6533, 6537, 7263, 7453, 7456, 7457, 7458, 7462, 7846, 7847, 7849, 7868, 7869, 7869, 8195, 8768, 9296, 9354, 9469, 9834, 9932, 9933, 10202, 10479, 11257, 11258, 11259, 11259, 11945 | +| ICON_PLAY | 1601 | 113 | — | 3091, 3093 | +| ICON_PAUSE | 1602 | 130 | — | 3091, 3093 | +| lastVolume | 1605 | 19 | — | 1610, 11543, 11544, 11544 | +| syncMuteIcon | 1606 | 709 | $, els, lastVolume | 4916, 7125, 9966, 11539, 11547, 12668 | +| fmtTime | 1620 | 322 | — | 2441, 4785, 5783, 7627, 7958, 7959, 8041, 8388, 8389, 10203, 11814, 11821, 11901, 11902, 11908, 11909 | +| toast | 1629 | 1015 | $ | 882, 963, 990, 1077, 1170, 1176, 1211, 1216, 1229, 1267, 1376, 1381, 1400, 1419, 1426, 1428, 1459, 1478, 1480, 1484, 1485, 1489, 1490, 1494, 1495, 1505, 1520, 1530, 1531, 1532, 1535, 1538, 1558, 1580, 1585, 1671, 1831, 1843, 1855, 1867, 1869, 1873, 2008, 2024, 2027, 2030, 2058, 2066, 2068, 2078, 2361, 2441, 2486, 2502, 2510, 2514, 2630, 3114, 3130, 3172, 3173, 3174, 3185, 3226, 3341, 3511, 3807, 3810, 3819, 3824, 3827, 3911, 3912, 3916, 3938, 4008, 4033, 4063, 4066, 4098, 4134, 4143, 4145, 4149, 4165, 4172, 4192, 4196, 4200, 4204, 4210, 4234, 4235, 4339, 4835, 4836, 4945, 4988, 5049, 5070, 5070, 5295, 5321, 5411, 5645, 5966, 6316, 6439, 6440, 6445, 6818, 6819, 6820, 6831, 6877, 6946, 6975, 7439, 7473, 7473, 7482, 7541, 7583, 7593, 7627, 7670, 7746, 7750, 7756, 7779, 7820, 7820, 7894, 7898, 7898, 7938, 8115, 8129, 8134, 8154, 8243, 8255, 8261, 8293, 8511, 8664, 8781, 8955, 8966, 8989, 8997, 9004, 9129, 9155, 9429, 9441, 9489, 9499, 9891, 9898, 9919, 9947, 9951, 10023, 10039, 10076, 10121, 10278, 10386, 10406, 10408, 10431, 10505, 10510, 10576, 10622, 10624, 10684, 10766, 10828, 10854, 10859, 11216, 11222, 11359, 11404, 11421, 11436, 11463, 11466, 11720, 11728, 11792, 11796, 11801, 11814, 11821, 11832, 11890, 12061, 12081, 12113, 12116, 12240, 12310, 12311, 12331, 12353, 12357, 12363, 12472, 12485, 12487, 12491, 12513, 12630, 12631, 12648, 12663, 12664, 12665, 12713 | +| uid | 1657 | 91 | — | 1261, 1995, 10499, 10677, 12054, 12433, 12630 | +| applyAppearance | 1661 | 783 | data, toast | 1546, 9894, 9897, 9901, 9903, 9904, 9905, 12662 | +| fmtBytes | 1677 | 204 | — | 9162, 9257, 9290, 9357, 9452, 9473, 9930, 10060, 10061, 10070 | +| isUsableCacheItem | 1689 | 110 | — | 1697, 1719 | +| refreshCachedIds | 1693 | 340 | API, cachedIds, isUsableCacheItem | 12675 | +| cacheMutations | 1709 | 23 | — | 1715, 1718, 1864, 2013, 3183 | +| cacheResyncRunning | 1710 | 31 | — | 1712, 1713, 1738 | +| resyncCachedIds | 1711 | 1269 | WEB, data, view, cachedIds, downloading, $, isUsableCacheItem, cacheMutations, cacheResyncRunning, markCardCacheState, renderSidebar, renderList, updatePlaylistOfflineButton | 1749 | +| startCacheResyncWatch | 1742 | 356 | WEB, resyncCachedIds | 12676 | +| warmSearchThumbs | 1762 | 268 | warmThumb | 11179, 11214 | +| warmThumb | 1768 | 150 | WEB | 1765, 1866, 2016 | +| YT_ID_RE | 1774 | 39 | — | 1777 | +| UPLOAD_ID_RE | 1775 | 42 | — | 1776 | +| isUploadId | 1776 | 63 | UPLOAD_ID_RE | 1777, 1781, 3366, 3602, 3644, 4527, 6453, 6619, 7420, 7422, 9470 | +| isMediaId | 1777 | 76 | YT_ID_RE, isUploadId | 3475, 4941, 5698, 6187, 6568 | +| thumbUrlFor | 1779 | 324 | isUploadId | 1795, 1866, 2016, 8553, 9469, 9534, 9534 | +| THUMB_WARM_MAX | 1790 | 27 | — | 1801 | +| warmOfflineThumbs | 1791 | 576 | WEB, data, cachedIds, thumbUrlFor, THUMB_WARM_MAX, videoById | 12702 | +| recordDeviceFile | 1810 | 528 | WEB | 1865, 3184 | +| preload | 1821 | 3504 | SaveSlots, saveControllers, SaveQueue, API, data, view, current, cachedIds, downloading, downloadMeta, $, toast, cacheMutations, warmThumb, thumbUrlFor, recordDeviceFile, updateDownloadBadge, markCardCacheState, updateNowPlayingActions, EqRender, renderSidebar, renderList, slim, updatePlaylistOfflineButton | 374, 1921, 1948, 1957, 2330, 3128, 9223, 10578, 10619, 10679, 10831, 10858, 11434, 11471, 12056, 12633, 12689 | +| resavedAfterFailure | 1900 | 38 | — | 1919, 1920 | +| dropBrokenLocalCopy | 1901 | 871 | WEB, NO_HEVC_KEY, API, data, view, cachedIds, $, preload, resavedAfterFailure, markCardCacheState, renderSidebar, updatePlaylistOfflineButton | 2485 | +| updateDownloadBadge | 1925 | 331 | downloading, $ | 1838, 1883, 2007, 2035, 3178, 3191, 8724 | +| playlistOfflineStats | 1936 | 266 | cachedIds | 8700, 8754, 10789, 10821 | +| preloadPlaylist | 1946 | 138 | data, preload | 1556, 9986, 12684 | +| preloadPinnedPlaylists | 1952 | 299 | data, preload | 1557, 12685 | +| markCardCacheState | 1963 | 669 | — | 1728, 1836, 1881, 1912, 2005, 2034, 2056, 3119, 3177, 3190, 9498, 10574, 11462 | +| customVideoId | 1994 | 91 | sanitizeId, uid | 2221 | +| downloadEdited | 2000 | 1949 | API, data, view, cachedIds, downloading, downloadMeta, $, persist, toast, cacheMutations, warmThumb, thumbUrlFor, updateDownloadBadge, markCardCacheState, renderSidebar, renderList, videoById, slim, updatePlaylistOfflineButton | 2233 | +| deleteCustomVideo | 2049 | 620 | API, data, view, current, cachedIds, persist, toast, markCardCacheState, updateNowPlayingActions, renderList | 10566 | +| openVideoEditor | 2065 | 6603 | WEB, current, toast, customVideoId, downloadEdited, Player, showModal, closeModal | 10589, 11483 | +| Player | 2243 | 30427 | TAURI, WEB, perfMark, NO_HEVC_KEY, _currentBlobUrl, API, knownServerCachedIds, toAssetUrl, data, playFullMode, current, IS_IOS, useEqRender, abA, cachedIds, els, fmtTime, toast, preload, dropBrokenLocalCopy, showSpinner, chooseQuality, buildQualityMenu, offerPeerDownload, updateNowPlayingActions, Notes, Remote, Transition, Wave, Level, Gestures, Party, setHomeOverPlayer, showMiniBar, addToHistory, playNext, playPrev, updateServiceMode, channelKeyOf, markPlayingCard, scrollPlayerIntoViewPortrait, restoreAbMarkers, rememberPosEnabled, updateRememberPosUI, loadRelated, exitSelectMode | 2073, 2073, 2074, 2150, 2152, 2925, 2926, 2932, 2935, 2937, 2938, 2942, 2943, 2987, 2990, 2994, 2995, 2997, 2998, 3005, 3005, 3010, 3014, 3014, 3015, 3036, 3037, 3037, 3040, 3041, 3043, 3056, 3058, 3059, 3070, 3082, 3082, 3091, 3093, 3095, 3096, 3098, 3122, 3122, 3123, 3125, 3125, 3222, 3490, 3490, 3693, 3693, 3712, 3712, 4099, 4099, 4121, 4121, 4121, 4121, 4134, 4135, 4144, 4460, 4497, 4569, 4569, 4569, 4654, 4659, 4672, 4682, 4689, 4689, 4722, 4722, 4730, 4850, 4900, 4901, 4902, 4907, 4915, 5325, 5325, 5325, 5479, 5479, 5500, 5558, 5558, 5570, 5572, 5573, 5574, 5586, 5587, 5593, 5596, 5606, 5739, 5740, 5782, 5791, 5792, 5941, 5945, 6085, 6116, 6116, 6116, 6309, 6310, 6311, 6311, 6314, 6315, 6316, 6316, 6317, 6318, 6446, 6820, 6836, 6836, 6836, 6839, 6839, 6839, 7058, 7058, 7058, 7073, 7073, 7124, 7569, 7600, 7619, 7620, 7621, 7622, 7646, 7648, 7649, 7650, 7651, 7657, 7918, 7956, 7957, 7973, 7976, 7977, 8039, 8040, 8080, 8228, 8241, 8241, 8246, 8311, 8311, 8314, 8423, 8423, 8424, 8424, 8428, 8429, 8588, 8588, 9965, 11514, 11525, 11525, 11526, 11526, 11526, 11532, 11533, 11538, 11546, 11551, 11558, 11559, 11561, 11563, 11564, 11565, 11567, 11575, 11577, 11578, 11578, 11579, 11587, 11588, 11588, 11589, 11589, 11619, 11628, 11676, 11680, 11709, 11716, 11717, 11811, 11818, 11956, 12648, 12654, 12654, 12654, 12654, 12654, 12656, 12660, 12660, 12660, 12660, 12665, 12665, 12665, 12665, sw-update.js:177, sw-update.js:177 | +| showSpinner | 2947 | 75 | els | 2277, 2290, 2360, 2513, 2629, 3025, 3035, 3046 | +| chooseQuality | 2951 | 459 | data, current | 2356, 2874, 11560, 11576 | +| buildQualityMenu | 2964 | 559 | data, current, els | 2386 | +| wirePlayerEvents | 2984 | 4922 | WEB, perfMeasure, warmNextQueue, data, playFullMode, current, els, persist, Player, showSpinner, updatePlayBtn, updateProgress, onTrackEnded, rememberPosEnabled | 12565 | +| updatePlayBtn | 3089 | 530 | $, els, ICON_PLAY, ICON_PAUSE, Player, Remote | 2990, 3007, 7073, 7650, 7651, 7978, 8234, 8247, 12648, 12656, 12660, 12665 | +| reportingBroken | 3104 | 34 | — | 3107, 3108, 3132, 3363, 3364 | +| reportBroken | 3105 | 1271 | API, current, cachedIds, toast, preload, markCardCacheState, Player, reportingBroken, updateNowPlayingActions | 11494 | +| availCache | 3140 | 29 | — | 3150, 3153, 3158, 3158, 3158 | +| renderAvailability | 3141 | 1214 | WEB, data, current, $, availCache | 3354 | +| getFromPeers | 3171 | 1175 | cachedIds, downloading, toast, cacheMutations, recordDeviceFile, updateDownloadBadge, markCardCacheState, renderSidebar | 3217, 9214 | +| offerPeerDownload | 3197 | 1554 | WEB, data, cachedIds, els, toast, Player, getFromPeers | 2373 | +| openMoreControls | 3237 | 2465 | $, showModal, closeModal | 4718, 11477 | +| openAddChoice | 3294 | 998 | current, addToQueue, openCardMenu, showModal, closeModal | 11475 | +| openMoreActions | 3318 | 1347 | $, toast, showModal, closeModal | 11474 | +| setTile | 3347 | 135 | — | 3370, 3374, 3378, 3383 | +| updateNowPlayingActions | 3351 | 1537 | WEB, current, cachedIds, downloading, removing, $, els, isUploadId, reportingBroken, renderAvailability, setTile | 1842, 1882, 2057, 2400, 3109, 3133, 9442, 9497, 10040, 10075, 10575, 11457, 11469 | +| SERVICE_LYRIC_MIN_PX | 3390 | 32 | — | 4257 | +| fitLyricLines | 3400 | 2596 | — | 4257, 4411, 4414, 6225 | +| Notes | 3460 | 56491 | WEB, data, current, abA, $, persist, escapeHtml, toast, isUploadId, isMediaId, Player, SERVICE_LYRIC_MIN_PX, fitLyricLines, Party, isServiceModeOpen, updateServiceViewBtn, showModal, closeModal | 2380, 4722, 4722, 7810, 7810, 7903, 7963, 8502, 8644, 9981, 11586, 11598, 11599, 11601, 11602, 11630, 12648, 12648, 12648, 12658 | +| Remote | 4762 | 30421 | WEB, API, data, queue, queueIndex, current, sleepTimerRemaining, cachedIds, $, els, persist, escapeHtml, syncMuteIcon, fmtTime, toast, isMediaId, Player, playVideoAt, playFromList, renderUpNext, playNext, playPrev, isServiceModeOpen, enterServiceMode, exitServiceMode, slim, showModal, closeModal, closeSidebar, startSleepTimer, cancelSleepTimer | 2385, 3090, 8184, 12643 | +| TRANSITION_MODES | 5450 | 57 | — | 5636, 5636, 5636 | +| Transition | 5451 | 8619 | WEB, API, data, queue, queueIndex, queueSource, playFullMode, current, abA, abB, cachedIds, $, els, persist, toast, Player, TRANSITION_MODES, Party, advanceQueue, sleepAtTrackEnd | 2266, 7964, 8238, 11360, 12646 | +| Wave | 5668 | 5245 | WEB, data, current, $, fmtTime, isMediaId, Player | 2381, 7967, 11573 | +| CatalogSync | 5801 | 1192 | WEB, webFetch, SearchLibrary | 5829, 12730 | +| collectSearchMetadata | 5829 | 81 | WEB, CatalogSync | 251, 11180 | +| Recommendations | 5831 | 5450 | WEB, webFetch, data, $, els, profileHeaders, updateBottomChrome, setHomeOverPlayer, playFromList, addToQueue, openCardMenu | 8738, 8920, 12729 | +| StatsTrack | 5923 | 1462 | data, current, persist, Player | 5968, 7966 | +| renderStats | 5965 | 7074 | data, view, $, els, escapeHtml, toast, Player, StatsTrack, resetListHeaderExtras | 8894 | +| Presenter | 6097 | 9492 | WEB, $, escapeHtml, isMediaId, Player, fitLyricLines | 12621 | +| playVideoAt | 6308 | 546 | current, toast, Player | 5179, 6409, 6575, 7569, 7643, 12517 | +| renderLibrary | 6325 | 1254 | view, els, resetListHeaderExtras, renderCard | 8896 | +| renderNotesView | 6360 | 3892 | data, $, els, escapeHtml, playVideoAt | 8895 | +| Share | 6434 | 8739 | data, current, abA, abB, escapeHtml, toast, isUploadId, isMediaId, Player, playVideoAt, showModal, closeModal | 11361, 12624 | +| Level | 6588 | 3894 | data, cachedIds, isUploadId, EqRender, EQ | 2382, 6695, 6695, 6696, 6877, 9647, 9872, 9911, 9918 | +| EqRender | 6684 | 5914 | WEB, data, cachedIds, Level, loadSoundFeatures, EQ | 698, 699, 1862, 1862, 6594, 6594, 6942, 6942, 9912, 12652, 12653, 12700 | +| PiP | 6807 | 1774 | current, $, els, toast, Player | 11363, 11600, 12647 | +| loadSoundFeatures | 6853 | 107 | — | 6749, 6877, 6946 | +| EQ_BANDS | 6854 | 36 | — | 6882, 6921, 6959, 7022 | +| EQ_PRESETS | 6855 | 40 | — | 6869, 6934, 6934, 6958, 6973, 6975 | +| EQ | 6856 | 7927 | data, current, $, els, persist, toast, Level, EqRender, loadSoundFeatures, EQ_BANDS, EQ_PRESETS, showModal, closeModal | 6609, 6610, 6686, 6694, 6762, 8567, 8567, 9643, 9649, 9911, 9917, 11364, 11603, 12649, 12651, 12652, 12652, 12653 | +| Gestures | 7033 | 5217 | data, current, $, els, persist, syncMuteIcon, Player, updatePlayBtn | 2383 | +| SectionRail | 7170 | 10973 | data, relatedCollapsed, persist, escapeHtml, restoreNowPlayingList | 10371, 11376, 12623 | +| External | 7417 | 4595 | queue, queueIndex, current, escapeHtml, toast, isUploadId, showModal, closeModal | 11362 | +| Party | 7499 | 22833 | WEB, API, data, current, cachedIds, $, els, escapeHtml, fmtTime, toast, Player, updatePlayBtn, Notes, playVideoAt, advanceQueue, playNext, playPrev, closeSidebar | 2384, 4392, 4392, 4392, 5478, 8217, 8233, 8240, 8310, 12628 | +| updateProgress | 7955 | 1111 | data, playFullMode, current, abA, abB, $, els, fmtTime, Player, updatePlayBtn, Notes, Transition, Wave, StatsTrack, updateMiniBar, advanceQueue, updateServiceProgress, sleepAtTrackEnd, applySleepFade | 3049, 3077 | +| updateBottomChrome | 7990 | 525 | — | 5886, 8001, 8002, 8035, 8048, 12686 | +| setHomeOverPlayer | 8008 | 702 | current, els, showMiniBar, isServiceModeOpen, exitServiceMode, renderHomePlaylists | 2278, 5871, 8170, 10343, 11312, 11320 | +| showMiniBar | 8027 | 376 | current, $, updateBottomChrome, updateMiniBar, channelKeyOf | 2402, 8021, 11005 | +| updateMiniBar | 8037 | 303 | current, $, fmtTime, Player | 7961, 8034 | +| hideMiniBar | 8046 | 111 | $, updateBottomChrome | 11004, 11632, 11650 | +| addToHistory | 8054 | 535 | data, view, persist, renderList | 2379 | +| playFromList | 8071 | 403 | warmNextQueue, data, queue, queueIndex, queueSource, playFullMode, Player, unshuffledQueue, applyShuffle, renderUpNext | 4943, 5871, 8158, 8633, 8780, 8952, 8963, 8980, 8988, 9259, 9336, 9365, 9478, 10253 | +| unshuffledQueue | 8088 | 27 | — | 8076, 8092, 8092, 8105, 8107, 8108 | +| applyShuffle | 8090 | 436 | queue, queueIndex, unshuffledQueue | 8078, 8104 | +| toggleShuffle | 8101 | 558 | data, queue, queueIndex, current, persist, toast, unshuffledQueue, applyShuffle, renderUpNext, updateLoopRepeatButtons | 8290, 11517, 11594 | +| updateQueueBadge | 8119 | 339 | data, $ | 1548, 8132, 8146, 8152, 8723, 12669 | +| addToQueue | 8127 | 338 | data, view, persist, toast, updateQueueBadge, renderList, slim | 3310, 5874, 8955, 8966, 9004, 10548, 11402, 11498, 11595 | +| removeFromQueue | 8136 | 479 | data, view, queue, queueIndex, queueSource, current, persist, updateQueueBadge, renderUpNext, renderList | 10270, 11418 | +| clearQueue | 8149 | 148 | data, view, persist, toast, updateQueueBadge, renderList | 4692, 8943 | +| playQueue | 8156 | 119 | data, playFromList | 8940 | +| restoreNowPlayingList | 8164 | 845 | data, view, queueSource, current, els, setHomeOverPlayer, renderUpNext, _lastViewKey, render | 7234, 10338, 11025, 11639, 11650 | +| renderUpNext | 8182 | 1289 | queue, queueIndex, $, escapeHtml, Remote, playNext, updateServiceUpNext, openChannel, channelKeyOf | 4927, 4935, 4944, 8081, 8114, 8143, 8179, 8229, 8315, 10316, 11956 | +| advanceQueue | 8216 | 598 | data, queue, queueIndex, playFullMode, Player, Party, renderUpNext | 5574, 7569, 7974, 8234, 8242 | +| playNext | 8232 | 143 | $, updatePlayBtn, Party, advanceQueue | 2414, 4903, 4922, 7623, 8210, 11515, 11620, 12648, 12657, 12665 | +| onTrackEnded | 8237 | 702 | data, playFullMode, $, toast, Player, updatePlayBtn, Transition, Party, advanceQueue, sleepAtTrackEnd, finishSleep | 3078 | +| toggleLoopOne | 8251 | 191 | data, persist, toast, updateLoopRepeatButtons | 11519, 11592 | +| toggleRepeat | 8257 | 229 | data, persist, toast, updateLoopRepeatButtons | 11520, 11593 | +| PLAY_MODES | 8265 | 335 | — | 8286, 8293, 8302, 8305, 8305, 8306 | +| MODE_ICONS | 8272 | 456 | — | 8302 | +| playModeIndex | 8279 | 176 | data | 8286, 8301 | +| cyclePlayMode | 8285 | 416 | data, persist, toast, toggleShuffle, PLAY_MODES, playModeIndex, updateLoopRepeatButtons | 11518 | +| updateLoopRepeatButtons | 8295 | 769 | data, $, els, PLAY_MODES, MODE_ICONS, playModeIndex | 1547, 8113, 8254, 8260, 8292, 9906, 9907, 12667 | +| playPrev | 8309 | 268 | queue, queueIndex, Player, Party, renderUpNext | 2413, 4904, 7624, 11516, 11621, 12665 | +| serviceWakeLock | 8322 | 27 | — | 8332, 8337, 8337, 8338, 8341, 8343, 8344, 8349, 8355, 8357, 8358, 8361, 8369, 8369 | +| isServiceModeOpen | 8324 | 116 | $ | 2927, 2939, 2944, 4246, 4858, 8014, 8330, 8395, 8461, 8544, 11606, 11735, 12648, 12648 | +| acquireWakeLock | 8329 | 671 | serviceWakeLock, isServiceModeOpen, updateWakeStateUI | 2927, 2939, 2944, 8646 | +| releaseWakeLock | 8354 | 229 | serviceWakeLock, updateWakeStateUI | 8657, 11736 | +| updateWakeStateUI | 8366 | 268 | $, serviceWakeLock | 8333, 8345, 8351, 8363, 8432 | +| updateServiceUpNext | 8374 | 340 | queue, queueIndex, $ | 8183, 8420 | +| updateServiceProgress | 8385 | 379 | $, fmtTime | 7962, 8425 | +| updateServiceMode | 8394 | 1370 | queue, queueIndex, current, $, Player, isServiceModeOpen, updateWakeStateUI, updateServiceUpNext, updateServiceProgress, ServiceVisual, currentPlaylistEntry | 2403, 8643, 10759 | +| serviceVideoOn | 8441 | 96 | data | 8461, 8482 | +| applyServiceVideoLayout | 8457 | 351 | $, els, isServiceModeOpen, serviceVideoOn | 8468 | +| updateServiceVideoUI | 8467 | 90 | applyServiceVideoLayout, updateServiceViewBtn | 8501, 8641, 8655 | +| SERVICE_VIEWS | 8473 | 680 | — | 8489, 8489, 8507, 8511 | +| serviceView | 8480 | 213 | data, serviceVideoOn | 8489, 8508, 8544 | +| updateServiceViewBtn | 8486 | 484 | $, SERVICE_VIEWS, serviceView | 4262, 8469, 8503 | +| setServiceView | 8496 | 278 | data, persist, Notes, updateServiceVideoUI, updateServiceViewBtn, ServiceVisual | 8510 | +| cycleServiceView | 8506 | 327 | data, toast, SERVICE_VIEWS, serviceView, setServiceView | 11623 | +| SERVICE_FONT_SCALES | 8515 | 85 | — | 8523 | +| serviceFontStep | 8516 | 137 | data | 8521, 8531 | +| applyServiceFont | 8520 | 402 | $, SERVICE_FONT_SCALES, serviceFontStep | 8533, 8642 | +| stepServiceFont | 8530 | 150 | data, persist, serviceFontStep, applyServiceFont | 11624, 11625 | +| ServiceVisual | 8537 | 3523 | current, $, thumbUrlFor, Player, EQ, isServiceModeOpen, serviceView | 8421, 8504, 8645, 8656 | +| enterServiceMode | 8621 | 1132 | queueSource, current, $, Notes, playFromList, acquireWakeLock, updateServiceMode, updateServiceVideoUI, applyServiceFont, ServiceVisual | 4954, 8998, 11476, 11647 | +| exitServiceMode | 8649 | 351 | $, releaseWakeLock, updateServiceVideoUI, ServiceVisual | 4954, 8014, 11606, 11622, 11735 | +| openChannel | 8663 | 954 | API, view, channelData, els, toast, renderList, render | 8206, 10220, 11504, 11509, 11952 | +| channelKeyOf | 8688 | 227 | — | 2396, 8032, 8203, 8206, 10215, 10220, 11503, 11504, 11508, 11509, 11949, 11952 | +| renderSidebar | 8697 | 1422 | data, view, els, updateDownloadBadge, playlistOfflineStats, updateQueueBadge, renderHomePlaylists, render | 1265, 1552, 1729, 1890, 1913, 2042, 3192, 10360, 10405, 10503, 10836, 10844, 10872, 12632, 12663 | +| renderHomePlaylists | 8732 | 2774 | data, view, els, escapeHtml, toast, playlistOfflineStats, Recommendations, playFromList, updateHomeGridScrollState, render | 8020, 8725 | +| updateHomeGridScrollState | 8792 | 345 | — | 8786, 11150, 11151 | +| currentList | 8801 | 495 | data, view, searchResults, channelData, queue, getSmartList | 8908, 11389, 11399, 11426 | +| showSearchSkeletons | 8815 | 750 | els, setListPaneHidden | 9047, 11184 | +| setListPaneHidden | 8839 | 143 | — | 8818, 8888 | +| LIST_ICONS | 8845 | 547 | — | 8860, 8865 | +| listIconBtn | 8854 | 392 | LIST_ICONS | 9013, 9014, 9018, 9023, 9028, 9038 | +| setListIcon | 8864 | 126 | LIST_ICONS | 10795, 10805 | +| resetListHeaderExtras | 8869 | 399 | $, els | 5970, 6327, 8885, 8916, 9278, 9309, 9374, 9517, 9572 | +| renderList | 8882 | 10974 | WEB, data, view, searchResults, searchAttempted, channelData, listFilter, selectMode, selectedIds, $, els, persist, sharePlaylist, toast, Recommendations, renderStats, renderLibrary, renderNotesView, playFromList, addToQueue, clearQueue, playQueue, enterServiceMode, currentList, showSearchSkeletons, setListPaneHidden, listIconBtn, resetListHeaderExtras, addBrowseCta, renderP2pStrip, renderSavedSearches, renderP2pList, renderSaved, renderDownloads, renderSettings, renderCard, markPlayingCard, renamePlaylist, updatePlaylistOfflineButton, makePlaylistOffline, togglePinPlaylist, deletePlaylist, SMART_PLAYLISTS, toggleSelectMode | 378, 1735, 1837, 1884, 2006, 2025, 2036, 2059, 8065, 8133, 8147, 8153, 8676, 9535, 10041, 10077, 10274, 10319, 10362, 10765, 11199, 11210, 11382, 11386, 11405, 11611, 12039 | +| addBrowseCta | 9108 | 252 | view, render | 9074, 9081, 9088, 9096, 9411 | +| exportToDevice | 9128 | 5159 | WEB, hevcCapable, data, cachedIds, toast, fmtBytes, preload, getFromPeers, videoTitleById, showModal, closeModal | 9258, 9364, 9480, 10556, 11478, 12637, 12638 | +| p2pStripAt | 9237 | 40 | p2pStripData | 9241, 9243 | +| p2pStripData | 9237 | 40 | p2pStripAt | 9241, 9242, 9242, 9246, 9246, 9246 | +| renderP2pStrip | 9238 | 1834 | WEB, data, view, $, fmtBytes, playFromList, exportToDevice, p2pStripAt, p2pStripData, videoTitleById | 8976 | +| fmtAgo | 9269 | 263 | — | 9297, 9933, 11234 | +| renderSavedSearches | 9276 | 1587 | SearchLibrary, els, escapeHtml, fmtBytes, resetListHeaderExtras, fmtAgo | 8892 | +| renderP2pList | 9307 | 3593 | view, els, escapeHtml, fmtBytes, playFromList, resetListHeaderExtras, exportToDevice, videoTitleById, markPlayingCard, openCardMenu | 8891 | +| renderSaved | 9372 | 6530 | API, data, view, current, listFilter, cachedIds, $, els, persist, escapeHtml, toast, fmtBytes, isUploadId, thumbUrlFor, markCardCacheState, updateNowPlayingActions, playFromList, resetListHeaderExtras, addBrowseCta, exportToDevice, videoById, videoTitleById, markPlayingCard, showModal, closeModal | 8890 | +| renderDownloads | 9515 | 1216 | SaveQueue, view, listFilter, $, els, thumbUrlFor, resetListHeaderExtras, renderList, render, showModal, closeModal | 8893 | +| videoById | 9550 | 533 | data | 1795, 2016, 9458, 9566, 10018, 11401, 11427 | +| videoTitleById | 9565 | 85 | videoById | 9132, 9252, 9324, 9463, 10071 | +| renderSettings | 9570 | 31516 | WEB, APP_VERSION, saveDataToStorage, SearchLibrary, SaveSlots, API, data, view, current, cachedIds, $, els, persist, ProfileSecret, profileShareUrl, copyProfileLink, shareProfileLink, updateProfileStatus, createProfileFlow, protectProfileFlow, exportProfileCredentials, importProfileCredentials, loadProfileFlow, escapeHtml, syncMuteIcon, toast, applyAppearance, fmtBytes, preloadPlaylist, Player, updateNowPlayingActions, Notes, Level, EqRender, EQ, updateLoopRepeatButtons, resetListHeaderExtras, renderList, fmtAgo, videoById, videoTitleById, exportPlaylists, importPlaylists, openImportYouTubeModal, showModal, closeModal, doAutoBackup, importBackup, hardReloadUI | 8889 | +| renderCard | 10192 | 5357 | warmStreams, data, view, queue, queueIndex, queueSource, current, dragSource, selectMode, selectedIds, cachedIds, downloading, persist, escapeHtml, fmtTime, toast, playFromList, removeFromQueue, renderUpNext, openChannel, channelKeyOf, renderList, render, openCardMenu, openSongNoteModal, toggleSelectCard | 6354, 9104 | +| markPlayingCard | 10326 | 170 | current | 2401, 9105, 9369, 9509 | +| _lastViewKey | 10348 | 24 | — | 8177, 10351, 10351, 10367, 10367, 10368 | +| render | 10349 | 1194 | view, listFilter, $, els, SectionRail, renderSidebar, renderList, _lastViewKey, scrollListIntoViewPortrait, closeSidebar, renderSmartSidebar, exitSelectMode | 939, 1266, 1554, 8178, 8667, 8713, 8777, 9112, 9533, 10278, 10344, 10504, 10627, 10644, 10683, 10712, 10885, 11176, 11183, 11289, 11312, 11321, 11420, 11980, 11987, 12060, 12112, 12497, 12542, 12613, 12630, 12705 | +| exportPlaylists | 10377 | 402 | data, toast | 10097 | +| importPlaylists | 10388 | 876 | data, persist, toast, renderSidebar | 10099 | +| openImportYouTubeModal | 10414 | 4468 | data, $, persist, escapeHtml, toast, uid, renderSidebar, render, slim, showModal, closeModal | 10096 | +| openCardMenu | 10540 | 4233 | API, data, view, current, cachedIds, playlistOps, runExclusive, persist, toast, preload, markCardCacheState, deleteCustomVideo, openVideoEditor, updateNowPlayingActions, addToQueue, exportToDevice, render, slim, newPlaylist, showModal, closeModal | 3311, 5875, 9364, 10257, 11480 | +| slim | 10651 | 487 | — | 1226, 1835, 2004, 4942, 8130, 10471, 10616, 10677, 11434, 12054, 12482, 12630 | +| newPlaylist | 10667 | 756 | data, view, persist, toast, uid, preload, render, slim, showModal, closeModal | 10635, 11148, 11325 | +| renamePlaylist | 10691 | 1109 | $, persist, render, showModal, closeModal | 9011, 9012, 9013 | +| openSongNoteModal | 10719 | 1703 | queueSource, current, persist, toast, updateServiceMode, renderList, showModal, closeModal | 10243 | +| updatePlaylistOfflineButton | 10787 | 1338 | downloading, playlistOfflineStats, setListIcon | 1733, 1888, 1917, 2040, 9020, 10834, 10842, 10871 | +| makePlaylistOffline | 10814 | 1075 | view, cachedIds, $, toast, preload, playlistOfflineStats, renderSidebar, updatePlaylistOfflineButton | 9018 | +| togglePinPlaylist | 10847 | 1045 | data, $, persist, toast, preload, renderSidebar, updatePlaylistOfflineButton | 9023 | +| deletePlaylist | 10875 | 507 | data, view, persist, render, showModal, closeModal | 9028 | +| toggleShortcutHelp | 10894 | 108 | $ | 11604 | +| wireShortcutHelp | 10899 | 272 | $ | 12567 | +| showModal | 10909 | 515 | $ | 833, 998, 1143, 1244, 1364, 1394, 1497, 1570, 2207, 3289, 3312, 3342, 3782, 3877, 4036, 4077, 4125, 4224, 5082, 5297, 5350, 5365, 6557, 6951, 6986, 7443, 9152, 9423, 9481, 9531, 9531, 10032, 10164, 10483, 10522, 10648, 10671, 10706, 10776, 10876, 11409, 11444, 11492, 11800, 12049, 12096, 12256, 12630, 12633 | +| closeModal | 10925 | 61 | $ | 832, 835, 998, 1121, 1245, 1246, 1365, 1366, 1395, 1422, 1473, 1477, 1488, 1494, 1571, 1576, 2208, 2232, 3282, 3289, 3307, 3312, 3338, 3342, 3783, 3784, 3878, 3887, 4030, 4037, 4067, 4078, 4121, 4125, 5083, 5297, 5351, 5352, 5366, 5367, 6549, 6951, 6986, 7443, 9152, 9155, 9424, 9429, 9440, 9484, 9489, 9498, 9532, 9532, 10033, 10038, 10168, 10171, 10484, 10489, 10523, 10548, 10556, 10566, 10570, 10589, 10626, 10635, 10638, 10644, 10672, 10681, 10707, 10712, 10764, 10777, 10877, 10883, 10933, 11410, 11420, 11435, 11442, 11444, 11493, 11494, 11616, 11791, 11795, 11801, 11802, 12050, 12058, 12097, 12111, 12257, 12259, 12630, 12633, 12633 | +| _portraitPwaMQ | 10944 | 172 | — | 10949, 11051 | +| isPortraitPWA | 10948 | 61 | _portraitPwaMQ | 10961, 11015, 11055 | +| isStackedPlayerLayout | 10954 | 412 | isPortraitPWA | 10339, 11026, 11039, 11637 | +| playerScrollBehavior | 10964 | 160 | data | 11029, 11046 | +| setupClassicLayout | 10968 | 2013 | current, $, showMiniBar, hideMiniBar | 12569 | +| applyPortraitPwaClass | 11012 | 223 | isPortraitPWA | 11050, 11052 | +| scrollPlayerIntoViewPortrait | 11024 | 241 | restoreNowPlayingList, isStackedPlayerLayout, playerScrollBehavior | 2421, 11637 | +| scrollListIntoViewPortrait | 11038 | 556 | isStackedPlayerLayout, playerScrollBehavior | 10367, 11181, 11188 | +| setupPortraitPwaWatcher | 11049 | 313 | _portraitPwaMQ, isPortraitPWA, applyPortraitPwaClass, closeSidebar | 12568 | +| setupViewportAnchorGuard | 11076 | 1614 | els | 12570 | +| openSidebar | 11113 | 211 | $ | 11134 | +| closeSidebar | 11120 | 216 | $ | 5358, 5358, 7876, 7876, 10358, 10358, 11055, 11133, 11137, 11609 | +| setupSidebarDrawer | 11127 | 399 | $, openSidebar, closeSidebar | 11141 | +| wireUI | 11140 | 24799 | perfMark, perfMeasure, RecentSearches, SearchLibrary, API, warmStreams, data, view, searchResults, searchAttempted, searchSeq, current, listFilter, selectMode, selectedIds, relatedCollapsed, cachedIds, downloading, removing, runExclusive, $, els, persist, copyProfileLink, shareProfileLink, escapeHtml, lastVolume, syncMuteIcon, toast, warmSearchThumbs, preload, markCardCacheState, openVideoEditor, Player, chooseQuality, reportBroken, openMoreControls, openAddChoice, openMoreActions, updateNowPlayingActions, Notes, Transition, Wave, collectSearchMetadata, Share, PiP, EQ, SectionRail, External, setHomeOverPlayer, hideMiniBar, toggleShuffle, addToQueue, removeFromQueue, restoreNowPlayingList, playNext, toggleLoopOne, toggleRepeat, cyclePlayMode, playPrev, isServiceModeOpen, cycleServiceView, stepServiceFont, enterServiceMode, exitServiceMode, openChannel, channelKeyOf, updateHomeGridScrollState, currentList, showSearchSkeletons, renderList, exportToDevice, fmtAgo, videoById, render, openCardMenu, slim, newPlaylist, toggleShortcutHelp, showModal, closeModal, isStackedPlayerLayout, scrollPlayerIntoViewPortrait, scrollListIntoViewPortrait, closeSidebar, setupSidebarDrawer, cancelSleepTimer, openSleepTimer, setAbA, setAbB, clearAb, toggleRememberPos, exitSelectMode, newPlaylistWithVideos, updateFromIcon | 12566 | +| sleepAtTrackEnd | 11664 | 28 | — | 5477, 7965, 8239, 11686, 11708, 11745, 11747, 11799 | +| sleepFading | 11665 | 24 | — | 11676, 11676, 11679, 11709, 11709, 11752 | +| sleepFadeSec | 11667 | 138 | data | 11674, 11761, 11796, 11796 | +| applySleepFade | 11673 | 346 | data, Player, sleepFading, sleepFadeSec | 7965, 11698 | +| startSleepTimer | 11683 | 487 | sleepTimerRemaining, sleepTimerTick, sleepAtTrackEnd, applySleepFade, cancelSleepTimer, finishSleep, updateSleepTimerUI | 4950, 11790, 11794 | +| cancelSleepTimer | 11704 | 253 | sleepTimerRemaining, sleepTimerTick, Player, sleepAtTrackEnd, sleepFading, updateSleepTimerUI | 4950, 11359, 11684, 11715, 11801 | +| finishSleep | 11714 | 674 | data, toast, Player, cancelSleepTimer, showSleepCurtain | 8239, 11696 | +| showSleepCurtain | 11734 | 390 | $, isServiceModeOpen, releaseWakeLock, exitServiceMode | 11724, 11726 | +| updateSleepTimerUI | 11744 | 579 | sleepTimerRemaining, $, sleepAtTrackEnd, sleepFading | 11687, 11692, 11699, 11710 | +| openSleepTimer | 11758 | 2657 | data, sleepTimerRemaining, persist, toast, showModal, closeModal, sleepAtTrackEnd, sleepFadeSec, startSleepTimer, cancelSleepTimer | 11357 | +| setAbA | 11809 | 152 | current, abA, fmtTime, toast, Player, saveAbMarkers, updateAbUI | 11367, 11596, 12659 | +| setAbB | 11816 | 152 | current, abB, fmtTime, toast, Player, saveAbMarkers, updateAbUI | 11368, 11597, 12659 | +| clearAb | 11823 | 263 | data, current, abA, abB, persist, toast, currentPlaylistEntry, updateAbUI | 11369, 12654, 12659 | +| saveAbMarkers | 11834 | 550 | data, current, abA, abB, persist, currentPlaylistEntry | 11812, 11819, 12654 | +| restoreAbMarkers | 11848 | 426 | data, current, abA, abB, currentPlaylistEntry, updateAbUI | 2423 | +| currentPlaylistEntry | 11860 | 383 | data, queueSource, current | 8405, 11827, 11842, 11852, 11875, 11882 | +| rememberPosEnabled | 11873 | 196 | data, current, currentPlaylistEntry | 2437, 3060, 3069, 11881, 11894 | +| toggleRememberPos | 11878 | 467 | data, current, persist, toast, currentPlaylistEntry, rememberPosEnabled, updateRememberPosUI | 11370 | +| updateRememberPosUI | 11892 | 134 | $, rememberPosEnabled | 2424, 11889 | +| updateAbUI | 11897 | 931 | abA, abB, $, fmtTime | 11813, 11820, 11831, 11849, 11856, 12654 | +| relatedState | 11915 | 51 | — | 11920, 11928, 11932, 11934, 11935 | +| fetchRelatedVideos | 11916 | 265 | API, current, relatedVideos, relatedState, renderRelated | 11924 | +| loadRelated | 11923 | 115 | current, fetchRelatedVideos | 2425, 11938 | +| renderRelated | 11926 | 2002 | queue, queueIndex, playFullMode, relatedVideos, relatedCollapsed, $, escapeHtml, Player, renderUpNext, openChannel, channelKeyOf, relatedState, loadRelated | 11920 | +| SMART_PLAYLISTS | 11965 | 233 | — | 8947, 11975 | +| renderSmartSidebar | 11971 | 928 | WEB, data, view, $, render, SMART_PLAYLISTS | 938, 1553, 10361, 12612 | +| getSmartList | 11991 | 926 | data | 8807 | +| exitSelectMode | 12023 | 230 | selectMode, selectedIds, $ | 2426, 10359, 11386, 11405, 11420, 11435, 11442, 11611 | +| toggleSelectMode | 12031 | 328 | selectMode, selectedIds, $, renderList | 9038 | +| toggleSelectCard | 12041 | 309 | selectedIds, $ | 10252 | +| newPlaylistWithVideos | 12046 | 721 | data, view, persist, toast, uid, preload, render, slim, showModal, closeModal | 11442 | +| doAutoBackup | 12070 | 479 | data, persist, toast | 10104, 12086 | +| checkAutoBackup | 12083 | 232 | data, doAutoBackup | 12704 | +| importBackup | 12088 | 1722 | data, persist, toast, render, showModal, closeModal | 10106 | +| RUNNING_BUILD | 12135 | 159 | — | 12159, 12239, 12350, 12350, 12350, 12353 | +| _knownBuildTag | 12141 | 26 | — | 12159, 12160, 12178, 12239 | +| fetchServerBuild | 12143 | 196 | — | 12157, 12238, 12347 | +| maybeShowUpdateBanner | 12154 | 774 | RUNNING_BUILD, _knownBuildTag, fetchServerBuild, prefetchUpdate, _updateBannerShown, _updating, showUpdateBanner | 12190, 12386, 12393, 12399 | +| _prefetchedFor | 12175 | 26 | — | 12179, 12180 | +| prefetchUpdate | 12176 | 398 | _knownBuildTag, _prefetchedFor, _swReg | 12167 | +| checkBuildTag | 12189 | 62 | maybeShowUpdateBanner | 12194, 12712, 12713 | +| pollBuildTag | 12193 | 117 | checkBuildTag | 12711 | +| hardReloadUI | 12204 | 865 | — | 10160 | +| _updateBannerShown | 12224 | 31 | — | 12155, 12248, 12249, 12334, 12345, 12352, 12361 | +| _updating | 12225 | 22 | — | 12155, 12235, 12288, 12289, 12328 | +| _updateToast | 12226 | 24 | — | 12308, 12308, 12309, 12330, 12330, 12330, 12357 | +| setUpdateIcon | 12230 | 106 | $ | 12236, 12240, 12251, 12257, 12332 | +| updateFromIcon | 12234 | 384 | toast, RUNNING_BUILD, _knownBuildTag, fetchServerBuild, _updating, setUpdateIcon, applyUpdate | 11629 | +| showUpdateBanner | 12246 | 821 | showModal, closeModal, _updateBannerShown, setUpdateIcon, applyUpdate | 12168 | +| _swReg | 12267 | 18 | — | 12183, 12295, 12372 | +| UPDATE_STATE_KEY | 12273 | 44 | — | 12278, 12282, 12283 | +| UPDATE_MAX_ATTEMPTS | 12274 | 30 | — | 12356 | +| SHELL_CACHE_RE | 12275 | 54 | — | 12316 | +| readUpdateState | 12277 | 134 | UPDATE_STATE_KEY | 12290, 12342 | +| writeUpdateState | 12280 | 251 | UPDATE_STATE_KEY | 12291, 12329, 12351, 12362 | +| applyUpdate | 12287 | 2240 | toast, _updateBannerShown, _updating, _updateToast, setUpdateIcon, _swReg, SHELL_CACHE_RE, readUpdateState, writeUpdateState | 12243, 12260, 12358 | +| checkUpdateOutcome | 12341 | 1002 | toast, RUNNING_BUILD, fetchServerBuild, _updateBannerShown, _updateToast, UPDATE_MAX_ATTEMPTS, readUpdateState, writeUpdateState, applyUpdate | 12709 | +| registerServiceWorker | 12366 | 1896 | WEB, maybeShowUpdateBanner, _swReg | 12710 | +| youtubeFromText | 12419 | 341 | — | 12515 | +| SHARE_INBOX | 12427 | 38 | — | 12464 | +| SHARED_PLAYLIST | 12428 | 41 | — | 12433, 12485 | +| sharedUploadsPlaylist | 12430 | 231 | data, uid, SHARED_PLAYLIST | 12481, 12495 | +| uploadSharedFile | 12440 | 852 | — | 12473 | +| _sharing | 12459 | 21 | — | 12461, 12462, 12499 | +| processSharedFiles | 12460 | 1649 | view, persist, toast, render, slim, SHARE_INBOX, SHARED_PLAYLIST, sharedUploadsPlaylist, uploadSharedFile, _sharing | 12525, 12526 | +| bootShareFromUrl | 12502 | 1091 | data, els, toast, playVideoAt, youtubeFromText, processSharedFiles | 12627 | +| URL_VIEWS | 12530 | 121 | — | 12540 | +| bootViewFromUrl | 12531 | 391 | view, render, URL_VIEWS | 12625 | +| bootSearchFromUrl | 12545 | 414 | els | 12626 | +| boot | 12563 | 11475 | WEB, APP_VERSION, perfMark, perfMeasure, webFetch, SaveQueue, API, DEFAULT_SETTINGS, data, view, current, abA, abB, cachedIds, downloading, $, els, persist, ProfileSecret, profileHeaders, syncOnLaunch, updateProfileStatus, adoptSharedPlaylistFromUrl, startPlaylistInboxWatch, adoptProfileFromUrl, syncMuteIcon, toast, uid, applyAppearance, refreshCachedIds, startCacheResyncWatch, warmOfflineThumbs, preload, preloadPlaylist, preloadPinnedPlaylists, Player, wirePlayerEvents, updatePlayBtn, Notes, Remote, Transition, CatalogSync, Recommendations, Presenter, Share, EqRender, PiP, EQ, SectionRail, Party, updateBottomChrome, updateQueueBadge, playNext, updateLoopRepeatButtons, playPrev, isServiceModeOpen, renderSidebar, exportToDevice, render, slim, wireShortcutHelp, showModal, closeModal, setupClassicLayout, setupPortraitPwaWatcher, setupViewportAnchorGuard, wireUI, setAbA, setAbB, clearAb, saveAbMarkers, updateAbUI, renderSmartSidebar, checkAutoBackup, checkBuildTag, pollBuildTag, checkUpdateOutcome, registerServiceWorker, bootShareFromUrl, bootViewFromUrl, bootSearchFromUrl | 12734 | From 3c9a24ae45cc6efdf1112667d20f1cf64a7411b1 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:38:37 +0800 Subject: [PATCH 32/81] Extract eager shell and shared view renderers before app boot --- frontend/app-seams.test.js | 40 + frontend/app.js | 2032 +----------------------------------- frontend/assets.json | 8 +- frontend/index.html | 5 +- frontend/section-rail.js | 247 +++++ frontend/shell-core.js | 304 ++++++ frontend/sw.js | 3 + frontend/views-core.js | 1501 ++++++++++++++++++++++++++ perf/seams.mjs | 70 ++ 9 files changed, 2198 insertions(+), 2012 deletions(-) create mode 100644 frontend/app-seams.test.js create mode 100644 frontend/section-rail.js create mode 100644 frontend/shell-core.js create mode 100644 frontend/views-core.js create mode 100644 perf/seams.mjs diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js new file mode 100644 index 0000000..23890ad --- /dev/null +++ b/frontend/app-seams.test.js @@ -0,0 +1,40 @@ +const {test}=require('node:test'); +const assert=require('node:assert/strict'); +const {readFileSync}=require('node:fs'); +const {createHash}=require('node:crypto'); +const {join}=require('node:path'); +const app=readFileSync(join(__dirname,'app.js'),'utf8'); +test('Phase 4 preserves the exact player, continuity, tracking and queue bodies',()=>{ + {const start=app.indexOf("const Player = {");assert.ok(start>=0,"Player");const body=app.slice(start,start+30343);assert.equal(createHash('sha256').update(body).digest('hex'),"373df46f4f994717472d26a6bac07449f6ca0a930cb666bfe3895d1dc65aa351","Player body unchanged");} + {const start=app.indexOf("const Transition = (() => {");assert.ok(start>=0,"Transition");const body=app.slice(start,start+8588);assert.equal(createHash('sha256').update(body).digest('hex'),"71997a537078308a41f0cbf8e29fd1658fb3a199c4f5a25d8af0931f1c2a6d50","Transition body unchanged");} + {const start=app.indexOf("const Wave = (() => {");assert.ok(start>=0,"Wave");const body=app.slice(start,start+5241);assert.equal(createHash('sha256').update(body).digest('hex'),"7252f4e856c59aef8aabfcd394ce4bcba656110cbd01a1a8af662eeb48166a3c","Wave body unchanged");} + {const start=app.indexOf("const StatsTrack = (() => {");assert.ok(start>=0,"StatsTrack");const body=app.slice(start,start+1462);assert.equal(createHash('sha256').update(body).digest('hex'),"9aae2631ba3bfad918319579b7120814af06c84949394d04e52c65345332d514","StatsTrack body unchanged");} + {const start=app.indexOf("function wirePlayerEvents() {");assert.ok(start>=0,"wirePlayerEvents");const body=app.slice(start,start+4913);assert.equal(createHash('sha256').update(body).digest('hex'),"1c5a2b5ce310f6aef6764325eda85a95f47e4f507f2049036ce1da206379908c","wirePlayerEvents body unchanged");} + {const start=app.indexOf("function updatePlayBtn() {");assert.ok(start>=0,"updatePlayBtn");const body=app.slice(start,start+522);assert.equal(createHash('sha256').update(body).digest('hex'),"1326233af07ae92a5ecc81cc211bd98d21ed5f291dc4eb59d040b8df9baba8c8","updatePlayBtn body unchanged");} + {const start=app.indexOf("function persist() {");assert.ok(start>=0,"persist");const body=app.slice(start,start+147);assert.equal(createHash('sha256').update(body).digest('hex'),"01e5c5dbc80616266db09b3829dc45b66476a3256b1c169d8e44f4983b24ac45","persist body unchanged");} + {const start=app.indexOf("function playFromList(list, index, source = '', { playFull = false } = {}) {");assert.ok(start>=0,"playFromList");const body=app.slice(start,start+401);assert.equal(createHash('sha256').update(body).digest('hex'),"f8009c9674b3478959997dca881fb7b9e1ab3708c98e5abdf1958d752e47ee41","playFromList body unchanged");} + {const start=app.indexOf("function advanceQueue() {");assert.ok(start>=0,"advanceQueue");const body=app.slice(start,start+596);assert.equal(createHash('sha256').update(body).digest('hex'),"be405b9c163e3d41a949ef11f6022ef13115b04083e3b6ad21d97beba1f45ae6","advanceQueue body unchanged");} + {const start=app.indexOf("function playNext() {");assert.ok(start>=0,"playNext");const body=app.slice(start,start+143);assert.equal(createHash('sha256').update(body).digest('hex'),"859d2ffd2e8c89a8d9c0dd0cf429fd403675452cedba2e34aa3dc72683d4f8c6","playNext body unchanged");} + {const start=app.indexOf("function playPrev() {");assert.ok(start>=0,"playPrev");const body=app.slice(start,start+268);assert.equal(createHash('sha256').update(body).digest('hex'),"ece8d33bd03c8146a6a702534c8fed50ff606170685b08d730b19d9d3c68cf48","playPrev body unchanged");} + {const start=app.indexOf("function onTrackEnded() {");assert.ok(start>=0,"onTrackEnded");const body=app.slice(start,start+702);assert.equal(createHash('sha256').update(body).digest('hex'),"d6e147238ad9656fa1c2335973b37597749bcfd02df1a66390b306fe1194ae0d","onTrackEnded body unchanged");} + {const start=app.indexOf("function sleepFadeSec() {");assert.ok(start>=0,"sleepFadeSec");const body=app.slice(start,start+138);assert.equal(createHash('sha256').update(body).digest('hex'),"3f986c8cc474d8313476e9c209b9264e3724011ffaee887f47178bb5155a4d77","sleepFadeSec body unchanged");} + {const start=app.indexOf("function applySleepFade(remaining) {");assert.ok(start>=0,"applySleepFade");const body=app.slice(start,start+346);assert.equal(createHash('sha256').update(body).digest('hex'),"9bd0fa697b271c6b80c128ff1d0a7b00afcb3ccf08f98b5c7e7dc86fd4329681","applySleepFade body unchanged");} + {const start=app.indexOf("function startSleepTimer(minutes, { endOfSong = false } = {}) {");assert.ok(start>=0,"startSleepTimer");const body=app.slice(start,start+487);assert.equal(createHash('sha256').update(body).digest('hex'),"f0a93401ab90196096074cb607b28d52c5903e11dbdfb8ddb95114e143af2409","startSleepTimer body unchanged");} + {const start=app.indexOf("function cancelSleepTimer() {");assert.ok(start>=0,"cancelSleepTimer");const body=app.slice(start,start+253);assert.equal(createHash('sha256').update(body).digest('hex'),"cf396ab758a70eede6af7444539a82ca15af801a9a57024dd5542067e9fa771a","cancelSleepTimer body unchanged");} + {const start=app.indexOf("function finishSleep() {");assert.ok(start>=0,"finishSleep");const body=app.slice(start,start+662);assert.equal(createHash('sha256').update(body).digest('hex'),"7ee93bf760bad5f39f4644339963918c5b369b2acc554b8e561c1a1f070ac6fb","finishSleep body unchanged");} + {const start=app.indexOf("const EQ = (() => {");assert.ok(start>=0,"EQ");const body=app.slice(start,start+7917);assert.equal(createHash('sha256').update(body).digest('hex'),"f0cba011c94f33e6fd0ab778021f4c97238262dfa0a8dd40bf3f17149c227528","EQ body unchanged");} + {const start=app.indexOf("const EqRender = (() => {");assert.ok(start>=0,"EqRender");const body=app.slice(start,start+5912);assert.equal(createHash('sha256').update(body).digest('hex'),"f014dd41dafebc33f09e87be866074afd7a2443c5bb452103a435585353a828f","EqRender body unchanged");} + {const start=app.indexOf("const Level = (() => {");assert.ok(start>=0,"Level");const body=app.slice(start,start+3892);assert.equal(createHash('sha256').update(body).digest('hex'),"e48ad7797384ac31bb8b864662fc2a546b04470b981042f016874ba750957226","Level body unchanged");} +}); + +test('eager shell and Settings definitions load before app state and defer reading it',()=>{ + const html=readFileSync(join(__dirname,'index.html'),'utf8'); + for(const file of ['shell-core.js','views-core.js','section-rail.js']) { + assert.ok(html.indexOf('src="'+file+'"') { })(); function collectSearchMetadata(q, cards) { if (WEB) CatalogSync.send(q, cards); } -const Recommendations = (() => { - let cards = [], fetchedAt = 0, loading = false, error = false, actor = '', queuedRefresh = false; - let listHost = null; - const deviceFingerprint = () => window.getFingerprint ? window.getFingerprint() : 'unknown'; - const fingerprint = () => data.profile?.name ? 'profile:' + data.profile.name.toLowerCase() : 'device:' + deviceFingerprint(); - function load() { - const fp = fingerprint(); - if (fp === actor) return; - actor = fp; cards = []; fetchedAt = 0; - try { - const saved = JSON.parse(localStorage.getItem('ytpRecommendations:' + fp) || 'null'); - if (saved && Array.isArray(saved.cards)) cards = saved.cards; - } catch { /* no saved recommendations */ } - } - function paint(host) { - if (!host) return; - host.replaceChildren(); - const heading = document.createElement('div'); heading.className = 'rec-heading'; - const copy = document.createElement('div'); - const title = document.createElement('h2'); title.textContent = 'Recommended for you'; - const sub = document.createElement('p'); sub.textContent = error && cards.length ? 'Saved picks · reconnect to refresh' : 'Familiar favorites and something new, inspired by your listening.'; - copy.append(title, sub); - const refresh = document.createElement('button'); refresh.type = 'button'; refresh.className = 'rec-refresh'; - refresh.textContent = loading ? 'Updating…' : 'Refresh'; refresh.disabled = loading; - refresh.onclick = () => update(true); - heading.append(copy, refresh); host.appendChild(heading); - if (!cards.length) { - const empty = document.createElement('p'); empty.className = 'rec-empty'; empty.setAttribute('role', 'status'); - empty.textContent = loading ? 'Finding your next listen…' : error ? 'Recommendations are unavailable. You can still search or play your playlists.' : 'Search or play a few videos to start discovering recommendations here.'; - host.appendChild(empty); return; - } - const grid = document.createElement('div'); grid.className = 'rec-grid'; - cards.forEach((v, i) => { - const item = document.createElement('article'); item.className = 'rec-item'; - const play = document.createElement('button'); play.type = 'button'; play.className = 'rec-play'; - play.setAttribute('aria-label', 'Play ' + v.title); - const cover = document.createElement('span'); cover.className = 'rec-cover'; - const img = document.createElement('img'); img.src = v.thumbnail || ''; img.alt = ''; img.loading = 'lazy'; img.decoding = 'async'; cover.appendChild(img); - const title = document.createElement('span'); title.className = 'rec-title'; title.textContent = v.title; - const channel = document.createElement('span'); channel.className = 'rec-channel'; channel.textContent = v.channel || ''; - play.append(cover, title, channel); play.onclick = () => { setHomeOverPlayer(false); playFromList(cards.slice(), i, 'recommendations'); }; - const reason = document.createElement('div'); reason.className = 'rec-reason'; reason.textContent = v.reason || 'Recommended for you'; - const actions = document.createElement('div'); actions.className = 'rec-actions'; - const queue = document.createElement('button'); queue.type = 'button'; queue.textContent = '+ Queue'; queue.setAttribute('aria-label', 'Queue ' + v.title); queue.onclick = () => addToQueue(v); - const more = document.createElement('button'); more.type = 'button'; more.textContent = '•••'; more.setAttribute('aria-label', 'More actions for ' + v.title); more.onclick = () => openCardMenu(v); - actions.append(queue, more); item.append(play, reason, actions); grid.appendChild(item); - }); - host.appendChild(grid); - } - function repaint() { - if (!WEB) return; - const home = $('homeRecommendations'); - if (home) { home.classList.remove('hidden'); paint(home); } - els.playerPane?.classList.add('has-recommendations'); - if (listHost?.isConnected) paint(listHost); - requestAnimationFrame(updateBottomChrome); - } - async function update(force = false) { - load(); - if (!WEB) return; - if (loading) { if (force) queuedRefresh = true; return; } - if (!force && Date.now() - fetchedAt < 300000) return; - const fp = actor; loading = true; error = false; repaint(); - try { - const name = data.profile?.name || ''; - const result = await webFetch('/api/recommendations?fp=' + encodeURIComponent(deviceFingerprint()) + (name ? '&profile=' + encodeURIComponent(name) : ''), { headers: name ? profileHeaders(name) : {} }); - if (fp !== fingerprint()) return; - if (!result.ok || !Array.isArray(result.results)) throw new Error('invalid recommendations'); - cards = result.results; - try { localStorage.setItem('ytpRecommendations:' + fp, JSON.stringify({ cards })); } catch { /* full */ } - } catch { error = true; } - finally { - loading = false; fetchedAt = fp === fingerprint() ? Date.now() : 0; repaint(); - if (queuedRefresh || fp !== fingerprint()) { queuedRefresh = false; update(true); } - } - } - function home() { if (WEB) { load(); repaint(); update(); } } - function inList() { - if (!WEB) return; - listHost = document.createElement('section'); listHost.className = 'recommendations'; listHost.setAttribute('aria-label', 'Recommended videos'); - els.cards.appendChild(listHost); load(); paint(listHost); update(); - } - return { home, inList, update }; -})(); + // ============================================================================ // Listening stats — tracker (data.stats, see frontend/stats-core.js) @@ -6322,111 +6199,12 @@ async function playVideoAt(v, t = 0) { // ============================================================================ // 📁 Library — video/audio uploaded to this server // ============================================================================ -async function renderLibrary() { - els.listTitle.textContent = 'Library'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - els.cards.innerHTML = '
Loading the server library…
'; - let list = []; - try { - const j = await (await fetch('/api/uploads?limit=200')).json(); - list = (j && j.ok && j.uploads) || []; - } catch { - els.cards.innerHTML = '
⚠ Could not reach the server
'; - return; - } - if (view.type !== 'library') return; - if (!list.length) { - els.cards.innerHTML = ` -
-
📁
-

Nothing uploaded yet

-

An admin can upload videos and audio at /admin; they show up here and in search, with their cover art and any embedded lyrics.

-
`; - return; - } - const cards = list.map((u) => ({ - id: u.id, title: u.title, channel: u.artist || u.album || 'Uploaded', duration: u.duration, - thumbnail: u.art ? `/api/uploads/${u.id}/art` : '', kind: u.kind, upload: true, - })); - els.cards.innerHTML = ''; - cards.forEach((v, i) => els.cards.appendChild(renderCard(v, i, cards))); -} + // ============================================================================ // 📝 Notes view — every video's personal notes & bookmarks // ============================================================================ -function renderNotesView() { - els.listTitle.textContent = 'Notes'; - els.status.classList.add('hidden'); - const groups = Object.entries(data.bookmarks || {}) - .filter(([, list]) => Array.isArray(list) && list.length) - .map(([id, list]) => { - const h = data.history.find((x) => x.id === id); - const first = list.find((b) => b.vt) || {}; - return { id, title: first.vt || (h && h.title) || id, channel: first.vc || (h && h.channel) || '', list }; - }); - // Most recently played first (history order), the rest after. - const order = new Map(data.history.map((v, i) => [v.id, i])); - groups.sort((a, b) => (order.has(a.id) ? order.get(a.id) : 1e9) - (order.has(b.id) ? order.get(b.id) : 1e9)); - els.listActions.innerHTML = groups.length ? '' : ''; - const c = els.cards; - if (!groups.length) { - c.innerHTML = ` -
-
📝
-

No notes yet

-

While a video plays, open Chapters & bookmarks → 📝 Note (or press N) to write a note tied to that exact moment. They sync with your online profile.

-
`; - return; - } - const total = groups.reduce((n, g) => n + g.list.length, 0); - c.innerHTML = ` -
- - ${groups.map((g) => ` -
-
${escapeHtml(g.title)}${escapeHtml(g.channel)} · ${g.list.length}
- ${g.list.map((b) => ` - `).join('')} -
`).join('')} -
`; - c.querySelector('.nv-filter').addEventListener('input', (e) => { - const q = e.target.value.trim().toLowerCase(); - c.querySelectorAll('.nv-group').forEach((g) => { - let any = false; - g.querySelectorAll('.nv-item').forEach((it) => { const hit = !q || it.dataset.q.includes(q); it.classList.toggle('hidden', !hit); any = any || hit; }); - g.classList.toggle('hidden', !any); - }); - }); - c.querySelector('.nv-filter').addEventListener('keydown', (e) => e.stopPropagation()); - c.querySelectorAll('.nv-item').forEach((it) => it.addEventListener('click', () => { - const g = groups.find((x) => x.id === it.closest('.nv-group').dataset.id); - playVideoAt({ id: g.id, title: g.title, channel: g.channel }, Number(it.dataset.t)); - })); - const ex = $('notesExportBtn'); - if (ex) ex.addEventListener('click', () => { - const md = ['# YT Player notes', `_Exported ${new Date().toLocaleString()}_`, '']; - for (const g of groups) { - md.push(`## ${g.title}`, `${g.channel ? g.channel + ' · ' : ''}https://youtu.be/${g.id}`, ''); - for (const b of g.list) { - md.push(`- **[${LyricsCore.fmtClock(b.t)}](${location.origin}/?v=${g.id}&t=${Math.floor(b.t)})** ${b.title}`); - if (b.note && b.note !== b.title) md.push(...b.note.split('\n').map((l) => ` ${l}`)); - } - md.push(''); - } - const blob = new Blob([md.join('\n')], { type: 'text/markdown' }); - const a = document.createElement('a'); - a.href = URL.createObjectURL(blob); - a.download = `ytplayer-notes-${new Date().toISOString().slice(0, 10)}.md`; - a.click(); - setTimeout(() => URL.revokeObjectURL(a.href), 2000); - }); -} + // ============================================================================ // Timestamp sharing — deep links (/?v=ID&t=SEC) and GIFs of a moment @@ -7167,252 +6945,7 @@ const Gestures = (() => { * A folded card keeps its header, so it stays a landmark you can scroll to * and reopen. Fold state is per device and rides in settings. * ========================================================================== */ -const SectionRail = (() => { - const CLASSIC_ICONS = { - player: '', - meta: '', - notes: '', - related: '', - list: '', - }; - const SECTIONS = [ - { id: 'player', sel: '.player-stage', icon: '📺', label: 'Player' }, - { id: 'meta', sel: '#nowPlayingMeta', icon: '🎵', label: 'Now playing', fold: true }, - { id: 'notes', sel: '#notesPanel', icon: '📝', label: 'Lyrics', fold: true }, - { id: 'related', sel: '#relatedPanel', icon: '🔗', label: 'Related', fold: true }, - { id: 'list', sel: '#listPane', icon: '📋', label: 'List' }, - ]; - const st = { active: '', btns: new Map(), labelTimer: null, raf: 0, bottom: -1 }; - const rail = () => document.getElementById('sectionRail'); - const folds = () => (data.settings.foldedCards ||= {}); - const isFolded = (id) => !!folds()[id]; - const elOf = (s) => document.querySelector(s.sel); - // Only cards that are actually on screen belong in the rail. - const visible = () => SECTIONS.filter((s) => { - const el = elOf(s); - return el && !el.classList.contains('hidden') && el.offsetParent !== null; - }); - function applyFold(sec) { - const el = elOf(sec); - if (!el || !sec.fold) return; - el.classList.toggle('folded', isFolded(sec.id)); - if (sec.id === 'notes') { - const b = document.getElementById('notesFoldBtn'); - if (b) b.setAttribute('aria-expanded', String(!isFolded(sec.id))); - } - // The Related card already had its own +/− button; keep the two in step. - if (sec.id === 'related') { - relatedCollapsed = isFolded(sec.id); - const rl = document.getElementById('relatedList'); - const rb = document.getElementById('relatedToggleBtn'); - if (rl) rl.classList.toggle('hidden', relatedCollapsed); - if (rb) rb.textContent = relatedCollapsed ? '+' : '−'; - } - } - - function setFolded(id, on) { - const sec = SECTIONS.find((x) => x.id === id); - if (!sec || !sec.fold) return; - folds()[id] = !!on; - persist(); - applyFold(sec); - paint(); // NOT render() — folding a card must not rebuild the list - } - - function flashLabel(btn) { - clearTimeout(st.labelTimer); - [...st.btns.values()].forEach((b) => b.classList.remove('show-label')); - btn.classList.add('show-label'); - st.labelTimer = setTimeout(() => btn.classList.remove('show-label'), 1400); - } - - function onTap(sec, btn) { - const el = elOf(sec); - if (!el) return; - flashLabel(btn); - if (sec.id === 'player' || sec.id === 'meta') restoreNowPlayingList(); - if (st.active === sec.id && sec.fold) { - // Already here: this is the second tap — fold or unfold the card. - setFolded(sec.id, !isFolded(sec.id)); - if (isFolded(sec.id)) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); - return; - } - st.active = sec.id; // claim it now so the next tap folds - paint(); - el.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } - - function build() { - const r = rail(); - if (!r) return; - const items = visible(); - // A rail with one entry is noise; so is one on the empty home screen. - if (items.length < 2) { r.classList.add('hidden'); r.innerHTML = ''; st.btns.clear(); return; } - const key = items.map((s) => s.id).join(','); - if (r.dataset.key !== key) { - r.dataset.key = key; - r.innerHTML = ''; - st.btns.clear(); - for (const sec of items) { - const btn = document.createElement('button'); - btn.type = 'button'; - btn.className = 'sec-rail-btn'; - btn.dataset.sec = sec.id; - btn.setAttribute('aria-label', sec.label); - btn.innerHTML = `${escapeHtml(sec.label)}`; - btn.addEventListener('click', () => onTap(sec, btn)); - r.appendChild(btn); - st.btns.set(sec.id, btn); - } - } - r.classList.remove('hidden'); - placeRail(); - paint(); - } - - // The page does NOT scroll the document: `.player-pane` is the scroller in - // the browser, but the installed PWA in portrait scrolls `.body` instead - // (`.player-pane` goes overflow:visible there). So find the real scroller - // rather than assuming one. - function scrollerOf(el) { - for (let e = el && el.parentElement; e; e = e.parentElement) { - const cs = getComputedStyle(e); - if (/(auto|scroll)/.test(cs.overflowY) && e.scrollHeight > e.clientHeight + 4) return e; - } - return document.scrollingElement || document.documentElement; - } - - // The visible box to measure against — the scroller's own rect, or the - // window when the document itself scrolls. - function viewBox() { - const first = elOf(visible()[0] || SECTIONS[0]); - const sc = scrollerOf(first); - if (!sc || sc === document.scrollingElement || sc === document.documentElement) { - return { top: 0, height: window.innerHeight }; - } - const r = sc.getBoundingClientRect(); - return { top: r.top, height: r.height }; - } - - // Which card is the reader looking at? The one whose top is closest to a - // line a third of the way down the visible box — steadier than "first - // visible", which flickers between two cards at a boundary. - function currentId() { - const items = visible(); - if (!items.length) return ''; - const box = viewBox(); - const line = box.top + box.height / 3; - let best = '', bestD = Infinity; - let near = items[0].id, nearD = Infinity; // fallback: closest card overall - for (const sec of items) { - const el = elOf(sec); - if (!el) continue; - const r = el.getBoundingClientRect(); - const d = Math.abs(r.top - line); - // Distance to the visible band, for the fallback below. - const outside = Math.max(box.top - r.bottom, r.top - (box.top + box.height), 0); - if (outside < nearD || (outside === nearD && d < bestD)) { nearD = outside; near = sec.id; } - if (r.bottom < box.top || r.top > box.top + box.height) continue; - if (d < bestD) { bestD = d; best = sec.id; } - } - // Scrolled past the last card (or a card is taller than the viewport and - // its top has gone by): never leave the rail with nothing highlighted. - return best || near; - } - - // The mini player and the bottom nav are both position:fixed bottom:0, and - // either can be absent (nothing playing / landscape). Measure whatever is - // actually pinned down there and park the rail above it, rather than - // guessing an offset that is wrong on the next phone. - function placeRail() { - const r = rail(); - let occupied = 0; - for (const id of ['bottomNav', 'miniBar']) { - const el = document.getElementById(id); - if (!el || el.classList.contains('hidden')) continue; - const box = el.getBoundingClientRect(); - if (!box.height) continue; - if (getComputedStyle(el).position !== 'fixed') continue; - // Count any fixed bar sitting in the lower half. It must NOT be required - // to touch the viewport bottom: on an iPhone XR the bottom nav ends - // above the home-indicator gap, so a "bottom >= innerHeight" test missed - // it entirely and the rail was parked underneath it. - if (box.top > window.innerHeight * 0.5) occupied = Math.max(occupied, window.innerHeight - box.top); - } - // 14px was too tight: the mini player is a floating CARD with a shadow and - // rounded corners, so its visual edge reads higher than its box. - const want = Math.round(occupied + 24); - if (st.bottom !== want) { - st.bottom = want; - if (r) r.style.setProperty('--rail-bottom', want + 'px'); - // Published for anything else that must sit above the bottom bars — - // the watch-party panel's leave button was hidden behind them. - document.documentElement.style.setProperty('--bottom-chrome', Math.round(occupied) + 'px'); - } - } - - function paint() { - for (const [id, btn] of st.btns) { - btn.classList.toggle('active', id === st.active); - btn.classList.toggle('folded', isFolded(id)); - } - } - - function onScroll() { - if (st.raf) return; - st.raf = requestAnimationFrame(() => { - st.raf = 0; - // Panels appear and disappear outside render() too (the Related card - // shows once a video's related list arrives), and a card with no icon - // would leave the rail with nothing highlighted. build() is a no-op - // unless the set of visible cards actually changed. - build(); - placeRail(); - const id = currentId(); - if (id && id !== st.active) { st.active = id; paint(); } - }); - } - - function boot() { - const fb = document.getElementById('notesFoldBtn'); - if (fb) fb.addEventListener('click', () => setFolded('notes', !isFolded('notes'))); - SECTIONS.forEach(applyFold); - // Scroll events from an element do NOT bubble, so a window listener never - // fires here. A capture-phase listener on document catches them all, and - // keeps working when the scroller changes between browser and installed - // PWA (different elements scroll in each). - document.addEventListener('scroll', onScroll, { passive: true, capture: true }); - window.addEventListener('resize', () => { build(); placeRail(); onScroll(); }); - // The mini player appears AFTER the scroll that reveals it, so a scroll - // handler alone measures the layout as it was a moment ago and parks the - // rail underneath it. Watch the two bottom bars for real. - const watch = ['bottomNav', 'miniBar'].map((id) => document.getElementById(id)).filter(Boolean); - if (watch.length && typeof MutationObserver !== 'undefined') { - // The mini bar slides in over 0.25s, so a measurement taken the instant - // it appears catches it mid-animation and lands the rail a few pixels - // too low. Measure now and again once it has settled. - const mo = new MutationObserver(() => { placeRail(); setTimeout(placeRail, 320); }); - watch.forEach((el) => mo.observe(el, { attributes: true, attributeFilter: ['class', 'style'] })); - } - if (watch.length && typeof ResizeObserver !== 'undefined') { - const ro = new ResizeObserver(() => placeRail()); - watch.forEach((el) => ro.observe(el)); - } - build(); - onScroll(); - } - - // Called from render(): cards appear and disappear as videos load. - function refresh() { - SECTIONS.forEach(applyFold); - build(); - placeRail(); - onScroll(); - } - - return { boot, refresh, setFolded, isFolded }; -})(); const External = (() => { const isAndroid = /Android/i.test(navigator.userAgent); @@ -7987,17 +7520,7 @@ function updateProgress() { // Height of the fixed bars at the bottom (bottom nav, mini player) as CSS // --bottom-chrome, so lists can scroll their last card clear of them. Measured, // never guessed: the mini player comes and goes, and phones differ. -function updateBottomChrome() { - let occupied = 0; - for (const id of ['bottomNav', 'miniBar']) { - const el = document.getElementById(id); - if (!el || el.classList.contains('hidden')) continue; - const box = el.getBoundingClientRect(); - if (!box.height || getComputedStyle(el).position !== 'fixed') continue; - if (box.top > window.innerHeight * 0.5) occupied = Math.max(occupied, window.innerHeight - box.top); - } - document.documentElement.style.setProperty('--bottom-chrome', Math.round(occupied) + 'px'); -} + window.addEventListener('resize', () => requestAnimationFrame(updateBottomChrome)); window.addEventListener('orientationchange', () => setTimeout(updateBottomChrome, 300)); @@ -8005,48 +7528,11 @@ window.addEventListener('orientationchange', () => setTimeout(updateBottomChrome // board / hero) over the player pane, using the same look as "nothing playing" // (.empty). The media keeps playing — it is only made invisible, never removed // or paused — and the mini bar stays up to get back to it. -function setHomeOverPlayer(on) { - const pane = els.playerPane; - if (!pane) return; - on = !!on && !!(current && current.meta); - // Service mode hides the bottom bar and mini bar (and, in its Video view, - // lives inside this pane): leave it first or the home screen is a dead end. - if (on && isServiceModeOpen()) exitServiceMode(); - if (pane.classList.contains('home-over') === on) return; - pane.classList.toggle('home-over', on); - pane.classList.toggle('empty', on); - if (els.placeholder) els.placeholder.classList.toggle('hidden', !on); - if (on) { - renderHomePlaylists(); - showMiniBar(); - const body = document.querySelector('.body'); - if (body) body.scrollTo({ top: 0 }); - } -} -function showMiniBar() { - if (!current || !current.meta) return; - $('miniTitle').textContent = current.meta.title; - const miniCh = $('miniChannel'); - miniCh.textContent = current.meta.channel || ''; - miniCh.classList.toggle('link', !!channelKeyOf(current.meta)); - $('miniBar').classList.remove('hidden'); - updateMiniBar(); - requestAnimationFrame(updateBottomChrome); -} -function updateMiniBar() { - if (!current || !current.meta) return; - const cur = Player.master.currentTime || 0; - const dur = Player.master.duration || 0; - $('miniTime').textContent = fmtTime(cur); - if (dur > 0) { - $('miniProgressFill').style.width = Math.min(100, (cur / dur) * 100) + '%'; - } -} -function hideMiniBar() { - $('miniBar').classList.add('hidden'); - requestAnimationFrame(updateBottomChrome); -} + + + + // ============================================================================ // History @@ -8694,109 +8180,18 @@ function channelKeyOf(v) { // ============================================================================ // Rendering // ============================================================================ -function renderSidebar() { - els.playlistList.innerHTML = ''; - for (const pl of data.playlists) { - const stats = playlistOfflineStats(pl); - let offlineBadge = ''; - if (stats.total > 0) { - if (stats.cached === stats.total) { - offlineBadge = `⬇`; - } else if (stats.cached > 0) { - offlineBadge = `${stats.cached}/${stats.total}`; - } - } - const item = document.createElement('div'); - item.className = 'playlist-item' + (view.type === 'playlist' && view.id === pl.id ? ' active' : ''); - item.innerHTML = `${offlineBadge}${pl.videos.length}`; - item.querySelector('.pl-name').textContent = pl.name; - item.addEventListener('click', () => { view = { type: 'playlist', id: pl.id }; render(); }); - els.playlistList.appendChild(item); - } - document.querySelectorAll('.nav-item').forEach((b) => { - b.classList.toggle('active', b.dataset.view === view.type); - }); - // Keep bottom-nav in sync with sidebar nav active state - document.querySelectorAll('.bottom-nav-btn').forEach((b) => { - b.classList.toggle('active', b.dataset.view === view.type); - }); - updateQueueBadge(); - updateDownloadBadge(); - renderHomePlaylists(); -} + // The empty player pane (nothing playing yet) shows the branding hero. Once // this device has playlists, they take that space instead — the hero stays as // the fallback so a first-time visitor still gets the landing. // Driven from renderSidebar() so every playlist mutation refreshes both. -function renderHomePlaylists() { - if (window.BentoHub) BentoHub.playlists = () => data.playlists || []; - const wrap = document.getElementById('homePlaylists'); - const hero = document.querySelector('#playerPlaceholder .hero'); - const grid = document.getElementById('homePlGrid'); - if (!wrap || !hero || !grid) return; - Recommendations.home(); - const lists = data.playlists || []; - wrap.classList.toggle('hidden', !lists.length); - hero.classList.toggle('hidden', !!lists.length); - // The hero is centered art; the grid wants the full box, so the placeholder - // switches from centering to stretching (and tightens its padding), and the - // stage drops its 16:9 lock so the grid gets the pane's real height. - if (els.placeholder) els.placeholder.classList.toggle('showing-playlists', !!lists.length); - if (els.playerPane) els.playerPane.classList.toggle('home-playlists', !!lists.length); - if (!lists.length) { grid.innerHTML = ''; return; } - - grid.innerHTML = ''; - for (const pl of lists) { - const count = pl.videos.length; - const thumb = (pl.videos.find((v) => v && v.thumbnail) || {}).thumbnail || ''; - const stats = playlistOfflineStats(pl); - let offlineHtml = ''; - if (stats.total > 0) { - if (stats.cached === stats.total) { - offlineHtml = `⬇`; - } else if (stats.cached > 0) { - offlineHtml = `${stats.cached}/${stats.total}`; - } - } - const card = document.createElement('button'); - card.className = 'home-pl-card'; - card.type = 'button'; - card.innerHTML = ` - - ${thumb ? `` - : '🎵'} - ${offlineHtml} - ▶ - - - ${count} video${count === 1 ? '' : 's'}`; - card.querySelector('.home-pl-name').textContent = pl.name; - card.title = pl.name; - card.addEventListener('click', () => { view = { type: 'playlist', id: pl.id }; render(); }); - card.querySelector('.home-pl-play').addEventListener('click', (e) => { - e.stopPropagation(); // the ▶ badge plays; the rest of the card opens the list - if (count) playFromList(pl.videos, 0, 'playlist:' + pl.id); - else toast('That playlist is empty'); - }); - grid.appendChild(card); - } - // Measure after layout — scrollHeight is meaningless until the cards lay out. - requestAnimationFrame(updateHomeGridScrollState); -} // With enough playlists the grid still has to scroll. Flag when it genuinely // overflows (and whether it's at the end) so the CSS fades the bottom edge // instead of slicing the last row against a hard border. -function updateHomeGridScrollState() { - const grid = document.getElementById('homePlGrid'); - if (!grid) return; - const overflows = grid.scrollHeight > grid.clientHeight + 1; - grid.classList.toggle('is-scrollable', overflows); - grid.classList.toggle('at-end', !overflows || - grid.scrollTop + grid.clientHeight >= grid.scrollHeight - 2); -} + function currentList() { if (view.type === 'nowPlaying') return queue; @@ -8812,306 +8207,25 @@ function currentList() { return []; } -function showSearchSkeletons() { - // A search is in flight — the pane is about to have results, so reveal it - // now rather than popping in only once they land. - setListPaneHidden(false); - els.status.classList.add('hidden'); - els.cards.innerHTML = ''; - for (let i = 0; i < 8; i++) { - const s = document.createElement('div'); - s.className = 'card skeleton-card'; - s.innerHTML = ` -
-
-
-
-
-
`; - els.cards.appendChild(s); - } -} + // Before the first search the list pane has nothing to say but "Search for // something to begin" — hide it outright so the playlist board (or the hero) // owns the full width on a fresh launch. Any search or view change brings it // back. Must run before the early returns below, which skip the rest. -function setListPaneHidden(hidden) { - const pane = document.getElementById('listPane'); - if (pane) pane.classList.toggle('hidden', hidden); -} + // Small icon-only button for the playlist title row and the filter row. -const LIST_ICONS = { - rename: '', - share: '', - offline: '', - offlineDone: '', - pin: '', - select: '', - del: '', -}; -function listIconBtn(icon, label, onClick, extraClass) { - const b = document.createElement('button'); - b.type = 'button'; - b.className = 'list-icon-btn' + (extraClass ? ' ' + extraClass : ''); - b.title = label; - b.setAttribute('aria-label', label); - b.innerHTML = ``; - if (onClick) b.onclick = onClick; - return b; -} -function setListIcon(btn, icon) { - btn.innerHTML = ``; -} + + + // Drop the playlist-only title/filter icons so they never linger on other views. -function resetListHeaderExtras() { - $('listTitleActions').innerHTML = ''; - const fa = $('listFilterActions'); - fa.innerHTML = ''; - fa._del = null; - els.listTitle.onclick = null; - els.listTitle.onkeydown = null; - els.listTitle.classList.remove('title-clickable'); - els.listTitle.removeAttribute('role'); - els.listTitle.removeAttribute('tabindex'); - els.listTitle.removeAttribute('title'); -} -function renderList() { - // Theme composition follows the real view without changing its controls. - els.cards.dataset.view = view.type; - resetListHeaderExtras(); - { const ls = $('listSub'); if (ls) ls.textContent = ''; const ps = $('p2pStrip'); if (ps) ps.classList.add('hidden'); } - if (view.type !== 'search') { const sm = $('searchMeta'); if (sm) sm.classList.add('hidden'); } - setListPaneHidden(view.type === 'search' && !searchResults.length && !searchAttempted && !els.placeholder.classList.contains('hidden')); - if (view.type === 'settings') { renderSettings(); return; } - if (view.type === 'saved') { renderSaved(); return; } - if (view.type === 'p2p') { renderP2pList(); return; } - if (view.type === 'savedSearches') { renderSavedSearches(); return; } - if (view.type === 'downloads') { renderDownloads(); return; } - if (view.type === 'stats') { renderStats(); return; } - if (view.type === 'notes') { renderNotesView(); return; } - if (view.type === 'library') { renderLibrary(); return; } - // Filter bar — show for filterable views - const filterableViews = ['history', 'playlist', 'queue', 'channel', 'smart', 'nowPlaying']; - const showFilter = filterableViews.includes(view.type); - $('listFilterBar').classList.toggle('hidden', !showFilter); - $('batchBar').classList.toggle('hidden', !selectMode); - if (selectMode) $('batchCount').textContent = `${selectedIds.size} selected`; - // A channel's videos can be queued or added to a playlist, not deleted. - $('batchDeleteBtn').classList.toggle('hidden', view.type === 'channel'); - // Build the list, applying filter if active - let list = currentList(); - if (listFilter && showFilter) { - const q = listFilter.toLowerCase(); - list = list.filter((v) => (v.title || '').toLowerCase().includes(q) || (v.channel || '').toLowerCase().includes(q)); - } - els.cards.innerHTML = ''; - els.cards.classList.toggle('select-mode', selectMode); - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - if (view.type === 'search' && WEB && els.placeholder.classList.contains('hidden')) { - Recommendations.inList(); - } - - if (view.type === 'nowPlaying') { - els.listTitle.textContent = 'Now playing'; - } else if (view.type === 'search') { - els.listTitle.textContent = 'Search results'; - } else if (view.type === 'history') { - els.listTitle.textContent = 'History'; - if (list.length) { - const clear = document.createElement('button'); - clear.textContent = 'Clear'; - clear.onclick = () => { data.history = []; persist(); renderList(); }; - els.listActions.appendChild(clear); - } - } else if (view.type === 'queue') { - els.listTitle.textContent = 'Queue'; - if (list.length) { - const playAll = document.createElement('button'); - playAll.textContent = '▶ Play queue'; - playAll.onclick = () => playQueue(0); - const clear = document.createElement('button'); - clear.textContent = 'Clear'; - clear.onclick = clearQueue; - els.listActions.append(playAll, clear); - } - } else if (view.type === 'smart') { - const sp = SMART_PLAYLISTS.find((s) => s.id === view.smartType); - els.listTitle.textContent = sp ? sp.label : 'Auto Playlist'; - if (list.length) { - const playAll = document.createElement('button'); - playAll.textContent = '▶ Play all'; - playAll.onclick = () => playFromList(list.slice(), 0, 'smart:' + view.smartType); - const queueAll = document.createElement('button'); - queueAll.textContent = '+ Queue all'; - queueAll.onclick = () => { list.forEach((v) => addToQueue(v, { quiet: true })); toast('Added to queue'); }; - els.listActions.append(playAll, queueAll); - } - } else if (view.type === 'channel') { - els.listTitle.textContent = channelData.name || 'Channel'; - if (list.length) { - const playAll = document.createElement('button'); - playAll.textContent = '▶ Play all'; - playAll.onclick = () => playFromList(channelData.results.slice(), 0, 'channel'); - const queueAll = document.createElement('button'); - queueAll.textContent = '+ Queue all'; - queueAll.onclick = () => { channelData.results.forEach((v) => addToQueue(v, { quiet: true })); toast('Added channel to queue'); }; - els.listActions.append(playAll, queueAll); - } - } else if (view.type === 'playlist') { - const pl = data.playlists.find((p) => p.id === view.id); - els.listTitle.textContent = pl ? pl.name : 'Playlist'; - if (pl) { - { const secs = (pl.videos || []).reduce((a, v) => a + (Number(v.duration) || 0), 0); - const h = Math.floor(secs / 3600), m = Math.round((secs % 3600) / 60); - $('listSub').textContent = `${pl.videos.length} track${pl.videos.length === 1 ? '' : 's'}${secs ? ' · ' + (h ? h + 'h ' : '') + m + 'm' : ''}`; } - renderP2pStrip(); - const playAll = document.createElement('button'); - playAll.textContent = '▶ Play all'; - playAll.className = 'la-primary'; - playAll.onclick = () => { if (pl.videos.length) playFromList(pl.videos, 0, 'playlist:' + pl.id); }; - const playFull = document.createElement('button'); - playFull.textContent = '▶ Play in full'; - playFull.className = 'la-main'; - playFull.dataset.sub = 'Start to finish'; - playFull.title = 'Play every video start to finish — ignores saved positions and A-B loops, stops after the last one'; - playFull.onclick = () => { - if (!pl.videos.length) return; - playFromList(pl.videos, 0, 'playlist:' + pl.id, { playFull: true }); - toast('Playing in full — stops after the last video'); - }; - const serviceBtn = document.createElement('button'); - serviceBtn.textContent = '🎤 Service mode'; - serviceBtn.className = 'la-main'; - serviceBtn.dataset.sub = 'Full lyrics'; - serviceBtn.title = 'Set-list view with screen wake lock'; - serviceBtn.onclick = () => { - if (!pl.videos || !pl.videos.length) { toast('Playlist is empty'); return; } - enterServiceMode(pl); - }; - const queueAll = document.createElement('button'); - queueAll.textContent = '+ Queue'; - queueAll.className = 'la-main'; - queueAll.dataset.sub = `+${pl.videos.length} items`; - queueAll.onclick = () => { pl.videos.forEach((v) => addToQueue(v, { quiet: true })); toast('Added playlist to queue'); }; - // Title row: a long name wraps; tapping it opens the rename modal, - // which also shows the full name. Rename + Share sit beside it as icons. - els.listTitle.classList.add('title-clickable'); - els.listTitle.setAttribute('role', 'button'); - els.listTitle.tabIndex = 0; - els.listTitle.title = 'Show full name / rename'; - els.listTitle.onclick = () => renamePlaylist(pl); - els.listTitle.onkeydown = (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); renamePlaylist(pl); } }; - const titleIcons = [listIconBtn('rename', 'Rename playlist', () => renamePlaylist(pl))]; - if (pl.videos && pl.videos.length >= 1) titleIcons.push(listIconBtn('share', 'Share playlist', () => sharePlaylist(pl))); - $('listTitleActions').append(...titleIcons); - - // Filter row icons: offline + pin show their state by colour alone. - const offlineBtn = listIconBtn('offline', 'Make available offline', () => makePlaylistOffline(pl)); - offlineBtn.id = 'plOfflineBtn'; - updatePlaylistOfflineButton(offlineBtn, pl); - - const isPinned = (data.pinnedPlaylists || []).includes(pl.id); - const pinBtn = listIconBtn('pin', isPinned ? 'Pinned for offline keep — tap to unpin' : 'Pin to keep this playlist available offline', () => togglePinPlaylist(pl)); - pinBtn.id = 'plPinBtn'; - pinBtn.classList.toggle('pinned', isPinned); - pinBtn.setAttribute('aria-pressed', String(isPinned)); - - const del = listIconBtn('del', 'Delete playlist', () => deletePlaylist(pl), 'danger'); - $('listFilterActions').append(offlineBtn, pinBtn); - els.listActions.append(playAll, playFull, serviceBtn, queueAll); - $('listFilterActions')._del = del; // appended after Select below - } - } - - // Select button for batch-operable views - const batchViews = ['history', 'playlist', 'queue', 'smart', 'channel']; - if (batchViews.includes(view.type) && list.length) { - const selBtn = listIconBtn('select', selectMode ? 'Stop selecting' : 'Select items', toggleSelectMode); - selBtn.classList.toggle('pinned', selectMode); - selBtn.setAttribute('aria-pressed', String(selectMode)); - $('listFilterActions').appendChild(selBtn); - } - { const fa = $('listFilterActions'); if (fa._del) { fa.appendChild(fa._del); fa._del = null; } } - - // Channel still loading — show skeletons. - if (view.type === 'channel' && channelData.loading && !list.length) { - showSearchSkeletons(); - return; - } - - if (!list.length) { - els.status.classList.add('hidden'); - els.cards.innerHTML = ''; - const empty = document.createElement('div'); - empty.className = 'empty-state'; - - if (view.type === 'search') { - // Landing (hero or playlist board) lives in the player pane. Before the - // first search this pane is hidden outright; after one that came back - // empty it stays visible so the result is legible. - els.status.classList.remove('hidden'); - els.status.textContent = searchAttempted - ? 'No results for that search.' - : 'Search for something to begin.'; - return; - } - - if (view.type === 'history') { - empty.innerHTML = ` -
🕘
-

Nothing watched yet

-

Your viewing history shows up here once you start playing videos.

- `; - addBrowseCta(empty, '🔍 Search videos'); - } else if (view.type === 'queue') { - empty.innerHTML = ` -
▶
-

Your queue is empty

-

Use + Queue on any video to line it up. The queue is temporary and plays in order.

- `; - addBrowseCta(empty, '🔍 Find something to play'); - } else if (view.type === 'channel') { - empty.innerHTML = ` -
📺
-

No videos found

-

This channel didn't return any uploads.

- `; - addBrowseCta(empty, '🔍 Back to search'); - } else { - // Playlist view — empty - empty.innerHTML = ` -
🎵
-

This playlist is empty

-

Add videos from search results or use the + Playlist button while playing.

- `; - addBrowseCta(empty, '🔍 Browse videos'); - } - - els.cards.appendChild(empty); - return; - } - els.status.classList.add('hidden'); - - list.forEach((v, i) => els.cards.appendChild(renderCard(v, i, list))); - markPlayingCard(); -} - -function addBrowseCta(empty, label) { - const cta = document.createElement('button'); - cta.className = 'empty-cta'; - cta.textContent = label; - cta.addEventListener('click', () => { view = { type: 'search' }; render(); }); - empty.appendChild(cta); -} // ============================================================================ // Saved videos page — every offline-cached file with sizes + totals @@ -9235,314 +8349,23 @@ async function exportToDevice(video) { // Glass Stage: a compact "On other devices" card under a playlist (same data as the 📡 view). let p2pStripAt = 0, p2pStripData = null; -async function renderP2pStrip() { - const box = $('p2pStrip'); - if (!box || document.documentElement.dataset.layout !== 'glass-stage' || !WEB || data.settings.p2pReceive === false) return; - if (!p2pStripData || Date.now() - p2pStripAt > 60000) { - try { const r = await fetch('/api/p2p/available?limit=3'); p2pStripData = r.ok ? await r.json() : null; } catch { p2pStripData = null; } - p2pStripAt = Date.now(); - } - if (view.type !== 'playlist') return; - const items = (p2pStripData && p2pStripData.ok && p2pStripData.items) || []; - if (!items.length) { box.classList.add('hidden'); return; } - const online = items.filter((i) => i.online).length; - box.innerHTML = `
On other devices
-

${items.length} video${items.length === 1 ? '' : 's'} held by other devices · ${online ? online + ' online now' : 'none online'}

`; - items.forEach((it) => { - const v = { id: it.id, title: it.title || videoTitleById(it.id) || it.id, channel: it.channel || '', duration: it.duration || 0, thumbnail: `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg` }; - const row = document.createElement('div'); - row.className = 'ps-row'; - row.innerHTML = '📡'; - row.querySelector('b').textContent = v.title; - row.querySelector('small').textContent = `${fmtBytes(it.size)}${it.height ? ' · ' + it.height + 'p' : ''} · ${it.online ? 'Online' : 'Offline'}`; - row.querySelector('.ps-dl').onclick = () => exportToDevice(v); - row.querySelector('.ps-txt').onclick = () => playFromList([v], 0, 'p2p'); - box.appendChild(row); - }); - box.classList.remove('hidden'); -} + // ============================================================================ // Saved searches — browse (read-only here; deleting happens in Settings) // ============================================================================ -function fmtAgo(ts) { - const s = Math.max(0, (Date.now() - ts) / 1000); - if (s < 90) return 'just now'; - if (s < 3600) return Math.round(s / 60) + ' min ago'; - if (s < 86400) return Math.round(s / 3600) + ' h ago'; - return Math.round(s / 86400) + ' d ago'; -} -function renderSavedSearches() { - els.listTitle.textContent = '📚 Saved searches'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - const c = els.cards; - c.innerHTML = ''; - const items = SearchLibrary.list(); - if (!items.length) { - c.innerHTML = '
📚

No saved searches yet

Every search you run is kept here with its thumbnails, even after you clear the search box. You can remove them in Settings.

'; - return; - } - const sum = document.createElement('div'); - sum.className = 'saved-summary'; - sum.innerHTML = `${items.length}saved search${items.length === 1 ? '' : 'es'} · ${fmtBytes(SearchLibrary.bytes())} · manage in Settings`; - c.appendChild(sum); - items.forEach((it) => { - const row = document.createElement('div'); - row.className = 'card saved-card ss-card'; - row.innerHTML = ` -
-
${it.count} result${it.count === 1 ? '' : 's'} · ${fmtAgo(it.ts)}
`; - row.querySelector('.card-title').textContent = it.query; - row.addEventListener('click', () => { - els.searchInput.value = it.query; - if (els.runSearch) els.runSearch(it.query); - }); - c.appendChild(row); - }); -} - -async function renderP2pList() { - els.listTitle.textContent = '📡 On other devices'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - const c = els.cards; - c.innerHTML = '
Looking for videos on other devices…
'; - let res = null; - try { const r = await fetch('/api/p2p/available?limit=100'); res = r.ok ? await r.json() : null; } catch { /* offline */ } - if (view.type !== 'p2p') return; - c.innerHTML = ''; - if (!res || !res.ok) { - c.innerHTML = '
📡

Not available

Peer-to-peer sharing is off on this server, or you are offline.

'; - return; - } - const items = res.items || []; - const list = items.map((it) => ({ - id: it.id, title: it.title || videoTitleById(it.id) || it.id, channel: it.channel || '', - duration: it.duration || 0, thumbnail: `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg`, - })); - const refresh = document.createElement('button'); - refresh.textContent = '↻'; - refresh.className = 'la-icon'; - refresh.title = 'Refresh'; - refresh.setAttribute('aria-label', 'Refresh'); - refresh.onclick = () => renderP2pList(); - const playAll = document.createElement('button'); - playAll.textContent = '▶ Play all'; - playAll.className = 'la-primary la-inline'; - playAll.onclick = () => { if (list.length) playFromList(list, 0, 'p2p'); }; - els.listActions.append(playAll, refresh); - if (!items.length) { - c.innerHTML = '
📡

Nothing shared yet

Videos that other devices have saved and verified show up here. Save a video and keep sharing on, and yours will appear for everyone else.

'; - return; - } - const online = items.filter((i) => i.online).length; - const sum = document.createElement('div'); - sum.className = 'saved-summary'; - sum.innerHTML = `${items.length}video${items.length === 1 ? '' : 's'} on other devices · ${online} with a device online now`; - c.appendChild(sum); - items.forEach((it, idx) => { - const v = list[idx]; - const row = document.createElement('div'); - row.className = 'card saved-card p2p-card'; - row.dataset.id = it.id; - const state = it.online ? `● ${it.online} online` : '○ none online'; - row.innerHTML = ` -
-
-
-
${state} · ${it.holders} device${it.holders === 1 ? '' : 's'} · ${fmtBytes(it.size)}${it.height ? ' · ' + it.height + 'p' : ''}${it.stale ? ' · not checked lately' : ''}
-
- - `; - row.querySelector('.card-title').textContent = v.title; - row.addEventListener('click', (e) => { - const act = e.target.closest('[data-act]'); - if (act) { e.stopPropagation(); if (act.dataset.act === 'export') exportToDevice(v); else openCardMenu(v); return; } - playFromList(list, idx, 'p2p'); - }); - c.appendChild(row); - }); - markPlayingCard(); -} - -async function renderSaved() { - els.listTitle.textContent = 'Saved videos'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - $('batchBar').classList.add('hidden'); - const c = els.cards; - c.classList.remove('select-mode'); - c.innerHTML = '
Loading saved videos…
'; - - let res; - try { res = await API.cacheList(); } catch { res = null; } - if (view.type !== 'saved') return; // navigated away - - if (!res || !res.ok) { - $('listFilterBar').classList.add('hidden'); - c.innerHTML = ''; - const empty = document.createElement('div'); - empty.className = 'empty-state'; - empty.innerHTML = ` -
💾
-

Offline cache unavailable

-

This build doesn't support saving videos for offline playback.

`; - c.appendChild(empty); - return; - } - - const items = (res.items || []).slice().sort((a, b) => b.size - a.size); - const total = res.total || 0; - - if (!items.length) { - $('listFilterBar').classList.add('hidden'); - c.innerHTML = ''; - const empty = document.createElement('div'); - empty.className = 'empty-state'; - empty.innerHTML = ` -
💾
-

Nothing saved yet

-

Use ⬇ Save while playing, or add videos to a playlist to keep them offline.

`; - addBrowseCta(empty, '🔍 Find videos'); - c.appendChild(empty); - return; - } - - // Header actions: total + clear all. - const clearAll = document.createElement('button'); - clearAll.type = 'button'; - clearAll.className = 'saved-clear'; - clearAll.textContent = 'Clear all'; - clearAll.setAttribute('aria-label', 'Clear all saved videos'); - clearAll.onclick = () => { - showModal('Clear all saved videos?', document.createTextNode('Frees disk space. Normal videos re-download on demand, but edited videos are removed for good (they exist only here).'), [ - { label: 'Cancel', onClick: closeModal }, - { label: 'Clear all', danger: true, onClick: async () => { - try { - const result = await API.cacheClear(); - if (result?.ok === false) throw new Error(result.error || 'Storage could not be cleared'); - } catch { toast('Could not clear saved videos. Try again.'); closeModal(); return; } - cachedIds.clear(); - // Custom cuts live only in the cache — clearing it destroys their media, - // so drop their registry entries and playlist references too. - const customIds = new Set((data.customVideos || []).map((v) => v.id)); - if (customIds.size) { - data.customVideos = []; - data.playlists.forEach((pl) => { pl.videos = pl.videos.filter((x) => !customIds.has(x.id)); }); - data.queue = (data.queue || []).filter((x) => !customIds.has(x.id)); - persist(); - } - closeModal(); - toast('Cache cleared'); - if (current) updateNowPlayingActions(); - renderSaved(); - } }, - ]); - }; - c.innerHTML = ''; - const summary = document.createElement('div'); - summary.className = 'saved-summary saved-storage-summary'; - summary.innerHTML = `${fmtBytes(total)} · ${items.length} video${items.length === 1 ? '' : 's'} stored offline`; - summary.appendChild(clearAll); - $('listFilterBar').classList.remove('hidden'); - c.appendChild(summary); - items.forEach((it) => { - const known = videoById(it.id); - // A custom (edited) id has no YouTube thumbnail; fall back to its source's - // thumbnail when we know it, else a neutral placeholder. - const isCustom = (known && known.custom) || String(it.id).startsWith('edit_'); - const fallbackThumb = isCustom ? '' : `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg`; - const v = known || { id: it.id, title: videoTitleById(it.id), thumbnail: fallbackThumb }; - if (!SavedPage.matches(v, listFilter)) return; - const row = document.createElement('div'); - row.className = 'card saved-card' + (isCustom ? ' custom' : ''); - row.dataset.id = it.id; - row.innerHTML = ` -
${isCustom ? '✂' : ''}${isUploadId(v.id) ? `${v.kind === 'audio' ? '♪' : '📁'}` : ''}
-
-
-
${isCustom ? '✂ edited · ' : ''}${fmtBytes(it.size)}
-
`; - row.querySelector('.card-title').textContent = v.title || it.id; - row.addEventListener('click', (e) => { - if (e.target.closest('.saved-file-actions')) return; - playFromList([v], 0, 'saved'); - }); - SavedPage.actions(row, v, () => exportToDevice(v), () => { - showModal(`Delete saved file “${v.title || v.id}”?`, document.createTextNode(isCustom - ? 'This edited copy exists only on this device and will be removed permanently.' - : 'Frees space on this device. You can save this video again later.'), [ - { label: 'Cancel', onClick: closeModal }, - { label: 'Delete saved file', danger: true, onClick: async () => { - try { - const result = await API.cacheDelete(it.id); - if (result?.ok === false) throw new Error(result.error || 'Storage could not be updated'); - } catch { toast('Could not delete this saved file. Try again.'); closeModal(); return; } - cachedIds.delete(it.id); - if (isCustom) { - data.customVideos = (data.customVideos || []).filter(x => x.id !== it.id); - data.playlists.forEach(pl => { pl.videos = pl.videos.filter(x => x.id !== it.id); }); - data.queue = (data.queue || []).filter(x => x.id !== it.id); - persist(); - } - if (current?.meta?.id === it.id) updateNowPlayingActions(); - markCardCacheState(it.id, 'none'); closeModal(); - toast('Removed saved file'); renderSaved(); - } }, - ]); - }); - c.appendChild(row); - }); - if (!c.querySelector('.saved-card')) { - const message = document.createElement('p'); message.className = 'status'; - message.textContent = 'No saved videos match your filter.'; c.appendChild(message); - } - markPlayingCard(); -} + + + // ============================================================================ // Downloads page — videos currently being saved // ============================================================================ -function renderDownloads() { - els.listTitle.textContent = 'Downloads'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - const c = els.cards; - c.innerHTML = ''; - $('listFilterBar').classList.toggle('hidden', !Downloads.getJobs().length); - $('batchBar').classList.add('hidden'); - c.classList.remove('select-mode'); - if (window.DownloadsPage && window.DownloadsPage.render) { - window.DownloadsPage.render(c, { - downloadsApi: window.Downloads, - filter: listFilter, - isActive: () => view.type === 'downloads', - showModal: typeof showModal === 'function' ? showModal : null, - closeModal: typeof closeModal === 'function' ? closeModal : null, - onNavigateSaved: () => { view = { type: 'saved' }; render(); }, - thumbUrlFor: typeof thumbUrlFor === 'function' ? thumbUrlFor : null, - refresh: renderList - }); - } - - const jobs = window.Downloads && window.Downloads.getJobs ? window.Downloads.getJobs() : []; - jobs.filter(j => j.status === 'active' || j.status === 'queued').forEach(v => { - if (typeof SaveQueue !== 'undefined' && SaveQueue.progress) { - SaveQueue.progress(v.id, SaveQueue.get(v.id)); - } - }); -} // ============================================================================ // Settings page @@ -9567,767 +8390,11 @@ function videoTitleById(id) { return v ? v.title : id; } -async function renderSettings() { - els.listTitle.textContent = 'Settings'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - const c = els.cards; - els.status.classList.add('hidden'); - c.innerHTML = ''; - - const wrap = document.createElement('div'); - wrap.className = 'settings'; - - // ---- Playback ---- - const qualities = ['auto', '1080p', '720p', '480p', '360p', '240p']; - const qOptions = qualities - .map((q) => ``) - .join(''); - - const sel = (id, val, opts) => ``; - - wrap.innerHTML = ` -
-
Appearance & accessibility
- - - - - - -
- -
-
Playback
- - - - - ${EQ.isIOS() ? `` : ''} - - - - -
- -
-
Sharing (peer-to-peer)
- - -
- This device… - … -
- -
- -
-
Offline cache
- - -
- Storage used - … -
- -
- -
-
- Saved videos -
-
-
- -
-
Saved searches
-
- - Kept on this device - Search results and their thumbnails stay saved after you clear the search box. Only you can remove them, here. - - … -
-
- - - -
-
-
- -
-
Playlists
-
- - - - -
-
- -
-
Backup & restore
- - -
- - - -
-
- -
-
Reset
-
- - Force refresh UI - Re-fetches the app shell and assets, bypassing the browser cache, then reloads. - -
- -
-
-
- - Reset app - Clears all local storage, unregisters the service worker, and deletes every cache. You will need to reload after. - -
- -
-
-
- -
-
Online profile — sync between devices
-
- - Linked profile - Playlists, history and settings sync to the server under this name. The name works like a passkey — anyone who knows it can load and change this data, so prefer a random one. - - ${data.profile && data.profile.name ? data.profile.name : 'Not linked'} -
-
- - Profile link - Open this URL on another device to load the profile there. Anyone with the link gets full access to this data — share it only with your own devices or people you trust. - - ${escapeHtml(profileShareUrl() || '')} -
-
- - - - - - - - - -
-
- -
-
About
-
- - Version - App version and current build. - -
- v${APP_VERSION} -
-
-
- - Build time - When the running server build was produced — compare across devices to confirm you're on the latest version. - - … -
-
`; - - c.appendChild(wrap); - const definitions = [ - ['appearance', 'Appearance', 'Listening', () => `${data.settings.theme || 'dark'} · ${data.settings.fontScale || 'normal'} text`, ''], - ['playback', 'Playback & sound', 'Listening', () => `${data.settings.quality || 'auto'} quality · ${Level.enabled() ? 'Levelled volume' : 'Original volume'}`, ''], - ['sharing', 'Sharing', 'Library & storage', () => data.settings.p2pShare !== false ? 'Sharing saved videos' : 'Sharing off', ''], - ['offline', 'Offline storage', 'Library & storage', () => `${SaveSlots.limit ? SaveSlots.limit() : Number(data.settings.parallelSaves) || 4} at once · ${$('cacheTotal')?.textContent || 'Checking storage'}`, ''], - ['searches', 'Saved searches', 'Library & storage', () => `${SearchLibrary.list().length} saved searches`, ''], - ['playlists', 'Playlists', 'Library & storage', () => `${data.playlists.length} playlists`, ''], - ['backup', 'Backup & restore', 'Account & sync', () => data.settings.autoBackupEnabled ? 'Scheduled backup on' : 'Manual backups', ''], - ['reset', 'Refresh & reset', 'Advanced & about', () => 'Refresh the app or clear device data', ''], - ['profile', 'Profile & sync', 'Account & sync', () => data.profile?.name || 'Not linked', ''], - ['about', 'About', 'Advanced & about', () => `Version ${APP_VERSION}`, ''], - ]; - const groups = [...wrap.querySelectorAll(':scope > .set-group')]; - definitions.forEach(([id, title, cluster, summary, icon], i) => SettingsSections.register({ id, title, cluster, summary, icon, render(container) { container.append(groups[i]); } })); - SettingsSections.register({ id: 'video-fullscreen', title: 'Video & fullscreen', cluster: 'Listening', icon: '', summary: () => `Fullscreen: ${FullscreenOrientation.normalize(data.settings.fullscreenOrientation)}`, render(container) { - const row = document.createElement('label'); row.className = 'set-row'; - row.innerHTML = 'Fullscreen orientation'; - const select = row.querySelector('select'); select.value = FullscreenOrientation.normalize(data.settings.fullscreenOrientation); - select.onchange = () => { data.settings.fullscreenOrientation = select.value; persist(); }; - container.append(row); - } }); - SettingsSections.mount(wrap, { settings: data.settings, data, persist, toast }); - - // ---- Wire appearance / accessibility ---- - $('setTheme').addEventListener('change', (e) => { data.settings.theme = e.target.value; applyAppearance(); persist(); }); - $('setLayout').addEventListener('change', async (e) => { - const select=e.target, next=select.value, previous=data.settings.layout; select.disabled=true; - try { await Lazy.load('layout:'+next); data.settings.layout=next; Lazy.layout=next; if(WEB)saveDataToStorage(JSON.stringify(data)); applyAppearance(); persist(); Lazy.reportLayout?.(); } - catch(error) { select.value=previous; toast(error.message); } - finally { select.disabled=false; } - }); - $('setFont').addEventListener('change', (e) => { data.settings.fontScale = e.target.value; applyAppearance(); persist(); }); - $('setParallelSaves').addEventListener('change', (e) => { data.settings.parallelSaves = Number(e.target.value) || 4; persist(); SaveSlots.pump(); }); - $('setDensity').addEventListener('change', (e) => { data.settings.density = e.target.value; applyAppearance(); persist(); }); - $('setPerf').addEventListener('change', (e) => { data.settings.perfMode = e.target.checked; applyAppearance(); persist(); }); - $('setMotion').addEventListener('change', (e) => { data.settings.reduceMotion = e.target.checked; applyAppearance(); persist(); }); - $('setRepeat').addEventListener('change', (e) => { data.settings.repeatMode = e.target.checked ? 'all' : 'off'; updateLoopRepeatButtons(); persist(); }); - $('setLoopOne').addEventListener('change', (e) => { data.settings.loopOne = e.target.checked; updateLoopRepeatButtons(); persist(); }); - $('setLevelVolume').addEventListener('change', (e) => { - data.settings.levelVolume = e.target.checked; - persist(); - if (current && current.meta) Level.onTrack(current.meta); else EQ.setLevel(0); - EqRender.scheduleAll(); - }); - if ($('setLiveAudioIOS')) $('setLiveAudioIOS').addEventListener('change', (e) => { - data.settings.liveAudioIOS = e.target.checked; - persist(); - EQ.apply(); - if (current && current.meta) Level.onTrack(current.meta); - if (e.target.checked) toast('Live sound processing on — streamed songs go silent when the screen locks', { duration: 4500 }); - }); - // ---- Saved searches manager ---- - { - const listEl = $('ssList'); - const sel = new Set(); - const refresh = () => { - const items = SearchLibrary.list(); - for (const k of [...sel]) if (!items.some((i) => i.key === k)) sel.delete(k); - $('ssTotal').textContent = items.length ? `${items.length} · ${fmtBytes(SearchLibrary.bytes())}` : 'None'; - listEl.innerHTML = items.length ? items.map((i) => ` - `).join('') : '
No saved searches.
'; - $('ssDeleteSel').disabled = !sel.size; - $('ssDeleteSel').textContent = sel.size ? `Delete selected (${sel.size})` : 'Delete selected'; - $('ssSelectAll').textContent = items.length && sel.size === items.length ? 'Select none' : 'Select all'; - $('ssClearAll').disabled = !items.length; - }; - listEl.addEventListener('change', (e) => { const k = e.target.dataset && e.target.dataset.k; if (!k) return; e.target.checked ? sel.add(k) : sel.delete(k); refresh(); }); - $('ssSelectAll').addEventListener('click', () => { - const items = SearchLibrary.list(); - if (sel.size === items.length) sel.clear(); else items.forEach((i) => sel.add(i.key)); - refresh(); - }); - $('ssDeleteSel').addEventListener('click', () => { - if (!sel.size || !confirm(`Delete ${sel.size} saved search${sel.size === 1 ? '' : 'es'}? Their results and thumbnails are removed from this device.`)) return; - SearchLibrary.remove([...sel]); sel.clear(); refresh(); toast('Saved searches deleted'); - }); - $('ssClearAll').addEventListener('click', () => { - if (!confirm('Delete ALL saved searches and their thumbnails from this device?')) return; - SearchLibrary.clear(); sel.clear(); refresh(); toast('All saved searches deleted'); - }); - refresh(); - } - // ---- Wire playback controls ---- - $('setQuality').addEventListener('change', (e) => { - data.settings.quality = e.target.value; - els.quality.value = e.target.value; - persist(); - }); - $('setVolume').addEventListener('input', (e) => { - data.settings.volume = parseFloat(e.target.value); - els.volume.value = e.target.value; - Player.applyVolume(); - syncMuteIcon(); - persist(); - }); - $('setAudioOnly').addEventListener('change', (e) => { - data.settings.audioOnly = e.target.checked; - els.audioOnlyToggle.checked = e.target.checked; - persist(); - }); - $('setSaveBeforePlay').addEventListener('change', (e) => { - data.settings.saveBeforePlay = e.target.checked; - persist(); - }); - $('setLyricFlags').addEventListener('change', (e) => { - data.settings.lyricFlags = e.target.checked; - persist(); - Notes.refreshFlags(); - }); - $('setAutoPreload').addEventListener('change', (e) => { - data.settings.autoPreload = e.target.checked; - persist(); - if (e.target.checked) data.playlists.forEach(preloadPlaylist); - }); - $('setP2pShare').addEventListener('change', (e) => { - data.settings.p2pShare = e.target.checked; - persist(); - if (window.P2PClient) window.P2PClient.sync(); // share off → withdraws every holding - }); - $('setP2pReceive').addEventListener('change', (e) => { - data.settings.p2pReceive = e.target.checked; - persist(); - if (window.P2PClient) window.P2PClient.sync(); - }); - (async () => { - const info = $('p2pDeviceInfo'); - const cnt = $('p2pHoldingCount'); - if (!info || !cnt) return; - const P = window.P2PClient; - const d = P && P.device(); - info.textContent = !d ? 'Not registered yet' - : P.isConnected() ? `Online · peer ${P.peer()}` : 'Registered · not connected'; - const files = window.DeviceDB ? await window.DeviceDB.listFiles() : []; - cnt.textContent = `${files.filter((f) => f.state === 'verified').length} verified / ${files.length} saved`; - const unknown = window.P2PClient ? await window.P2PClient.unknownVideos() : []; - const row = $('p2pContributeRow'); - const btn = $('p2pContributeBtn'); - if (row && btn && unknown.length) { - row.classList.remove('hidden'); - btn.textContent = `Verify & share ${unknown.length} saved video${unknown.length === 1 ? '' : 's'}`; - btn.onclick = async () => { - btn.disabled = true; - let ok = 0; - for (let i = 0; i < unknown.length; i++) { - const v = videoById(unknown[i]) || {}; - btn.textContent = `Uploading ${i + 1} of ${unknown.length}…`; - const r = await window.P2PClient.contribute(unknown[i], { title: v.title || '', channel: v.channel || '' }); - if (r && r.ok) ok++; - } - toast(`Verified ${ok} of ${unknown.length} saved video${unknown.length === 1 ? '' : 's'}`); - btn.disabled = false; - row.classList.add('hidden'); - }; - } - })(); - // ---- Cache management ---- - $('clearCacheBtn').addEventListener('click', () => { - showModal('Clear all cached videos?', document.createTextNode('This frees disk space. Playlists keep their entries and will re-download on demand.'), [ - { label: 'Cancel', onClick: closeModal }, - { - label: 'Clear all', danger: true, onClick: async () => { - try { await API.cacheClear(); } catch {} - cachedIds.clear(); - closeModal(); - toast('Cache cleared'); - if (current) updateNowPlayingActions(); - renderList(); - }, - }, - ]); - }); - // The saved-videos list folds; remember how the user left it. - { - const fold = $('cacheFold'); - try { fold.open = localStorage.getItem('ytpCacheFoldOpen') === '1'; } catch { /* blocked */ } - fold.addEventListener('toggle', () => { try { localStorage.setItem('ytpCacheFoldOpen', fold.open ? '1' : '0'); } catch { /* blocked */ } }); - } - - // ---- Populate live cache stats ---- - try { - const res = await API.cacheList(); - if (view.type !== 'settings') return; // user navigated away - const total = (res && res.total) || 0; - const items = (res && res.items) || []; - $('cacheTotal').textContent = `${fmtBytes(total)} · ${items.length} video${items.length === 1 ? '' : 's'}`; - $('cacheFoldCount').textContent = items.length ? `${items.length} · ${fmtBytes(total)}` : 'none'; - const listEl = $('cacheList'); - if (!items.length) { - listEl.innerHTML = '
No videos saved offline yet.
'; - } else { - items.sort((a, b) => b.size - a.size); - items.forEach((it) => { - const row = document.createElement('div'); - row.className = 'cache-item'; - row.innerHTML = `${fmtBytes(it.size)}`; - row.querySelector('.ci-title').textContent = videoTitleById(it.id); - row.querySelector('.ci-del').addEventListener('click', async () => { - try { await API.cacheDelete(it.id); } catch {} - cachedIds.delete(it.id); - if (current && current.meta && current.meta.id === it.id) updateNowPlayingActions(); - toast('Removed from cache'); - renderList(); - }); - listEl.appendChild(row); - }); - } - } catch { - const t = $('cacheTotal'); - if (t) t.textContent = 'Offline cache not available in this build'; - } - - // ---- Cache cap ---- - const capSel = $('cacheCapSelect'); - capSel.value = String(data.settings.cacheCap || 0); - capSel.addEventListener('change', (e) => { - data.settings.cacheCap = parseInt(e.target.value) || 0; - persist(); - }); - - // ---- Export / Import playlists ---- - $('importYtBtn')?.addEventListener('click', openImportYouTubeModal); - $('exportBtn').addEventListener('click', exportPlaylists); - $('importBtn').addEventListener('click', () => $('fileInput').click()); - $('fileInput').addEventListener('change', importPlaylists); - - // ---- Backup ---- - $('setAutoBackup').addEventListener('change', (e) => { data.settings.autoBackupEnabled = e.target.checked; persist(); }); - $('setBackupInterval').addEventListener('change', (e) => { data.settings.autoBackupIntervalDays = parseInt(e.target.value) || 7; persist(); }); - $('backupNowBtn').addEventListener('click', () => doAutoBackup()); - $('importBackupBtn').addEventListener('click', () => $('backupFileInput').click()); - $('backupFileInput').addEventListener('change', importBackup); - - // ---- Online profile ---- - $('profileCreateBtn').addEventListener('click', createProfileFlow); - $('profileLoadBtn').addEventListener('click', loadProfileFlow); - $('profileCopyLinkBtn').addEventListener('click', copyProfileLink); - $('profileShareBtn').addEventListener('click', shareProfileLink); - $('profileProtectBtn').addEventListener('click', protectProfileFlow); - $('profileExportCredBtn').addEventListener('click', exportProfileCredentials); - $('profileImportCredBtn').addEventListener('click', importProfileCredentials); - $('profileUnlinkBtn').addEventListener('click', () => { - data.profile = null; - ProfileSecret.clear(); - persist(); - updateProfileStatus(); - toast('Profile unlinked — this device stops syncing (server copy is kept)'); - }); - updateProfileStatus(); - - // ---- About: append server build tag + build time (WEB mode only) ---- - if (WEB) { - try { - const res = await fetch('/api/version', { cache: 'no-store' }); - if (res.ok && view.type === 'settings') { - const v = await res.json(); - const el = $('aboutVersion'); - if (el && v.buildTag) el.textContent = `v${v.version || APP_VERSION} · build ${v.buildTag}`; - const bt = $('aboutBuildTime'); - if (bt) { - const t = v.buildTime ? new Date(v.buildTime) : null; - if (t && !isNaN(t)) { - // Shown in GMT+8 regardless of device/server timezone, plus build age. - const gmt8 = new Date(t.getTime() + 8 * 3600e3).toISOString().replace('T', ' ').slice(0, 16); - const s = Math.max(0, Math.floor((Date.now() - t.getTime()) / 1000)); - const ago = s < 60 ? `${s} second${s === 1 ? '' : 's'} ago` - : s < 3600 ? `${Math.floor(s / 60)} minute${Math.floor(s / 60) === 1 ? '' : 's'} ago` - : s < 86400 ? `${Math.floor(s / 3600)} hour${Math.floor(s / 3600) === 1 ? '' : 's'} ago` - : `${Math.floor(s / 86400)} day${Math.floor(s / 86400) === 1 ? '' : 's'} ago`; - bt.textContent = `${gmt8} +08 · built ${ago}`; - } else { - bt.textContent = 'unknown'; - } - } - } - } catch { /* offline — leave the static version in place */ } - } - - // ---- Reset ---- - $('refreshUiBtn').addEventListener('click', async () => { - const btn = $('refreshUiBtn'); - btn.disabled = true; - btn.textContent = 'Refreshing…'; - // hardReloadUI() deletes all caches and unregisters the SW so the - // next page load always fetches fresh assets from the network. - await hardReloadUI(); - }); - - $('resetAppBtn').addEventListener('click', () => { - showModal( - 'Reset app?', - (() => { const p = document.createElement('p'); p.textContent = 'This clears all local data and caches. The page will reload.'; return p; })(), - [ - { label: 'Cancel', onClick: closeModal }, - { - label: 'Reset', danger: true, onClick: async () => { - closeModal(); - try { - localStorage.clear(); - sessionStorage.clear(); - if ('serviceWorker' in navigator) { - const regs = await navigator.serviceWorker.getRegistrations(); - await Promise.all(regs.map((r) => r.unregister())); - } - if ('caches' in window) { - const keys = await caches.keys(); - await Promise.all(keys.map((k) => caches.delete(k))); - } - } catch { /* best effort — reload regardless */ } - window.location.href = '/'; - }, - }, - ], - ); - }); -} - -function renderCard(v, index, list) { - const card = document.createElement('div'); - const isCached = cachedIds.has(v.id); - const isDownloading = downloading.has(v.id); - card.className = 'card' + (isCached ? ' cached' : '') + (isDownloading ? ' downloading' : '') + (selectedIds.has(v.id) ? ' selected' : ''); - card.dataset.id = v.id; - card._video = v; // read by f7-layout.js swipe actions - card.innerHTML = ` -
-
- - ${v.duration ? `${fmtTime(v.duration)}` : ''} - ${isDownloading ? '' : '⬇'} - ${isDownloading ? '
' : ''} -
-
-
-
-
- `; - card.querySelector('.card-title').textContent = v.title; - const chEl = card.querySelector('.card-channel'); - chEl.textContent = v.channel || ''; - if (channelKeyOf(v)) { - chEl.classList.add('link'); - chEl.title = 'View channel'; - chEl.addEventListener('click', (e) => { - e.stopPropagation(); - openChannel(channelKeyOf(v), v.channel); - }); - } - - // Playlist view: note under title (if present) and note edit button (Section 5) - if (view.type === 'playlist') { - const hasNote = !!(v.notes && v.notes.trim()); - if (hasNote) { - const noteEl = document.createElement('div'); - noteEl.className = 'card-note'; - noteEl.textContent = v.notes.trim(); - noteEl.title = v.notes.trim(); - const titleEl = card.querySelector('.card-title'); - if (titleEl) titleEl.after(noteEl); - } - - const noteBtn = document.createElement('button'); - noteBtn.type = 'button'; - noteBtn.className = 'card-note-btn' + (hasNote ? ' has-note' : ''); - noteBtn.title = hasNote ? 'Edit note' : 'Add note'; - noteBtn.textContent = '✎'; - noteBtn.addEventListener('click', (e) => { - e.stopPropagation(); - openSongNoteModal(v); - }); - const menuBtn = card.querySelector('.card-menu'); - card.insertBefore(noteBtn, menuBtn); - } - - card.addEventListener('pointerdown', () => warmStreams([v.id]), { passive: true }); - card.addEventListener('click', (e) => { - if (e.target.closest('.card-menu') || e.target.closest('.card-del') || e.target.closest('.card-note-btn') || e.target.closest('.card-channel.link')) return; - if (selectMode) { toggleSelectCard(v.id); return; } - playFromList(list, index, view.type === 'playlist' ? 'playlist:' + view.id : view.type === 'nowPlaying' ? queueSource : view.type); - }); - card.querySelector('.card-menu').addEventListener('click', (e) => { - e.stopPropagation(); - openCardMenu(v); - }); - - // Per-item delete in playlist, queue, history, and smart views. - if (view.type === 'playlist' || view.type === 'queue' || view.type === 'history' || view.type === 'smart') { - const del = document.createElement('button'); - del.className = 'card-del'; - del.title = view.type === 'queue' ? 'Remove from queue' - : (view.type === 'history' || view.type === 'smart') ? 'Remove from history' - : 'Remove from playlist'; - del.textContent = '✕'; - del.addEventListener('click', (e) => { - e.stopPropagation(); - if (view.type === 'queue') { removeFromQueue(v.id); return; } - if (view.type === 'history' || view.type === 'smart') { - data.history = data.history.filter((x) => x.id !== v.id); - persist(); - renderList(); - return; - } - const pl = data.playlists.find((p) => p.id === view.id); - if (pl) { pl.videos = pl.videos.filter((x) => x.id !== v.id); persist(); render(); toast('Removed from playlist'); } - }); - card.appendChild(del); - } - - // Drag-to-reorder in playlist and queue views - if (view.type === 'playlist' || view.type === 'queue') { - card.draggable = true; - card.addEventListener('dragstart', () => { - card.classList.add('dragging'); - dragSource = index; - }); - card.addEventListener('dragend', () => { - card.classList.remove('dragging'); - }); - card.addEventListener('dragover', (e) => { - e.preventDefault(); - card.classList.add('drag-over'); - }); - card.addEventListener('dragleave', () => { - card.classList.remove('drag-over'); - }); - card.addEventListener('drop', (e) => { - e.preventDefault(); - card.classList.remove('drag-over'); - const from = dragSource; - const to = index; - if (from === to || from < 0) return; - const arr = view.type === 'queue' - ? data.queue - : (data.playlists.find((p) => p.id === view.id) || {}).videos; - if (!arr) return; - const [moved] = arr.splice(from, 1); - arr.splice(to, 0, moved); - if (view.type === 'queue' && queueSource === 'queue') { - const playingId = current && current.meta && current.meta.id; - queue = data.queue.slice(); - queueIndex = playingId ? queue.findIndex((x) => x.id === playingId) : queueIndex; - renderUpNext(); - } - persist(); - renderList(); - }); - } - - return card; -} - -function markPlayingCard() { - document.querySelectorAll('.card').forEach((c) => { - c.classList.toggle('playing', current && c.dataset.id === current.meta.id); - }); -} // Only entries created by returning to the player participate here; leave // unrelated history (including Settings section navigation) to its owner. @@ -11923,41 +9990,7 @@ const fetchRelatedVideos = RelatedVideos.createLoader({ async function loadRelated(options = {}) { if (current?.meta) return fetchRelatedVideos(current.meta, options); } -function renderRelated() { - const panel = $('relatedPanel'), list = $('relatedList'); - if (!panel || !list || (relatedState.status === 'idle' && !relatedVideos.length)) { if (panel) panel.classList.add('hidden'); return; } - panel.classList.remove('hidden'); - list.classList.toggle('hidden', relatedCollapsed); - list.innerHTML = ''; - if (relatedState.message) { - const notice = document.createElement('div'); notice.className = 'related-notice'; notice.setAttribute('role', 'status'); - const message = document.createElement('p'); message.textContent = relatedState.message; notice.append(message); - if (relatedState.status === 'error') { - const retry = document.createElement('button'); retry.type = 'button'; retry.className = 'related-retry'; retry.setAttribute('aria-label', 'Retry related videos'); - retry.innerHTML = 'Retry'; - retry.onclick = () => loadRelated({ refresh: true }); notice.append(retry); - } - list.append(notice); - } - relatedVideos.forEach((v) => { - const item = document.createElement('div'); - item.className = 'related-item'; - item.innerHTML = `
`; - item.querySelector('.ri-title').textContent = v.title; - const riChEl = item.querySelector('.ri-channel'); - riChEl.textContent = v.channel || ''; - if (channelKeyOf(v)) { - riChEl.classList.add('link'); - riChEl.title = 'View channel'; - riChEl.addEventListener('click', (e) => { e.stopPropagation(); openChannel(channelKeyOf(v), v.channel); }); - } - item.addEventListener('click', (e) => { - if (e.target.closest('.ri-channel.link')) return; - queue = [v]; queueIndex = 0; playFullMode = false; Player.loadVideo(v); renderUpNext(); - }); - list.appendChild(item); - }); -} + // ============================================================================ // Smart / auto playlists @@ -11968,26 +10001,7 @@ const SMART_PLAYLISTS = [ { id: 'unwatched', label: 'Unwatched' }, { id: 'autoMix', label: 'Auto Mix' }, ]; -function renderSmartSidebar() { - const list = $('smartPlaylistList'); - if (!list) return; - list.innerHTML = ''; - SMART_PLAYLISTS.forEach((sp) => { - const item = document.createElement('div'); - const isActive = view.type === 'smart' && view.smartType === sp.id; - item.className = 'playlist-item smart-item' + (isActive ? ' active' : ''); - item.innerHTML = `${sp.label}`; - item.addEventListener('click', () => { view = { type: 'smart', smartType: sp.id }; render(); }); - list.appendChild(item); - }); - if (WEB && data.settings.p2pReceive !== false) { - const item = document.createElement('div'); - item.className = 'playlist-item smart-item' + (view.type === 'p2p' ? ' active' : ''); - item.innerHTML = '📡 On other devices'; - item.addEventListener('click', () => { view = { type: 'p2p' }; render(); }); - list.appendChild(item); - } -} + function getSmartList(smartType) { switch (smartType) { case 'mostPlayed': { diff --git a/frontend/assets.json b/frontend/assets.json index 253339a..dd849b4 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -57,7 +57,10 @@ "/feature-bootstrap.js", "/eq-parameters.js", "/assets.json", - "/device-db.js" + "/device-db.js", + "/shell-core.js", + "/views-core.js", + "/section-rail.js" ], "background": false }, @@ -249,7 +252,8 @@ "embeddedIn": [ "/app.js", "/settings-sections.js", - "/settings-sections.css" + "/settings-sections.css", + "/views-core.js" ], "background": false }, diff --git a/frontend/index.html b/frontend/index.html index e0cb08b..7798602 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + @@ -669,6 +669,9 @@ + + + diff --git a/frontend/section-rail.js b/frontend/section-rail.js new file mode 100644 index 0000000..c84cf10 --- /dev/null +++ b/frontend/section-rail.js @@ -0,0 +1,247 @@ +/* Eager UI definitions. Read app lexical state only when called after initialization. */ +const SectionRail = (() => { + const CLASSIC_ICONS = { + player: '', + meta: '', + notes: '', + related: '', + list: '', + }; + const SECTIONS = [ + { id: 'player', sel: '.player-stage', icon: '📺', label: 'Player' }, + { id: 'meta', sel: '#nowPlayingMeta', icon: '🎵', label: 'Now playing', fold: true }, + { id: 'notes', sel: '#notesPanel', icon: '📝', label: 'Lyrics', fold: true }, + { id: 'related', sel: '#relatedPanel', icon: '🔗', label: 'Related', fold: true }, + { id: 'list', sel: '#listPane', icon: '📋', label: 'List' }, + ]; + const st = { active: '', btns: new Map(), labelTimer: null, raf: 0, bottom: -1 }; + const rail = () => document.getElementById('sectionRail'); + const folds = () => (data.settings.foldedCards ||= {}); + const isFolded = (id) => !!folds()[id]; + const elOf = (s) => document.querySelector(s.sel); + // Only cards that are actually on screen belong in the rail. + const visible = () => SECTIONS.filter((s) => { + const el = elOf(s); + return el && !el.classList.contains('hidden') && el.offsetParent !== null; + }); + + function applyFold(sec) { + const el = elOf(sec); + if (!el || !sec.fold) return; + el.classList.toggle('folded', isFolded(sec.id)); + if (sec.id === 'notes') { + const b = document.getElementById('notesFoldBtn'); + if (b) b.setAttribute('aria-expanded', String(!isFolded(sec.id))); + } + // The Related card already had its own +/− button; keep the two in step. + if (sec.id === 'related') { + relatedCollapsed = isFolded(sec.id); + const rl = document.getElementById('relatedList'); + const rb = document.getElementById('relatedToggleBtn'); + if (rl) rl.classList.toggle('hidden', relatedCollapsed); + if (rb) rb.textContent = relatedCollapsed ? '+' : '−'; + } + } + + function setFolded(id, on) { + const sec = SECTIONS.find((x) => x.id === id); + if (!sec || !sec.fold) return; + folds()[id] = !!on; + persist(); + applyFold(sec); + paint(); // NOT render() — folding a card must not rebuild the list + } + + function flashLabel(btn) { + clearTimeout(st.labelTimer); + [...st.btns.values()].forEach((b) => b.classList.remove('show-label')); + btn.classList.add('show-label'); + st.labelTimer = setTimeout(() => btn.classList.remove('show-label'), 1400); + } + + function onTap(sec, btn) { + const el = elOf(sec); + if (!el) return; + flashLabel(btn); + if (sec.id === 'player' || sec.id === 'meta') restoreNowPlayingList(); + if (st.active === sec.id && sec.fold) { + // Already here: this is the second tap — fold or unfold the card. + setFolded(sec.id, !isFolded(sec.id)); + if (isFolded(sec.id)) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); + return; + } + st.active = sec.id; // claim it now so the next tap folds + paint(); + el.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + + function build() { + const r = rail(); + if (!r) return; + const items = visible(); + // A rail with one entry is noise; so is one on the empty home screen. + if (items.length < 2) { r.classList.add('hidden'); r.innerHTML = ''; st.btns.clear(); return; } + const key = items.map((s) => s.id).join(','); + if (r.dataset.key !== key) { + r.dataset.key = key; + r.innerHTML = ''; + st.btns.clear(); + for (const sec of items) { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'sec-rail-btn'; + btn.dataset.sec = sec.id; + btn.setAttribute('aria-label', sec.label); + btn.innerHTML = `${escapeHtml(sec.label)}`; + btn.addEventListener('click', () => onTap(sec, btn)); + r.appendChild(btn); + st.btns.set(sec.id, btn); + } + } + r.classList.remove('hidden'); + placeRail(); + paint(); + } + + // The page does NOT scroll the document: `.player-pane` is the scroller in + // the browser, but the installed PWA in portrait scrolls `.body` instead + // (`.player-pane` goes overflow:visible there). So find the real scroller + // rather than assuming one. + function scrollerOf(el) { + for (let e = el && el.parentElement; e; e = e.parentElement) { + const cs = getComputedStyle(e); + if (/(auto|scroll)/.test(cs.overflowY) && e.scrollHeight > e.clientHeight + 4) return e; + } + return document.scrollingElement || document.documentElement; + } + + // The visible box to measure against — the scroller's own rect, or the + // window when the document itself scrolls. + function viewBox() { + const first = elOf(visible()[0] || SECTIONS[0]); + const sc = scrollerOf(first); + if (!sc || sc === document.scrollingElement || sc === document.documentElement) { + return { top: 0, height: window.innerHeight }; + } + const r = sc.getBoundingClientRect(); + return { top: r.top, height: r.height }; + } + + // Which card is the reader looking at? The one whose top is closest to a + // line a third of the way down the visible box — steadier than "first + // visible", which flickers between two cards at a boundary. + function currentId() { + const items = visible(); + if (!items.length) return ''; + const box = viewBox(); + const line = box.top + box.height / 3; + let best = '', bestD = Infinity; + let near = items[0].id, nearD = Infinity; // fallback: closest card overall + for (const sec of items) { + const el = elOf(sec); + if (!el) continue; + const r = el.getBoundingClientRect(); + const d = Math.abs(r.top - line); + // Distance to the visible band, for the fallback below. + const outside = Math.max(box.top - r.bottom, r.top - (box.top + box.height), 0); + if (outside < nearD || (outside === nearD && d < bestD)) { nearD = outside; near = sec.id; } + if (r.bottom < box.top || r.top > box.top + box.height) continue; + if (d < bestD) { bestD = d; best = sec.id; } + } + // Scrolled past the last card (or a card is taller than the viewport and + // its top has gone by): never leave the rail with nothing highlighted. + return best || near; + } + + // The mini player and the bottom nav are both position:fixed bottom:0, and + // either can be absent (nothing playing / landscape). Measure whatever is + // actually pinned down there and park the rail above it, rather than + // guessing an offset that is wrong on the next phone. + function placeRail() { + const r = rail(); + let occupied = 0; + for (const id of ['bottomNav', 'miniBar']) { + const el = document.getElementById(id); + if (!el || el.classList.contains('hidden')) continue; + const box = el.getBoundingClientRect(); + if (!box.height) continue; + if (getComputedStyle(el).position !== 'fixed') continue; + // Count any fixed bar sitting in the lower half. It must NOT be required + // to touch the viewport bottom: on an iPhone XR the bottom nav ends + // above the home-indicator gap, so a "bottom >= innerHeight" test missed + // it entirely and the rail was parked underneath it. + if (box.top > window.innerHeight * 0.5) occupied = Math.max(occupied, window.innerHeight - box.top); + } + // 14px was too tight: the mini player is a floating CARD with a shadow and + // rounded corners, so its visual edge reads higher than its box. + const want = Math.round(occupied + 24); + if (st.bottom !== want) { + st.bottom = want; + if (r) r.style.setProperty('--rail-bottom', want + 'px'); + // Published for anything else that must sit above the bottom bars — + // the watch-party panel's leave button was hidden behind them. + document.documentElement.style.setProperty('--bottom-chrome', Math.round(occupied) + 'px'); + } + } + + function paint() { + for (const [id, btn] of st.btns) { + btn.classList.toggle('active', id === st.active); + btn.classList.toggle('folded', isFolded(id)); + } + } + + function onScroll() { + if (st.raf) return; + st.raf = requestAnimationFrame(() => { + st.raf = 0; + // Panels appear and disappear outside render() too (the Related card + // shows once a video's related list arrives), and a card with no icon + // would leave the rail with nothing highlighted. build() is a no-op + // unless the set of visible cards actually changed. + build(); + placeRail(); + const id = currentId(); + if (id && id !== st.active) { st.active = id; paint(); } + }); + } + + function boot() { + const fb = document.getElementById('notesFoldBtn'); + if (fb) fb.addEventListener('click', () => setFolded('notes', !isFolded('notes'))); + SECTIONS.forEach(applyFold); + // Scroll events from an element do NOT bubble, so a window listener never + // fires here. A capture-phase listener on document catches them all, and + // keeps working when the scroller changes between browser and installed + // PWA (different elements scroll in each). + document.addEventListener('scroll', onScroll, { passive: true, capture: true }); + window.addEventListener('resize', () => { build(); placeRail(); onScroll(); }); + // The mini player appears AFTER the scroll that reveals it, so a scroll + // handler alone measures the layout as it was a moment ago and parks the + // rail underneath it. Watch the two bottom bars for real. + const watch = ['bottomNav', 'miniBar'].map((id) => document.getElementById(id)).filter(Boolean); + if (watch.length && typeof MutationObserver !== 'undefined') { + // The mini bar slides in over 0.25s, so a measurement taken the instant + // it appears catches it mid-animation and lands the rail a few pixels + // too low. Measure now and again once it has settled. + const mo = new MutationObserver(() => { placeRail(); setTimeout(placeRail, 320); }); + watch.forEach((el) => mo.observe(el, { attributes: true, attributeFilter: ['class', 'style'] })); + } + if (watch.length && typeof ResizeObserver !== 'undefined') { + const ro = new ResizeObserver(() => placeRail()); + watch.forEach((el) => ro.observe(el)); + } + build(); + onScroll(); + } + + // Called from render(): cards appear and disappear as videos load. + function refresh() { + SECTIONS.forEach(applyFold); + build(); + placeRail(); + onScroll(); + } + + return { boot, refresh, setFolded, isFolded }; +})(); diff --git a/frontend/shell-core.js b/frontend/shell-core.js new file mode 100644 index 0000000..89563fb --- /dev/null +++ b/frontend/shell-core.js @@ -0,0 +1,304 @@ +/* Eager UI definitions. Read app lexical state only when called after initialization. */ +const Recommendations = (() => { + let cards = [], fetchedAt = 0, loading = false, error = false, actor = '', queuedRefresh = false; + let listHost = null; + const deviceFingerprint = () => window.getFingerprint ? window.getFingerprint() : 'unknown'; + const fingerprint = () => data.profile?.name ? 'profile:' + data.profile.name.toLowerCase() : 'device:' + deviceFingerprint(); + function load() { + const fp = fingerprint(); + if (fp === actor) return; + actor = fp; cards = []; fetchedAt = 0; + try { + const saved = JSON.parse(localStorage.getItem('ytpRecommendations:' + fp) || 'null'); + if (saved && Array.isArray(saved.cards)) cards = saved.cards; + } catch { /* no saved recommendations */ } + } + function paint(host) { + if (!host) return; + host.replaceChildren(); + const heading = document.createElement('div'); heading.className = 'rec-heading'; + const copy = document.createElement('div'); + const title = document.createElement('h2'); title.textContent = 'Recommended for you'; + const sub = document.createElement('p'); sub.textContent = error && cards.length ? 'Saved picks · reconnect to refresh' : 'Familiar favorites and something new, inspired by your listening.'; + copy.append(title, sub); + const refresh = document.createElement('button'); refresh.type = 'button'; refresh.className = 'rec-refresh'; + refresh.textContent = loading ? 'Updating…' : 'Refresh'; refresh.disabled = loading; + refresh.onclick = () => update(true); + heading.append(copy, refresh); host.appendChild(heading); + if (!cards.length) { + const empty = document.createElement('p'); empty.className = 'rec-empty'; empty.setAttribute('role', 'status'); + empty.textContent = loading ? 'Finding your next listen…' : error ? 'Recommendations are unavailable. You can still search or play your playlists.' : 'Search or play a few videos to start discovering recommendations here.'; + host.appendChild(empty); return; + } + const grid = document.createElement('div'); grid.className = 'rec-grid'; + cards.forEach((v, i) => { + const item = document.createElement('article'); item.className = 'rec-item'; + const play = document.createElement('button'); play.type = 'button'; play.className = 'rec-play'; + play.setAttribute('aria-label', 'Play ' + v.title); + const cover = document.createElement('span'); cover.className = 'rec-cover'; + const img = document.createElement('img'); img.src = v.thumbnail || ''; img.alt = ''; img.loading = 'lazy'; img.decoding = 'async'; cover.appendChild(img); + const title = document.createElement('span'); title.className = 'rec-title'; title.textContent = v.title; + const channel = document.createElement('span'); channel.className = 'rec-channel'; channel.textContent = v.channel || ''; + play.append(cover, title, channel); play.onclick = () => { setHomeOverPlayer(false); playFromList(cards.slice(), i, 'recommendations'); }; + const reason = document.createElement('div'); reason.className = 'rec-reason'; reason.textContent = v.reason || 'Recommended for you'; + const actions = document.createElement('div'); actions.className = 'rec-actions'; + const queue = document.createElement('button'); queue.type = 'button'; queue.textContent = '+ Queue'; queue.setAttribute('aria-label', 'Queue ' + v.title); queue.onclick = () => addToQueue(v); + const more = document.createElement('button'); more.type = 'button'; more.textContent = '•••'; more.setAttribute('aria-label', 'More actions for ' + v.title); more.onclick = () => openCardMenu(v); + actions.append(queue, more); item.append(play, reason, actions); grid.appendChild(item); + }); + host.appendChild(grid); + } + function repaint() { + if (!WEB) return; + const home = $('homeRecommendations'); + if (home) { home.classList.remove('hidden'); paint(home); } + els.playerPane?.classList.add('has-recommendations'); + if (listHost?.isConnected) paint(listHost); + requestAnimationFrame(updateBottomChrome); + } + async function update(force = false) { + load(); + if (!WEB) return; + if (loading) { if (force) queuedRefresh = true; return; } + if (!force && Date.now() - fetchedAt < 300000) return; + const fp = actor; loading = true; error = false; repaint(); + try { + const name = data.profile?.name || ''; + const result = await webFetch('/api/recommendations?fp=' + encodeURIComponent(deviceFingerprint()) + (name ? '&profile=' + encodeURIComponent(name) : ''), { headers: name ? profileHeaders(name) : {} }); + if (fp !== fingerprint()) return; + if (!result.ok || !Array.isArray(result.results)) throw new Error('invalid recommendations'); + cards = result.results; + try { localStorage.setItem('ytpRecommendations:' + fp, JSON.stringify({ cards })); } catch { /* full */ } + } catch { error = true; } + finally { + loading = false; fetchedAt = fp === fingerprint() ? Date.now() : 0; repaint(); + if (queuedRefresh || fp !== fingerprint()) { queuedRefresh = false; update(true); } + } + } + function home() { if (WEB) { load(); repaint(); update(); } } + function inList() { + if (!WEB) return; + listHost = document.createElement('section'); listHost.className = 'recommendations'; listHost.setAttribute('aria-label', 'Recommended videos'); + els.cards.appendChild(listHost); load(); paint(listHost); update(); + } + return { home, inList, update }; +})(); + +function renderSidebar() { + els.playlistList.innerHTML = ''; + for (const pl of data.playlists) { + const stats = playlistOfflineStats(pl); + let offlineBadge = ''; + if (stats.total > 0) { + if (stats.cached === stats.total) { + offlineBadge = `⬇`; + } else if (stats.cached > 0) { + offlineBadge = `${stats.cached}/${stats.total}`; + } + } + const item = document.createElement('div'); + item.className = 'playlist-item' + (view.type === 'playlist' && view.id === pl.id ? ' active' : ''); + item.innerHTML = `${offlineBadge}${pl.videos.length}`; + item.querySelector('.pl-name').textContent = pl.name; + item.addEventListener('click', () => { view = { type: 'playlist', id: pl.id }; render(); }); + els.playlistList.appendChild(item); + } + document.querySelectorAll('.nav-item').forEach((b) => { + b.classList.toggle('active', b.dataset.view === view.type); + }); + // Keep bottom-nav in sync with sidebar nav active state + document.querySelectorAll('.bottom-nav-btn').forEach((b) => { + b.classList.toggle('active', b.dataset.view === view.type); + }); + updateQueueBadge(); + updateDownloadBadge(); + renderHomePlaylists(); +} + +function renderHomePlaylists() { + if (window.BentoHub) BentoHub.playlists = () => data.playlists || []; + const wrap = document.getElementById('homePlaylists'); + const hero = document.querySelector('#playerPlaceholder .hero'); + const grid = document.getElementById('homePlGrid'); + if (!wrap || !hero || !grid) return; + Recommendations.home(); + + const lists = data.playlists || []; + wrap.classList.toggle('hidden', !lists.length); + hero.classList.toggle('hidden', !!lists.length); + // The hero is centered art; the grid wants the full box, so the placeholder + // switches from centering to stretching (and tightens its padding), and the + // stage drops its 16:9 lock so the grid gets the pane's real height. + if (els.placeholder) els.placeholder.classList.toggle('showing-playlists', !!lists.length); + if (els.playerPane) els.playerPane.classList.toggle('home-playlists', !!lists.length); + if (!lists.length) { grid.innerHTML = ''; return; } + + grid.innerHTML = ''; + for (const pl of lists) { + const count = pl.videos.length; + const thumb = (pl.videos.find((v) => v && v.thumbnail) || {}).thumbnail || ''; + const stats = playlistOfflineStats(pl); + let offlineHtml = ''; + if (stats.total > 0) { + if (stats.cached === stats.total) { + offlineHtml = `⬇`; + } else if (stats.cached > 0) { + offlineHtml = `${stats.cached}/${stats.total}`; + } + } + const card = document.createElement('button'); + card.className = 'home-pl-card'; + card.type = 'button'; + card.innerHTML = ` + + ${thumb ? `` + : '🎵'} + ${offlineHtml} + ▶ + + + ${count} video${count === 1 ? '' : 's'}`; + card.querySelector('.home-pl-name').textContent = pl.name; + card.title = pl.name; + card.addEventListener('click', () => { view = { type: 'playlist', id: pl.id }; render(); }); + card.querySelector('.home-pl-play').addEventListener('click', (e) => { + e.stopPropagation(); // the ▶ badge plays; the rest of the card opens the list + if (count) playFromList(pl.videos, 0, 'playlist:' + pl.id); + else toast('That playlist is empty'); + }); + grid.appendChild(card); + } + // Measure after layout — scrollHeight is meaningless until the cards lay out. + requestAnimationFrame(updateHomeGridScrollState); +} + +function updateHomeGridScrollState() { + const grid = document.getElementById('homePlGrid'); + if (!grid) return; + const overflows = grid.scrollHeight > grid.clientHeight + 1; + grid.classList.toggle('is-scrollable', overflows); + grid.classList.toggle('at-end', !overflows || + grid.scrollTop + grid.clientHeight >= grid.scrollHeight - 2); +} + +function updateBottomChrome() { + let occupied = 0; + for (const id of ['bottomNav', 'miniBar']) { + const el = document.getElementById(id); + if (!el || el.classList.contains('hidden')) continue; + const box = el.getBoundingClientRect(); + if (!box.height || getComputedStyle(el).position !== 'fixed') continue; + if (box.top > window.innerHeight * 0.5) occupied = Math.max(occupied, window.innerHeight - box.top); + } + document.documentElement.style.setProperty('--bottom-chrome', Math.round(occupied) + 'px'); +} + +function setHomeOverPlayer(on) { + const pane = els.playerPane; + if (!pane) return; + on = !!on && !!(current && current.meta); + // Service mode hides the bottom bar and mini bar (and, in its Video view, + // lives inside this pane): leave it first or the home screen is a dead end. + if (on && isServiceModeOpen()) exitServiceMode(); + if (pane.classList.contains('home-over') === on) return; + pane.classList.toggle('home-over', on); + pane.classList.toggle('empty', on); + if (els.placeholder) els.placeholder.classList.toggle('hidden', !on); + if (on) { + renderHomePlaylists(); + showMiniBar(); + const body = document.querySelector('.body'); + if (body) body.scrollTo({ top: 0 }); + } +} + +function showMiniBar() { + if (!current || !current.meta) return; + $('miniTitle').textContent = current.meta.title; + const miniCh = $('miniChannel'); + miniCh.textContent = current.meta.channel || ''; + miniCh.classList.toggle('link', !!channelKeyOf(current.meta)); + $('miniBar').classList.remove('hidden'); + updateMiniBar(); + requestAnimationFrame(updateBottomChrome); +} + +function updateMiniBar() { + if (!current || !current.meta) return; + const cur = Player.master.currentTime || 0; + const dur = Player.master.duration || 0; + $('miniTime').textContent = fmtTime(cur); + if (dur > 0) { + $('miniProgressFill').style.width = Math.min(100, (cur / dur) * 100) + '%'; + } +} + +function hideMiniBar() { + $('miniBar').classList.add('hidden'); + requestAnimationFrame(updateBottomChrome); +} + +function setTile(btn, label) { + const tl = btn.querySelector('.tl'); + if (tl) tl.textContent = label; else btn.textContent = label; +} + +function updateNowPlayingActions() { + if (!current || !current.meta) return; + const id = current.meta.id; + renderAvailability(id); + // Custom (edited) videos are already a saved-offline cut of a source video; + // re-saving or re-editing them makes no sense, so hide those actions. + const isCustom = !!current.meta.custom; + if (els.editBtn) els.editBtn.hidden = isCustom; + if (els.saveBtn) els.saveBtn.hidden = isCustom; + // The server cache exists only behind the web PWA backend. + if (els.brokenBtn) { + els.brokenBtn.hidden = isCustom || !WEB; + els.brokenBtn.disabled = reportingBroken.has(id); + els.brokenBtn.textContent = reportingBroken.has(id) ? '⏳ Reporting…' : '⚠ Broken'; + } + { const ch = $('npChannel'); if (ch) { const ok = isUploadId(id) || cachedIds.has(id); ch.classList.toggle('verified', ok); ch.title = ok ? 'Available on this device or the server' : ''; } } + const btn = els.saveBtn; + if (!btn) return; + if (removing.has(id)) { + setTile(btn, 'Removing…'); + btn.classList.remove('done'); + btn.disabled = true; + } else if (downloading.has(id)) { + setTile(btn, 'Saving…'); + btn.classList.remove('done'); + btn.disabled = true; + } else if (cachedIds.has(id)) { + setTile(btn, 'Saved'); + btn.classList.add('done'); + btn.disabled = false; + btn.title = 'Saved for offline — click to remove from cache'; + } else { + setTile(btn, 'Save'); + btn.classList.remove('done'); + btn.disabled = false; + btn.title = 'Save this video for offline playback'; + } +} + +function renderSmartSidebar() { + const list = $('smartPlaylistList'); + if (!list) return; + list.innerHTML = ''; + SMART_PLAYLISTS.forEach((sp) => { + const item = document.createElement('div'); + const isActive = view.type === 'smart' && view.smartType === sp.id; + item.className = 'playlist-item smart-item' + (isActive ? ' active' : ''); + item.innerHTML = `${sp.label}`; + item.addEventListener('click', () => { view = { type: 'smart', smartType: sp.id }; render(); }); + list.appendChild(item); + }); + if (WEB && data.settings.p2pReceive !== false) { + const item = document.createElement('div'); + item.className = 'playlist-item smart-item' + (view.type === 'p2p' ? ' active' : ''); + item.innerHTML = '📡 On other devices'; + item.addEventListener('click', () => { view = { type: 'p2p' }; render(); }); + list.appendChild(item); + } +} diff --git a/frontend/sw.js b/frontend/sw.js index efca9b4..ed90ab1 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -137,6 +137,9 @@ const SHELL = [ '/car-mode.css', '/lower-third.css', '/settings-sections.css', + '/shell-core.js', + '/views-core.js', + '/section-rail.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', diff --git a/frontend/views-core.js b/frontend/views-core.js new file mode 100644 index 0000000..314b18b --- /dev/null +++ b/frontend/views-core.js @@ -0,0 +1,1501 @@ +/* Eager UI definitions. Read app lexical state only when called after initialization. */ +async function renderLibrary() { + els.listTitle.textContent = 'Library'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + els.cards.innerHTML = '
Loading the server library…
'; + let list = []; + try { + const j = await (await fetch('/api/uploads?limit=200')).json(); + list = (j && j.ok && j.uploads) || []; + } catch { + els.cards.innerHTML = '
⚠ Could not reach the server
'; + return; + } + if (view.type !== 'library') return; + if (!list.length) { + els.cards.innerHTML = ` +
+
📁
+

Nothing uploaded yet

+

An admin can upload videos and audio at /admin; they show up here and in search, with their cover art and any embedded lyrics.

+
`; + return; + } + const cards = list.map((u) => ({ + id: u.id, title: u.title, channel: u.artist || u.album || 'Uploaded', duration: u.duration, + thumbnail: u.art ? `/api/uploads/${u.id}/art` : '', kind: u.kind, upload: true, + })); + els.cards.innerHTML = ''; + cards.forEach((v, i) => els.cards.appendChild(renderCard(v, i, cards))); +} + +function renderNotesView() { + els.listTitle.textContent = 'Notes'; + els.status.classList.add('hidden'); + const groups = Object.entries(data.bookmarks || {}) + .filter(([, list]) => Array.isArray(list) && list.length) + .map(([id, list]) => { + const h = data.history.find((x) => x.id === id); + const first = list.find((b) => b.vt) || {}; + return { id, title: first.vt || (h && h.title) || id, channel: first.vc || (h && h.channel) || '', list }; + }); + // Most recently played first (history order), the rest after. + const order = new Map(data.history.map((v, i) => [v.id, i])); + groups.sort((a, b) => (order.has(a.id) ? order.get(a.id) : 1e9) - (order.has(b.id) ? order.get(b.id) : 1e9)); + els.listActions.innerHTML = groups.length ? '' : ''; + const c = els.cards; + if (!groups.length) { + c.innerHTML = ` +
+
📝
+

No notes yet

+

While a video plays, open Chapters & bookmarks → 📝 Note (or press N) to write a note tied to that exact moment. They sync with your online profile.

+
`; + return; + } + const total = groups.reduce((n, g) => n + g.list.length, 0); + c.innerHTML = ` +
+ + ${groups.map((g) => ` +
+
${escapeHtml(g.title)}${escapeHtml(g.channel)} · ${g.list.length}
+ ${g.list.map((b) => ` + `).join('')} +
`).join('')} +
`; + c.querySelector('.nv-filter').addEventListener('input', (e) => { + const q = e.target.value.trim().toLowerCase(); + c.querySelectorAll('.nv-group').forEach((g) => { + let any = false; + g.querySelectorAll('.nv-item').forEach((it) => { const hit = !q || it.dataset.q.includes(q); it.classList.toggle('hidden', !hit); any = any || hit; }); + g.classList.toggle('hidden', !any); + }); + }); + c.querySelector('.nv-filter').addEventListener('keydown', (e) => e.stopPropagation()); + c.querySelectorAll('.nv-item').forEach((it) => it.addEventListener('click', () => { + const g = groups.find((x) => x.id === it.closest('.nv-group').dataset.id); + playVideoAt({ id: g.id, title: g.title, channel: g.channel }, Number(it.dataset.t)); + })); + const ex = $('notesExportBtn'); + if (ex) ex.addEventListener('click', () => { + const md = ['# YT Player notes', `_Exported ${new Date().toLocaleString()}_`, '']; + for (const g of groups) { + md.push(`## ${g.title}`, `${g.channel ? g.channel + ' · ' : ''}https://youtu.be/${g.id}`, ''); + for (const b of g.list) { + md.push(`- **[${LyricsCore.fmtClock(b.t)}](${location.origin}/?v=${g.id}&t=${Math.floor(b.t)})** ${b.title}`); + if (b.note && b.note !== b.title) md.push(...b.note.split('\n').map((l) => ` ${l}`)); + } + md.push(''); + } + const blob = new Blob([md.join('\n')], { type: 'text/markdown' }); + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.download = `ytplayer-notes-${new Date().toISOString().slice(0, 10)}.md`; + a.click(); + setTimeout(() => URL.revokeObjectURL(a.href), 2000); + }); +} + +function showSearchSkeletons() { + // A search is in flight — the pane is about to have results, so reveal it + // now rather than popping in only once they land. + setListPaneHidden(false); + els.status.classList.add('hidden'); + els.cards.innerHTML = ''; + for (let i = 0; i < 8; i++) { + const s = document.createElement('div'); + s.className = 'card skeleton-card'; + s.innerHTML = ` +
+
+
+
+
+
`; + els.cards.appendChild(s); + } +} + +function setListPaneHidden(hidden) { + const pane = document.getElementById('listPane'); + if (pane) pane.classList.toggle('hidden', hidden); +} + +const LIST_ICONS = { + rename: '', + share: '', + offline: '', + offlineDone: '', + pin: '', + select: '', + del: '', +}; + +function listIconBtn(icon, label, onClick, extraClass) { + const b = document.createElement('button'); + b.type = 'button'; + b.className = 'list-icon-btn' + (extraClass ? ' ' + extraClass : ''); + b.title = label; + b.setAttribute('aria-label', label); + b.innerHTML = ``; + if (onClick) b.onclick = onClick; + return b; +} + +function setListIcon(btn, icon) { + btn.innerHTML = ``; +} + +function resetListHeaderExtras() { + $('listTitleActions').innerHTML = ''; + const fa = $('listFilterActions'); + fa.innerHTML = ''; + fa._del = null; + els.listTitle.onclick = null; + els.listTitle.onkeydown = null; + els.listTitle.classList.remove('title-clickable'); + els.listTitle.removeAttribute('role'); + els.listTitle.removeAttribute('tabindex'); + els.listTitle.removeAttribute('title'); +} + +function renderList() { + // Theme composition follows the real view without changing its controls. + els.cards.dataset.view = view.type; + resetListHeaderExtras(); + { const ls = $('listSub'); if (ls) ls.textContent = ''; const ps = $('p2pStrip'); if (ps) ps.classList.add('hidden'); } + if (view.type !== 'search') { const sm = $('searchMeta'); if (sm) sm.classList.add('hidden'); } + setListPaneHidden(view.type === 'search' && !searchResults.length && !searchAttempted && !els.placeholder.classList.contains('hidden')); + if (view.type === 'settings') { renderSettings(); return; } + if (view.type === 'saved') { renderSaved(); return; } + if (view.type === 'p2p') { renderP2pList(); return; } + if (view.type === 'savedSearches') { renderSavedSearches(); return; } + if (view.type === 'downloads') { renderDownloads(); return; } + if (view.type === 'stats') { renderStats(); return; } + if (view.type === 'notes') { renderNotesView(); return; } + if (view.type === 'library') { renderLibrary(); return; } + + // Filter bar — show for filterable views + const filterableViews = ['history', 'playlist', 'queue', 'channel', 'smart', 'nowPlaying']; + const showFilter = filterableViews.includes(view.type); + $('listFilterBar').classList.toggle('hidden', !showFilter); + $('batchBar').classList.toggle('hidden', !selectMode); + if (selectMode) $('batchCount').textContent = `${selectedIds.size} selected`; + // A channel's videos can be queued or added to a playlist, not deleted. + $('batchDeleteBtn').classList.toggle('hidden', view.type === 'channel'); + + // Build the list, applying filter if active + let list = currentList(); + if (listFilter && showFilter) { + const q = listFilter.toLowerCase(); + list = list.filter((v) => (v.title || '').toLowerCase().includes(q) || (v.channel || '').toLowerCase().includes(q)); + } + + els.cards.innerHTML = ''; + els.cards.classList.toggle('select-mode', selectMode); + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + + if (view.type === 'search' && WEB && els.placeholder.classList.contains('hidden')) { + Recommendations.inList(); + } + + if (view.type === 'nowPlaying') { + els.listTitle.textContent = 'Now playing'; + } else if (view.type === 'search') { + els.listTitle.textContent = 'Search results'; + } else if (view.type === 'history') { + els.listTitle.textContent = 'History'; + if (list.length) { + const clear = document.createElement('button'); + clear.textContent = 'Clear'; + clear.onclick = () => { data.history = []; persist(); renderList(); }; + els.listActions.appendChild(clear); + } + } else if (view.type === 'queue') { + els.listTitle.textContent = 'Queue'; + if (list.length) { + const playAll = document.createElement('button'); + playAll.textContent = '▶ Play queue'; + playAll.onclick = () => playQueue(0); + const clear = document.createElement('button'); + clear.textContent = 'Clear'; + clear.onclick = clearQueue; + els.listActions.append(playAll, clear); + } + } else if (view.type === 'smart') { + const sp = SMART_PLAYLISTS.find((s) => s.id === view.smartType); + els.listTitle.textContent = sp ? sp.label : 'Auto Playlist'; + if (list.length) { + const playAll = document.createElement('button'); + playAll.textContent = '▶ Play all'; + playAll.onclick = () => playFromList(list.slice(), 0, 'smart:' + view.smartType); + const queueAll = document.createElement('button'); + queueAll.textContent = '+ Queue all'; + queueAll.onclick = () => { list.forEach((v) => addToQueue(v, { quiet: true })); toast('Added to queue'); }; + els.listActions.append(playAll, queueAll); + } + } else if (view.type === 'channel') { + els.listTitle.textContent = channelData.name || 'Channel'; + if (list.length) { + const playAll = document.createElement('button'); + playAll.textContent = '▶ Play all'; + playAll.onclick = () => playFromList(channelData.results.slice(), 0, 'channel'); + const queueAll = document.createElement('button'); + queueAll.textContent = '+ Queue all'; + queueAll.onclick = () => { channelData.results.forEach((v) => addToQueue(v, { quiet: true })); toast('Added channel to queue'); }; + els.listActions.append(playAll, queueAll); + } + } else if (view.type === 'playlist') { + const pl = data.playlists.find((p) => p.id === view.id); + els.listTitle.textContent = pl ? pl.name : 'Playlist'; + if (pl) { + { const secs = (pl.videos || []).reduce((a, v) => a + (Number(v.duration) || 0), 0); + const h = Math.floor(secs / 3600), m = Math.round((secs % 3600) / 60); + $('listSub').textContent = `${pl.videos.length} track${pl.videos.length === 1 ? '' : 's'}${secs ? ' · ' + (h ? h + 'h ' : '') + m + 'm' : ''}`; } + renderP2pStrip(); + const playAll = document.createElement('button'); + playAll.textContent = '▶ Play all'; + playAll.className = 'la-primary'; + playAll.onclick = () => { if (pl.videos.length) playFromList(pl.videos, 0, 'playlist:' + pl.id); }; + const playFull = document.createElement('button'); + playFull.textContent = '▶ Play in full'; + playFull.className = 'la-main'; + playFull.dataset.sub = 'Start to finish'; + playFull.title = 'Play every video start to finish — ignores saved positions and A-B loops, stops after the last one'; + playFull.onclick = () => { + if (!pl.videos.length) return; + playFromList(pl.videos, 0, 'playlist:' + pl.id, { playFull: true }); + toast('Playing in full — stops after the last video'); + }; + const serviceBtn = document.createElement('button'); + serviceBtn.textContent = '🎤 Service mode'; + serviceBtn.className = 'la-main'; + serviceBtn.dataset.sub = 'Full lyrics'; + serviceBtn.title = 'Set-list view with screen wake lock'; + serviceBtn.onclick = () => { + if (!pl.videos || !pl.videos.length) { toast('Playlist is empty'); return; } + enterServiceMode(pl); + }; + const queueAll = document.createElement('button'); + queueAll.textContent = '+ Queue'; + queueAll.className = 'la-main'; + queueAll.dataset.sub = `+${pl.videos.length} items`; + queueAll.onclick = () => { pl.videos.forEach((v) => addToQueue(v, { quiet: true })); toast('Added playlist to queue'); }; + // Title row: a long name wraps; tapping it opens the rename modal, + // which also shows the full name. Rename + Share sit beside it as icons. + els.listTitle.classList.add('title-clickable'); + els.listTitle.setAttribute('role', 'button'); + els.listTitle.tabIndex = 0; + els.listTitle.title = 'Show full name / rename'; + els.listTitle.onclick = () => renamePlaylist(pl); + els.listTitle.onkeydown = (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); renamePlaylist(pl); } }; + const titleIcons = [listIconBtn('rename', 'Rename playlist', () => renamePlaylist(pl))]; + if (pl.videos && pl.videos.length >= 1) titleIcons.push(listIconBtn('share', 'Share playlist', () => sharePlaylist(pl))); + $('listTitleActions').append(...titleIcons); + + // Filter row icons: offline + pin show their state by colour alone. + const offlineBtn = listIconBtn('offline', 'Make available offline', () => makePlaylistOffline(pl)); + offlineBtn.id = 'plOfflineBtn'; + updatePlaylistOfflineButton(offlineBtn, pl); + + const isPinned = (data.pinnedPlaylists || []).includes(pl.id); + const pinBtn = listIconBtn('pin', isPinned ? 'Pinned for offline keep — tap to unpin' : 'Pin to keep this playlist available offline', () => togglePinPlaylist(pl)); + pinBtn.id = 'plPinBtn'; + pinBtn.classList.toggle('pinned', isPinned); + pinBtn.setAttribute('aria-pressed', String(isPinned)); + + const del = listIconBtn('del', 'Delete playlist', () => deletePlaylist(pl), 'danger'); + $('listFilterActions').append(offlineBtn, pinBtn); + els.listActions.append(playAll, playFull, serviceBtn, queueAll); + $('listFilterActions')._del = del; // appended after Select below + } + } + + // Select button for batch-operable views + const batchViews = ['history', 'playlist', 'queue', 'smart', 'channel']; + if (batchViews.includes(view.type) && list.length) { + const selBtn = listIconBtn('select', selectMode ? 'Stop selecting' : 'Select items', toggleSelectMode); + selBtn.classList.toggle('pinned', selectMode); + selBtn.setAttribute('aria-pressed', String(selectMode)); + $('listFilterActions').appendChild(selBtn); + } + { const fa = $('listFilterActions'); if (fa._del) { fa.appendChild(fa._del); fa._del = null; } } + + // Channel still loading — show skeletons. + if (view.type === 'channel' && channelData.loading && !list.length) { + showSearchSkeletons(); + return; + } + + if (!list.length) { + els.status.classList.add('hidden'); + els.cards.innerHTML = ''; + const empty = document.createElement('div'); + empty.className = 'empty-state'; + + if (view.type === 'search') { + // Landing (hero or playlist board) lives in the player pane. Before the + // first search this pane is hidden outright; after one that came back + // empty it stays visible so the result is legible. + els.status.classList.remove('hidden'); + els.status.textContent = searchAttempted + ? 'No results for that search.' + : 'Search for something to begin.'; + return; + } + + if (view.type === 'history') { + empty.innerHTML = ` +
🕘
+

Nothing watched yet

+

Your viewing history shows up here once you start playing videos.

+ `; + addBrowseCta(empty, '🔍 Search videos'); + } else if (view.type === 'queue') { + empty.innerHTML = ` +
▶
+

Your queue is empty

+

Use + Queue on any video to line it up. The queue is temporary and plays in order.

+ `; + addBrowseCta(empty, '🔍 Find something to play'); + } else if (view.type === 'channel') { + empty.innerHTML = ` +
📺
+

No videos found

+

This channel didn't return any uploads.

+ `; + addBrowseCta(empty, '🔍 Back to search'); + } else { + // Playlist view — empty + empty.innerHTML = ` +
🎵
+

This playlist is empty

+

Add videos from search results or use the + Playlist button while playing.

+ `; + addBrowseCta(empty, '🔍 Browse videos'); + } + + els.cards.appendChild(empty); + return; + } + els.status.classList.add('hidden'); + + list.forEach((v, i) => els.cards.appendChild(renderCard(v, i, list))); + markPlayingCard(); +} + +function addBrowseCta(empty, label) { + const cta = document.createElement('button'); + cta.className = 'empty-cta'; + cta.textContent = label; + cta.addEventListener('click', () => { view = { type: 'search' }; render(); }); + empty.appendChild(cta); +} + +async function renderP2pStrip() { + const box = $('p2pStrip'); + if (!box || document.documentElement.dataset.layout !== 'glass-stage' || !WEB || data.settings.p2pReceive === false) return; + if (!p2pStripData || Date.now() - p2pStripAt > 60000) { + try { const r = await fetch('/api/p2p/available?limit=3'); p2pStripData = r.ok ? await r.json() : null; } catch { p2pStripData = null; } + p2pStripAt = Date.now(); + } + if (view.type !== 'playlist') return; + const items = (p2pStripData && p2pStripData.ok && p2pStripData.items) || []; + if (!items.length) { box.classList.add('hidden'); return; } + const online = items.filter((i) => i.online).length; + box.innerHTML = `
On other devices
+

${items.length} video${items.length === 1 ? '' : 's'} held by other devices · ${online ? online + ' online now' : 'none online'}

`; + items.forEach((it) => { + const v = { id: it.id, title: it.title || videoTitleById(it.id) || it.id, channel: it.channel || '', duration: it.duration || 0, thumbnail: `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg` }; + const row = document.createElement('div'); + row.className = 'ps-row'; + row.innerHTML = '📡'; + row.querySelector('b').textContent = v.title; + row.querySelector('small').textContent = `${fmtBytes(it.size)}${it.height ? ' · ' + it.height + 'p' : ''} · ${it.online ? 'Online' : 'Offline'}`; + row.querySelector('.ps-dl').onclick = () => exportToDevice(v); + row.querySelector('.ps-txt').onclick = () => playFromList([v], 0, 'p2p'); + box.appendChild(row); + }); + box.classList.remove('hidden'); +} + +function fmtAgo(ts) { + const s = Math.max(0, (Date.now() - ts) / 1000); + if (s < 90) return 'just now'; + if (s < 3600) return Math.round(s / 60) + ' min ago'; + if (s < 86400) return Math.round(s / 3600) + ' h ago'; + return Math.round(s / 86400) + ' d ago'; +} + +function renderSavedSearches() { + els.listTitle.textContent = '📚 Saved searches'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + const c = els.cards; + c.innerHTML = ''; + const items = SearchLibrary.list(); + if (!items.length) { + c.innerHTML = '
📚

No saved searches yet

Every search you run is kept here with its thumbnails, even after you clear the search box. You can remove them in Settings.

'; + return; + } + const sum = document.createElement('div'); + sum.className = 'saved-summary'; + sum.innerHTML = `${items.length}saved search${items.length === 1 ? '' : 'es'} · ${fmtBytes(SearchLibrary.bytes())} · manage in Settings`; + c.appendChild(sum); + items.forEach((it) => { + const row = document.createElement('div'); + row.className = 'card saved-card ss-card'; + row.innerHTML = ` +
+
${it.count} result${it.count === 1 ? '' : 's'} · ${fmtAgo(it.ts)}
`; + row.querySelector('.card-title').textContent = it.query; + row.addEventListener('click', () => { + els.searchInput.value = it.query; + if (els.runSearch) els.runSearch(it.query); + }); + c.appendChild(row); + }); +} + +async function renderP2pList() { + els.listTitle.textContent = '📡 On other devices'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + const c = els.cards; + c.innerHTML = '
Looking for videos on other devices…
'; + let res = null; + try { const r = await fetch('/api/p2p/available?limit=100'); res = r.ok ? await r.json() : null; } catch { /* offline */ } + if (view.type !== 'p2p') return; + c.innerHTML = ''; + if (!res || !res.ok) { + c.innerHTML = '
📡

Not available

Peer-to-peer sharing is off on this server, or you are offline.

'; + return; + } + const items = res.items || []; + const list = items.map((it) => ({ + id: it.id, title: it.title || videoTitleById(it.id) || it.id, channel: it.channel || '', + duration: it.duration || 0, thumbnail: `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg`, + })); + const refresh = document.createElement('button'); + refresh.textContent = '↻'; + refresh.className = 'la-icon'; + refresh.title = 'Refresh'; + refresh.setAttribute('aria-label', 'Refresh'); + refresh.onclick = () => renderP2pList(); + const playAll = document.createElement('button'); + playAll.textContent = '▶ Play all'; + playAll.className = 'la-primary la-inline'; + playAll.onclick = () => { if (list.length) playFromList(list, 0, 'p2p'); }; + els.listActions.append(playAll, refresh); + if (!items.length) { + c.innerHTML = '
📡

Nothing shared yet

Videos that other devices have saved and verified show up here. Save a video and keep sharing on, and yours will appear for everyone else.

'; + return; + } + const online = items.filter((i) => i.online).length; + const sum = document.createElement('div'); + sum.className = 'saved-summary'; + sum.innerHTML = `${items.length}video${items.length === 1 ? '' : 's'} on other devices · ${online} with a device online now`; + c.appendChild(sum); + items.forEach((it, idx) => { + const v = list[idx]; + const row = document.createElement('div'); + row.className = 'card saved-card p2p-card'; + row.dataset.id = it.id; + const state = it.online ? `● ${it.online} online` : '○ none online'; + row.innerHTML = ` +
+
+
+
${state} · ${it.holders} device${it.holders === 1 ? '' : 's'} · ${fmtBytes(it.size)}${it.height ? ' · ' + it.height + 'p' : ''}${it.stale ? ' · not checked lately' : ''}
+
+ + `; + row.querySelector('.card-title').textContent = v.title; + row.addEventListener('click', (e) => { + const act = e.target.closest('[data-act]'); + if (act) { e.stopPropagation(); if (act.dataset.act === 'export') exportToDevice(v); else openCardMenu(v); return; } + playFromList(list, idx, 'p2p'); + }); + c.appendChild(row); + }); + markPlayingCard(); +} + +async function renderSaved() { + els.listTitle.textContent = 'Saved videos'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + $('batchBar').classList.add('hidden'); + const c = els.cards; + c.classList.remove('select-mode'); + c.innerHTML = '
Loading saved videos…
'; + + let res; + try { res = await API.cacheList(); } catch { res = null; } + if (view.type !== 'saved') return; // navigated away + + if (!res || !res.ok) { + $('listFilterBar').classList.add('hidden'); + c.innerHTML = ''; + const empty = document.createElement('div'); + empty.className = 'empty-state'; + empty.innerHTML = ` +
💾
+

Offline cache unavailable

+

This build doesn't support saving videos for offline playback.

`; + c.appendChild(empty); + return; + } + + const items = (res.items || []).slice().sort((a, b) => b.size - a.size); + const total = res.total || 0; + + if (!items.length) { + $('listFilterBar').classList.add('hidden'); + c.innerHTML = ''; + const empty = document.createElement('div'); + empty.className = 'empty-state'; + empty.innerHTML = ` +
💾
+

Nothing saved yet

+

Use ⬇ Save while playing, or add videos to a playlist to keep them offline.

`; + addBrowseCta(empty, '🔍 Find videos'); + c.appendChild(empty); + return; + } + + // Header actions: total + clear all. + const clearAll = document.createElement('button'); + clearAll.type = 'button'; + clearAll.className = 'saved-clear'; + clearAll.textContent = 'Clear all'; + clearAll.setAttribute('aria-label', 'Clear all saved videos'); + clearAll.onclick = () => { + showModal('Clear all saved videos?', document.createTextNode('Frees disk space. Normal videos re-download on demand, but edited videos are removed for good (they exist only here).'), [ + { label: 'Cancel', onClick: closeModal }, + { label: 'Clear all', danger: true, onClick: async () => { + try { + const result = await API.cacheClear(); + if (result?.ok === false) throw new Error(result.error || 'Storage could not be cleared'); + } catch { toast('Could not clear saved videos. Try again.'); closeModal(); return; } + cachedIds.clear(); + // Custom cuts live only in the cache — clearing it destroys their media, + // so drop their registry entries and playlist references too. + const customIds = new Set((data.customVideos || []).map((v) => v.id)); + if (customIds.size) { + data.customVideos = []; + data.playlists.forEach((pl) => { pl.videos = pl.videos.filter((x) => !customIds.has(x.id)); }); + data.queue = (data.queue || []).filter((x) => !customIds.has(x.id)); + persist(); + } + closeModal(); + toast('Cache cleared'); + if (current) updateNowPlayingActions(); + renderSaved(); + } }, + ]); + }; + + + c.innerHTML = ''; + const summary = document.createElement('div'); + summary.className = 'saved-summary saved-storage-summary'; + summary.innerHTML = `${fmtBytes(total)} · ${items.length} video${items.length === 1 ? '' : 's'} stored offline`; + summary.appendChild(clearAll); + $('listFilterBar').classList.remove('hidden'); + c.appendChild(summary); + + items.forEach((it) => { + const known = videoById(it.id); + // A custom (edited) id has no YouTube thumbnail; fall back to its source's + // thumbnail when we know it, else a neutral placeholder. + const isCustom = (known && known.custom) || String(it.id).startsWith('edit_'); + const fallbackThumb = isCustom ? '' : `https://i.ytimg.com/vi/${it.id}/mqdefault.jpg`; + const v = known || { id: it.id, title: videoTitleById(it.id), thumbnail: fallbackThumb }; + if (!SavedPage.matches(v, listFilter)) return; + const row = document.createElement('div'); + row.className = 'card saved-card' + (isCustom ? ' custom' : ''); + row.dataset.id = it.id; + row.innerHTML = ` +
${isCustom ? '✂' : ''}${isUploadId(v.id) ? `${v.kind === 'audio' ? '♪' : '📁'}` : ''}
+
+
+
${isCustom ? '✂ edited · ' : ''}${fmtBytes(it.size)}
+
`; + row.querySelector('.card-title').textContent = v.title || it.id; + row.addEventListener('click', (e) => { + if (e.target.closest('.saved-file-actions')) return; + playFromList([v], 0, 'saved'); + }); + SavedPage.actions(row, v, () => exportToDevice(v), () => { + showModal(`Delete saved file “${v.title || v.id}”?`, document.createTextNode(isCustom + ? 'This edited copy exists only on this device and will be removed permanently.' + : 'Frees space on this device. You can save this video again later.'), [ + { label: 'Cancel', onClick: closeModal }, + { label: 'Delete saved file', danger: true, onClick: async () => { + try { + const result = await API.cacheDelete(it.id); + if (result?.ok === false) throw new Error(result.error || 'Storage could not be updated'); + } catch { toast('Could not delete this saved file. Try again.'); closeModal(); return; } + cachedIds.delete(it.id); + if (isCustom) { + data.customVideos = (data.customVideos || []).filter(x => x.id !== it.id); + data.playlists.forEach(pl => { pl.videos = pl.videos.filter(x => x.id !== it.id); }); + data.queue = (data.queue || []).filter(x => x.id !== it.id); + persist(); + } + if (current?.meta?.id === it.id) updateNowPlayingActions(); + markCardCacheState(it.id, 'none'); closeModal(); + toast('Removed saved file'); renderSaved(); + } }, + ]); + }); + c.appendChild(row); + }); + if (!c.querySelector('.saved-card')) { + const message = document.createElement('p'); message.className = 'status'; + message.textContent = 'No saved videos match your filter.'; c.appendChild(message); + } + markPlayingCard(); +} + +function renderDownloads() { + els.listTitle.textContent = 'Downloads'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + const c = els.cards; + c.innerHTML = ''; + $('listFilterBar').classList.toggle('hidden', !Downloads.getJobs().length); + $('batchBar').classList.add('hidden'); + c.classList.remove('select-mode'); + + if (window.DownloadsPage && window.DownloadsPage.render) { + window.DownloadsPage.render(c, { + downloadsApi: window.Downloads, + filter: listFilter, + isActive: () => view.type === 'downloads', + showModal: typeof showModal === 'function' ? showModal : null, + closeModal: typeof closeModal === 'function' ? closeModal : null, + onNavigateSaved: () => { view = { type: 'saved' }; render(); }, + thumbUrlFor: typeof thumbUrlFor === 'function' ? thumbUrlFor : null, + refresh: renderList + }); + } + + const jobs = window.Downloads && window.Downloads.getJobs ? window.Downloads.getJobs() : []; + jobs.filter(j => j.status === 'active' || j.status === 'queued').forEach(v => { + if (typeof SaveQueue !== 'undefined' && SaveQueue.progress) { + SaveQueue.progress(v.id, SaveQueue.get(v.id)); + } + }); +} + +async function renderSettings() { + els.listTitle.textContent = 'Settings'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + const c = els.cards; + els.status.classList.add('hidden'); + c.innerHTML = ''; + + const wrap = document.createElement('div'); + wrap.className = 'settings'; + + // ---- Playback ---- + const qualities = ['auto', '1080p', '720p', '480p', '360p', '240p']; + const qOptions = qualities + .map((q) => ``) + .join(''); + + const sel = (id, val, opts) => ``; + + wrap.innerHTML = ` +
+
Appearance & accessibility
+ + + + + + +
+ +
+
Playback
+ + + + + ${EQ.isIOS() ? `` : ''} + + + + +
+ +
+
Sharing (peer-to-peer)
+ + +
+ This device… + … +
+ +
+ +
+
Offline cache
+ + +
+ Storage used + … +
+ +
+ +
+
+ Saved videos +
+
+
+ +
+
Saved searches
+
+ + Kept on this device + Search results and their thumbnails stay saved after you clear the search box. Only you can remove them, here. + + … +
+
+ + + +
+
+
+ +
+
Playlists
+
+ + + + +
+
+ +
+
Backup & restore
+ + +
+ + + +
+
+ +
+
Reset
+
+ + Force refresh UI + Re-fetches the app shell and assets, bypassing the browser cache, then reloads. + +
+ +
+
+
+ + Reset app + Clears all local storage, unregisters the service worker, and deletes every cache. You will need to reload after. + +
+ +
+
+
+ +
+
Online profile — sync between devices
+
+ + Linked profile + Playlists, history and settings sync to the server under this name. The name works like a passkey — anyone who knows it can load and change this data, so prefer a random one. + + ${data.profile && data.profile.name ? data.profile.name : 'Not linked'} +
+
+ + Profile link + Open this URL on another device to load the profile there. Anyone with the link gets full access to this data — share it only with your own devices or people you trust. + + ${escapeHtml(profileShareUrl() || '')} +
+
+ + + + + + + + + +
+
+ +
+
About
+
+ + Version + App version and current build. + +
+ v${APP_VERSION} +
+
+
+ + Build time + When the running server build was produced — compare across devices to confirm you're on the latest version. + + … +
+
`; + + c.appendChild(wrap); + const definitions = [ + ['appearance', 'Appearance', 'Listening', () => `${data.settings.theme || 'dark'} · ${data.settings.fontScale || 'normal'} text`, ''], + ['playback', 'Playback & sound', 'Listening', () => `${data.settings.quality || 'auto'} quality · ${Level.enabled() ? 'Levelled volume' : 'Original volume'}`, ''], + ['sharing', 'Sharing', 'Library & storage', () => data.settings.p2pShare !== false ? 'Sharing saved videos' : 'Sharing off', ''], + ['offline', 'Offline storage', 'Library & storage', () => `${SaveSlots.limit ? SaveSlots.limit() : Number(data.settings.parallelSaves) || 4} at once · ${$('cacheTotal')?.textContent || 'Checking storage'}`, ''], + ['searches', 'Saved searches', 'Library & storage', () => `${SearchLibrary.list().length} saved searches`, ''], + ['playlists', 'Playlists', 'Library & storage', () => `${data.playlists.length} playlists`, ''], + ['backup', 'Backup & restore', 'Account & sync', () => data.settings.autoBackupEnabled ? 'Scheduled backup on' : 'Manual backups', ''], + ['reset', 'Refresh & reset', 'Advanced & about', () => 'Refresh the app or clear device data', ''], + ['profile', 'Profile & sync', 'Account & sync', () => data.profile?.name || 'Not linked', ''], + ['about', 'About', 'Advanced & about', () => `Version ${APP_VERSION}`, ''], + ]; + const groups = [...wrap.querySelectorAll(':scope > .set-group')]; + definitions.forEach(([id, title, cluster, summary, icon], i) => SettingsSections.register({ id, title, cluster, summary, icon, render(container) { container.append(groups[i]); } })); + SettingsSections.register({ id: 'video-fullscreen', title: 'Video & fullscreen', cluster: 'Listening', icon: '', summary: () => `Fullscreen: ${FullscreenOrientation.normalize(data.settings.fullscreenOrientation)}`, render(container) { + const row = document.createElement('label'); row.className = 'set-row'; + row.innerHTML = 'Fullscreen orientation'; + const select = row.querySelector('select'); select.value = FullscreenOrientation.normalize(data.settings.fullscreenOrientation); + select.onchange = () => { data.settings.fullscreenOrientation = select.value; persist(); }; + container.append(row); + } }); + SettingsSections.mount(wrap, { settings: data.settings, data, persist, toast }); + + // ---- Wire appearance / accessibility ---- + $('setTheme').addEventListener('change', (e) => { data.settings.theme = e.target.value; applyAppearance(); persist(); }); + $('setLayout').addEventListener('change', async (e) => { + const select=e.target, next=select.value, previous=data.settings.layout; select.disabled=true; + try { await Lazy.load('layout:'+next); data.settings.layout=next; Lazy.layout=next; if(WEB)saveDataToStorage(JSON.stringify(data)); applyAppearance(); persist(); Lazy.reportLayout?.(); } + catch(error) { select.value=previous; toast(error.message); } + finally { select.disabled=false; } + }); + $('setFont').addEventListener('change', (e) => { data.settings.fontScale = e.target.value; applyAppearance(); persist(); }); + $('setParallelSaves').addEventListener('change', (e) => { data.settings.parallelSaves = Number(e.target.value) || 4; persist(); SaveSlots.pump(); }); + $('setDensity').addEventListener('change', (e) => { data.settings.density = e.target.value; applyAppearance(); persist(); }); + $('setPerf').addEventListener('change', (e) => { data.settings.perfMode = e.target.checked; applyAppearance(); persist(); }); + $('setMotion').addEventListener('change', (e) => { data.settings.reduceMotion = e.target.checked; applyAppearance(); persist(); }); + $('setRepeat').addEventListener('change', (e) => { data.settings.repeatMode = e.target.checked ? 'all' : 'off'; updateLoopRepeatButtons(); persist(); }); + $('setLoopOne').addEventListener('change', (e) => { data.settings.loopOne = e.target.checked; updateLoopRepeatButtons(); persist(); }); + $('setLevelVolume').addEventListener('change', (e) => { + data.settings.levelVolume = e.target.checked; + persist(); + if (current && current.meta) Level.onTrack(current.meta); else EQ.setLevel(0); + EqRender.scheduleAll(); + }); + if ($('setLiveAudioIOS')) $('setLiveAudioIOS').addEventListener('change', (e) => { + data.settings.liveAudioIOS = e.target.checked; + persist(); + EQ.apply(); + if (current && current.meta) Level.onTrack(current.meta); + if (e.target.checked) toast('Live sound processing on — streamed songs go silent when the screen locks', { duration: 4500 }); + }); + + + // ---- Saved searches manager ---- + { + const listEl = $('ssList'); + const sel = new Set(); + const refresh = () => { + const items = SearchLibrary.list(); + for (const k of [...sel]) if (!items.some((i) => i.key === k)) sel.delete(k); + $('ssTotal').textContent = items.length ? `${items.length} · ${fmtBytes(SearchLibrary.bytes())}` : 'None'; + listEl.innerHTML = items.length ? items.map((i) => ` + `).join('') : '
No saved searches.
'; + $('ssDeleteSel').disabled = !sel.size; + $('ssDeleteSel').textContent = sel.size ? `Delete selected (${sel.size})` : 'Delete selected'; + $('ssSelectAll').textContent = items.length && sel.size === items.length ? 'Select none' : 'Select all'; + $('ssClearAll').disabled = !items.length; + }; + listEl.addEventListener('change', (e) => { const k = e.target.dataset && e.target.dataset.k; if (!k) return; e.target.checked ? sel.add(k) : sel.delete(k); refresh(); }); + $('ssSelectAll').addEventListener('click', () => { + const items = SearchLibrary.list(); + if (sel.size === items.length) sel.clear(); else items.forEach((i) => sel.add(i.key)); + refresh(); + }); + $('ssDeleteSel').addEventListener('click', () => { + if (!sel.size || !confirm(`Delete ${sel.size} saved search${sel.size === 1 ? '' : 'es'}? Their results and thumbnails are removed from this device.`)) return; + SearchLibrary.remove([...sel]); sel.clear(); refresh(); toast('Saved searches deleted'); + }); + $('ssClearAll').addEventListener('click', () => { + if (!confirm('Delete ALL saved searches and their thumbnails from this device?')) return; + SearchLibrary.clear(); sel.clear(); refresh(); toast('All saved searches deleted'); + }); + refresh(); + } + + // ---- Wire playback controls ---- + $('setQuality').addEventListener('change', (e) => { + data.settings.quality = e.target.value; + els.quality.value = e.target.value; + persist(); + }); + $('setVolume').addEventListener('input', (e) => { + data.settings.volume = parseFloat(e.target.value); + els.volume.value = e.target.value; + Player.applyVolume(); + syncMuteIcon(); + persist(); + }); + $('setAudioOnly').addEventListener('change', (e) => { + data.settings.audioOnly = e.target.checked; + els.audioOnlyToggle.checked = e.target.checked; + persist(); + }); + $('setSaveBeforePlay').addEventListener('change', (e) => { + data.settings.saveBeforePlay = e.target.checked; + persist(); + }); + $('setLyricFlags').addEventListener('change', (e) => { + data.settings.lyricFlags = e.target.checked; + persist(); + Notes.refreshFlags(); + }); + $('setAutoPreload').addEventListener('change', (e) => { + data.settings.autoPreload = e.target.checked; + persist(); + if (e.target.checked) data.playlists.forEach(preloadPlaylist); + }); + $('setP2pShare').addEventListener('change', (e) => { + data.settings.p2pShare = e.target.checked; + persist(); + if (window.P2PClient) window.P2PClient.sync(); // share off → withdraws every holding + }); + $('setP2pReceive').addEventListener('change', (e) => { + data.settings.p2pReceive = e.target.checked; + persist(); + if (window.P2PClient) window.P2PClient.sync(); + }); + (async () => { + const info = $('p2pDeviceInfo'); + const cnt = $('p2pHoldingCount'); + if (!info || !cnt) return; + const P = window.P2PClient; + const d = P && P.device(); + info.textContent = !d ? 'Not registered yet' + : P.isConnected() ? `Online · peer ${P.peer()}` : 'Registered · not connected'; + const files = window.DeviceDB ? await window.DeviceDB.listFiles() : []; + cnt.textContent = `${files.filter((f) => f.state === 'verified').length} verified / ${files.length} saved`; + const unknown = window.P2PClient ? await window.P2PClient.unknownVideos() : []; + const row = $('p2pContributeRow'); + const btn = $('p2pContributeBtn'); + if (row && btn && unknown.length) { + row.classList.remove('hidden'); + btn.textContent = `Verify & share ${unknown.length} saved video${unknown.length === 1 ? '' : 's'}`; + btn.onclick = async () => { + btn.disabled = true; + let ok = 0; + for (let i = 0; i < unknown.length; i++) { + const v = videoById(unknown[i]) || {}; + btn.textContent = `Uploading ${i + 1} of ${unknown.length}…`; + const r = await window.P2PClient.contribute(unknown[i], { title: v.title || '', channel: v.channel || '' }); + if (r && r.ok) ok++; + } + toast(`Verified ${ok} of ${unknown.length} saved video${unknown.length === 1 ? '' : 's'}`); + btn.disabled = false; + row.classList.add('hidden'); + }; + } + })(); + + // ---- Cache management ---- + $('clearCacheBtn').addEventListener('click', () => { + showModal('Clear all cached videos?', document.createTextNode('This frees disk space. Playlists keep their entries and will re-download on demand.'), [ + { label: 'Cancel', onClick: closeModal }, + { + label: 'Clear all', danger: true, onClick: async () => { + try { await API.cacheClear(); } catch {} + cachedIds.clear(); + closeModal(); + toast('Cache cleared'); + if (current) updateNowPlayingActions(); + renderList(); + }, + }, + ]); + }); + + // The saved-videos list folds; remember how the user left it. + { + const fold = $('cacheFold'); + try { fold.open = localStorage.getItem('ytpCacheFoldOpen') === '1'; } catch { /* blocked */ } + fold.addEventListener('toggle', () => { try { localStorage.setItem('ytpCacheFoldOpen', fold.open ? '1' : '0'); } catch { /* blocked */ } }); + } + + // ---- Populate live cache stats ---- + try { + const res = await API.cacheList(); + if (view.type !== 'settings') return; // user navigated away + const total = (res && res.total) || 0; + const items = (res && res.items) || []; + $('cacheTotal').textContent = `${fmtBytes(total)} · ${items.length} video${items.length === 1 ? '' : 's'}`; + $('cacheFoldCount').textContent = items.length ? `${items.length} · ${fmtBytes(total)}` : 'none'; + const listEl = $('cacheList'); + if (!items.length) { + listEl.innerHTML = '
No videos saved offline yet.
'; + } else { + items.sort((a, b) => b.size - a.size); + items.forEach((it) => { + const row = document.createElement('div'); + row.className = 'cache-item'; + row.innerHTML = `${fmtBytes(it.size)}`; + row.querySelector('.ci-title').textContent = videoTitleById(it.id); + row.querySelector('.ci-del').addEventListener('click', async () => { + try { await API.cacheDelete(it.id); } catch {} + cachedIds.delete(it.id); + if (current && current.meta && current.meta.id === it.id) updateNowPlayingActions(); + toast('Removed from cache'); + renderList(); + }); + listEl.appendChild(row); + }); + } + } catch { + const t = $('cacheTotal'); + if (t) t.textContent = 'Offline cache not available in this build'; + } + + // ---- Cache cap ---- + const capSel = $('cacheCapSelect'); + capSel.value = String(data.settings.cacheCap || 0); + capSel.addEventListener('change', (e) => { + data.settings.cacheCap = parseInt(e.target.value) || 0; + persist(); + }); + + // ---- Export / Import playlists ---- + $('importYtBtn')?.addEventListener('click', openImportYouTubeModal); + $('exportBtn').addEventListener('click', exportPlaylists); + $('importBtn').addEventListener('click', () => $('fileInput').click()); + $('fileInput').addEventListener('change', importPlaylists); + + // ---- Backup ---- + $('setAutoBackup').addEventListener('change', (e) => { data.settings.autoBackupEnabled = e.target.checked; persist(); }); + $('setBackupInterval').addEventListener('change', (e) => { data.settings.autoBackupIntervalDays = parseInt(e.target.value) || 7; persist(); }); + $('backupNowBtn').addEventListener('click', () => doAutoBackup()); + $('importBackupBtn').addEventListener('click', () => $('backupFileInput').click()); + $('backupFileInput').addEventListener('change', importBackup); + + // ---- Online profile ---- + $('profileCreateBtn').addEventListener('click', createProfileFlow); + $('profileLoadBtn').addEventListener('click', loadProfileFlow); + $('profileCopyLinkBtn').addEventListener('click', copyProfileLink); + $('profileShareBtn').addEventListener('click', shareProfileLink); + $('profileProtectBtn').addEventListener('click', protectProfileFlow); + $('profileExportCredBtn').addEventListener('click', exportProfileCredentials); + $('profileImportCredBtn').addEventListener('click', importProfileCredentials); + $('profileUnlinkBtn').addEventListener('click', () => { + data.profile = null; + ProfileSecret.clear(); + persist(); + updateProfileStatus(); + toast('Profile unlinked — this device stops syncing (server copy is kept)'); + }); + updateProfileStatus(); + + // ---- About: append server build tag + build time (WEB mode only) ---- + if (WEB) { + try { + const res = await fetch('/api/version', { cache: 'no-store' }); + if (res.ok && view.type === 'settings') { + const v = await res.json(); + const el = $('aboutVersion'); + if (el && v.buildTag) el.textContent = `v${v.version || APP_VERSION} · build ${v.buildTag}`; + const bt = $('aboutBuildTime'); + if (bt) { + const t = v.buildTime ? new Date(v.buildTime) : null; + if (t && !isNaN(t)) { + // Shown in GMT+8 regardless of device/server timezone, plus build age. + const gmt8 = new Date(t.getTime() + 8 * 3600e3).toISOString().replace('T', ' ').slice(0, 16); + const s = Math.max(0, Math.floor((Date.now() - t.getTime()) / 1000)); + const ago = s < 60 ? `${s} second${s === 1 ? '' : 's'} ago` + : s < 3600 ? `${Math.floor(s / 60)} minute${Math.floor(s / 60) === 1 ? '' : 's'} ago` + : s < 86400 ? `${Math.floor(s / 3600)} hour${Math.floor(s / 3600) === 1 ? '' : 's'} ago` + : `${Math.floor(s / 86400)} day${Math.floor(s / 86400) === 1 ? '' : 's'} ago`; + bt.textContent = `${gmt8} +08 · built ${ago}`; + } else { + bt.textContent = 'unknown'; + } + } + } + } catch { /* offline — leave the static version in place */ } + } + + // ---- Reset ---- + $('refreshUiBtn').addEventListener('click', async () => { + const btn = $('refreshUiBtn'); + btn.disabled = true; + btn.textContent = 'Refreshing…'; + // hardReloadUI() deletes all caches and unregisters the SW so the + // next page load always fetches fresh assets from the network. + await hardReloadUI(); + }); + + $('resetAppBtn').addEventListener('click', () => { + showModal( + 'Reset app?', + (() => { const p = document.createElement('p'); p.textContent = 'This clears all local data and caches. The page will reload.'; return p; })(), + [ + { label: 'Cancel', onClick: closeModal }, + { + label: 'Reset', danger: true, onClick: async () => { + closeModal(); + try { + localStorage.clear(); + sessionStorage.clear(); + if ('serviceWorker' in navigator) { + const regs = await navigator.serviceWorker.getRegistrations(); + await Promise.all(regs.map((r) => r.unregister())); + } + if ('caches' in window) { + const keys = await caches.keys(); + await Promise.all(keys.map((k) => caches.delete(k))); + } + } catch { /* best effort — reload regardless */ } + window.location.href = '/'; + }, + }, + ], + ); + }); +} + +function renderCard(v, index, list) { + const card = document.createElement('div'); + const isCached = cachedIds.has(v.id); + const isDownloading = downloading.has(v.id); + card.className = 'card' + (isCached ? ' cached' : '') + (isDownloading ? ' downloading' : '') + (selectedIds.has(v.id) ? ' selected' : ''); + card.dataset.id = v.id; + card._video = v; // read by f7-layout.js swipe actions + card.innerHTML = ` +
+
+ + ${v.duration ? `${fmtTime(v.duration)}` : ''} + ${isDownloading ? '' : '⬇'} + ${isDownloading ? '
' : ''} +
+
+
+
+
+ `; + card.querySelector('.card-title').textContent = v.title; + const chEl = card.querySelector('.card-channel'); + chEl.textContent = v.channel || ''; + if (channelKeyOf(v)) { + chEl.classList.add('link'); + chEl.title = 'View channel'; + chEl.addEventListener('click', (e) => { + e.stopPropagation(); + openChannel(channelKeyOf(v), v.channel); + }); + } + + // Playlist view: note under title (if present) and note edit button (Section 5) + if (view.type === 'playlist') { + const hasNote = !!(v.notes && v.notes.trim()); + if (hasNote) { + const noteEl = document.createElement('div'); + noteEl.className = 'card-note'; + noteEl.textContent = v.notes.trim(); + noteEl.title = v.notes.trim(); + const titleEl = card.querySelector('.card-title'); + if (titleEl) titleEl.after(noteEl); + } + + const noteBtn = document.createElement('button'); + noteBtn.type = 'button'; + noteBtn.className = 'card-note-btn' + (hasNote ? ' has-note' : ''); + noteBtn.title = hasNote ? 'Edit note' : 'Add note'; + noteBtn.textContent = '✎'; + noteBtn.addEventListener('click', (e) => { + e.stopPropagation(); + openSongNoteModal(v); + }); + const menuBtn = card.querySelector('.card-menu'); + card.insertBefore(noteBtn, menuBtn); + } + + card.addEventListener('pointerdown', () => warmStreams([v.id]), { passive: true }); + card.addEventListener('click', (e) => { + if (e.target.closest('.card-menu') || e.target.closest('.card-del') || e.target.closest('.card-note-btn') || e.target.closest('.card-channel.link')) return; + if (selectMode) { toggleSelectCard(v.id); return; } + playFromList(list, index, view.type === 'playlist' ? 'playlist:' + view.id : view.type === 'nowPlaying' ? queueSource : view.type); + }); + card.querySelector('.card-menu').addEventListener('click', (e) => { + e.stopPropagation(); + openCardMenu(v); + }); + + // Per-item delete in playlist, queue, history, and smart views. + if (view.type === 'playlist' || view.type === 'queue' || view.type === 'history' || view.type === 'smart') { + const del = document.createElement('button'); + del.className = 'card-del'; + del.title = view.type === 'queue' ? 'Remove from queue' + : (view.type === 'history' || view.type === 'smart') ? 'Remove from history' + : 'Remove from playlist'; + del.textContent = '✕'; + del.addEventListener('click', (e) => { + e.stopPropagation(); + if (view.type === 'queue') { removeFromQueue(v.id); return; } + if (view.type === 'history' || view.type === 'smart') { + data.history = data.history.filter((x) => x.id !== v.id); + persist(); + renderList(); + return; + } + const pl = data.playlists.find((p) => p.id === view.id); + if (pl) { pl.videos = pl.videos.filter((x) => x.id !== v.id); persist(); render(); toast('Removed from playlist'); } + }); + card.appendChild(del); + } + + // Drag-to-reorder in playlist and queue views + if (view.type === 'playlist' || view.type === 'queue') { + card.draggable = true; + card.addEventListener('dragstart', () => { + card.classList.add('dragging'); + dragSource = index; + }); + card.addEventListener('dragend', () => { + card.classList.remove('dragging'); + }); + card.addEventListener('dragover', (e) => { + e.preventDefault(); + card.classList.add('drag-over'); + }); + card.addEventListener('dragleave', () => { + card.classList.remove('drag-over'); + }); + card.addEventListener('drop', (e) => { + e.preventDefault(); + card.classList.remove('drag-over'); + const from = dragSource; + const to = index; + if (from === to || from < 0) return; + const arr = view.type === 'queue' + ? data.queue + : (data.playlists.find((p) => p.id === view.id) || {}).videos; + if (!arr) return; + const [moved] = arr.splice(from, 1); + arr.splice(to, 0, moved); + if (view.type === 'queue' && queueSource === 'queue') { + const playingId = current && current.meta && current.meta.id; + queue = data.queue.slice(); + queueIndex = playingId ? queue.findIndex((x) => x.id === playingId) : queueIndex; + renderUpNext(); + } + persist(); + renderList(); + }); + } + + return card; +} + +function markPlayingCard() { + document.querySelectorAll('.card').forEach((c) => { + c.classList.toggle('playing', current && c.dataset.id === current.meta.id); + }); +} + +function renderRelated() { + const panel = $('relatedPanel'), list = $('relatedList'); + if (!panel || !list || (relatedState.status === 'idle' && !relatedVideos.length)) { if (panel) panel.classList.add('hidden'); return; } + panel.classList.remove('hidden'); + list.classList.toggle('hidden', relatedCollapsed); + list.innerHTML = ''; + if (relatedState.message) { + const notice = document.createElement('div'); notice.className = 'related-notice'; notice.setAttribute('role', 'status'); + const message = document.createElement('p'); message.textContent = relatedState.message; notice.append(message); + if (relatedState.status === 'error') { + const retry = document.createElement('button'); retry.type = 'button'; retry.className = 'related-retry'; retry.setAttribute('aria-label', 'Retry related videos'); + retry.innerHTML = 'Retry'; + retry.onclick = () => loadRelated({ refresh: true }); notice.append(retry); + } + list.append(notice); + } + relatedVideos.forEach((v) => { + const item = document.createElement('div'); + item.className = 'related-item'; + item.innerHTML = `
`; + item.querySelector('.ri-title').textContent = v.title; + const riChEl = item.querySelector('.ri-channel'); + riChEl.textContent = v.channel || ''; + if (channelKeyOf(v)) { + riChEl.classList.add('link'); + riChEl.title = 'View channel'; + riChEl.addEventListener('click', (e) => { e.stopPropagation(); openChannel(channelKeyOf(v), v.channel); }); + } + item.addEventListener('click', (e) => { + if (e.target.closest('.ri-channel.link')) return; + queue = [v]; queueIndex = 0; playFullMode = false; Player.loadVideo(v); renderUpNext(); + }); + list.appendChild(item); + }); +} diff --git a/perf/seams.mjs b/perf/seams.mjs new file mode 100644 index 0000000..e661828 --- /dev/null +++ b/perf/seams.mjs @@ -0,0 +1,70 @@ +#!/usr/bin/env node +// Phase 3 checks against the real Bun server, a same-origin restart and real workers. +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { mkdtempSync, cpSync, mkdirSync, symlinkSync, readFileSync, writeFileSync, rmSync } from 'node:fs'; +import { resolve, join } from 'node:path'; +import { createServer } from 'node:net'; +import { chromium, webkit } from 'playwright'; +import { createThrottleProxy } from './proxy.mjs'; +const repo=resolve(new URL('..',import.meta.url).pathname), scratch=mkdtempSync(join(repo,'perf/.tmp/seams-')); +const sleep=ms=>new Promise(r=>setTimeout(r,ms)); +async function wait(page,fn,arg,timeout=90000){const end=Date.now()+timeout;while(Date.now()portServer.listen(0,'127.0.0.1',r));const port=portServer.address().port;await new Promise(r=>portServer.close(r)); + let child,browser,proxy,log=''; + async function stop(){if(!child)return;const p=child;child=null;if(p.exitCode===null){p.kill('SIGTERM');await new Promise(r=>p.once('exit',r));}} + async function start(){log='';child=spawn('bun',[join(repo,'server/server.js')],{cwd,env:{...process.env,PORT:String(port),ASSET_HASHING:'1',ASSET_SYNC:'1',BUILD_TAG:'',DB_PATH:join(cwd,'db.sqlite'),DATA_DIR:join(cwd,'data'),MEDIA_DIR:join(cwd,'media'),UPLOAD_DIR:join(cwd,'uploads')},stdio:['ignore','pipe','pipe']});for(const stream of [child.stdout,child.stderr])stream.on('data',c=>log=(log+c).slice(-15000));for(let i=0;i<200;i++){if(child.exitCode!==null)throw Error(log);try{if((await fetch('http://127.0.0.1:'+port+'/api/version')).ok)return;}catch{}await sleep(100);}throw Error(log);} + try { + await start();proxy=createThrottleProxy({targetPort:port,profile:'unthrottled'});const origin='http://127.0.0.1:'+await proxy.listen();proxy.startTracking(); + browser=await ({chromium,webkit}[name]).launch({headless:true});const context=await browser.newContext(); + await context.route('**/*',r=>r.request().url().startsWith(origin)?r.continue():r.abort()); + await context.addInitScript(()=>{Object.defineProperty(navigator,'onLine',{configurable:true,get:()=>!window.__offline});}); + const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message)); + await page.goto(origin);await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn')); + await wait(page,async()=>!!(await navigator.serviceWorker.getRegistration())?.active); + await page.evaluate(()=>Lazy.warm()); + await wait(page,async()=>{const c=await caches.open('ytplayer-assets'),r=await c.match('/__ytp_asset_state');if(!r)return false;const s=await r.json();return !(await Promise.all(Object.values(s.current.groups).flatMap(g=>g.files).map(async p=>!!await c.match(p+'?v='+s.current.files[p].h)))).includes(false);}); + await page.reload();await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn')); + await page.evaluate(()=>{window.__offline=true;window.__shellBuild=document.querySelector('meta[name="ytp-build"]').content;}); + await stop();await proxy.setOffline(true);const before=proxy.getStats().requestCount; + await page.evaluate(()=>{data.playlists=[{id:'smoke',name:'Cached playlist',videos:[]}];render();}); + assert.equal(await page.locator('#homePlGrid .home-pl-name').textContent(),'Cached playlist'); + await page.click('[data-view="settings"]');await page.waitForSelector('.settings'); + await page.evaluate(()=>{view={type:'search'};render();}); + const groups=await page.evaluate(()=>Object.keys(Lazy.manifest.groups)); + const checked=['shell']; + if(groups.includes('feature:presenter')) { + await page.evaluate(async()=>{history.replaceState(null,'','/?present=');await Presenter.boot();}); + await page.waitForSelector('#presenterView:not(.hidden)');await page.keyboard.press('b'); + assert.equal(await page.locator('#pvBlank').evaluate(n=>!n.classList.contains('hidden')),true); + await page.evaluate(()=>{document.querySelector('#presenterView').classList.add('hidden');document.body.classList.remove('presenter-open');});checked.push('presenter'); + } + if(groups.includes('feature:remote-client')) { + await page.evaluate(()=>document.querySelector('#navRemoteBtn').click()); + await page.waitForSelector('#modal:not(.hidden)');assert.match(await page.locator('#modal').textContent(),/remote|screen|phone/i); + await page.evaluate(()=>closeModal());checked.push('remote'); + } + if(groups.includes('feature:watch-party')) { + await page.evaluate(()=>document.querySelector('#navPartyBtn').click());await page.waitForSelector('#partyPanel:not(.hidden)'); + await page.locator('.pt-name').fill('Cached guest');assert.equal(await page.locator('.pt-name').inputValue(),'Cached guest');checked.push('party'); + } + if(groups.includes('feature:share-external')) { + await page.evaluate(async()=>{current={meta:{id:'benchmedia01',title:'Cached smoke',channel:'Fixture'}};await Share.open();}); + await page.waitForSelector('.share-moment');assert.match(await page.locator('#modal').textContent(),/Cached smoke/); + const m3u=await page.evaluate(async()=>{await Lazy.load('feature:share-external');return window.YT.External.m3u([{id:'benchmedia01',title:'Cached smoke'}]);});assert.match(m3u,/#EXTM3U/);assert.match(m3u,/benchmedia01/); + await page.evaluate(()=>closeModal());checked.push('share'); + } + if(groups.includes('feature:stats-view')) { + await page.evaluate(async()=>{view={type:'stats'};await renderStats();});await page.waitForSelector('.stats-empty');checked.push('stats'); + } + assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network'); + // Ignore only verified disconnected version/recommendation API transports in WebKit. + const scriptErrors=errors.filter(e=>!(name==='webkit'&&(e==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(e))));assert.deepEqual(scriptErrors,[]); + results.push({browser:name,checked,offlineNetworkRequests:proxy.getStats().requestCount-before,errors:scriptErrors});console.log(name,JSON.stringify(results.at(-1))); + }finally{await browser?.close();await stop();await proxy?.close();} +} +try{for(const name of requested==='all'?['chromium','webkit']:[requested])await run(name);writeFileSync(join(repo,'perf/results/phase4-seams-2026-10-08.json'),JSON.stringify(results,null,2)+'\n');}finally{rmSync(scratch,{recursive:true,force:true});} From 5fb95644689266e009d3595a1e0bf3029988661e Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:39:52 +0800 Subject: [PATCH 33/81] Load the presenter client only on presenter entry --- frontend/app.js | 217 ++---------------------------------------- frontend/assets.json | 8 ++ frontend/index.html | 2 +- frontend/lazy.js | 3 +- frontend/lazy.test.js | 8 ++ frontend/presenter.js | 210 ++++++++++++++++++++++++++++++++++++++++ frontend/sw.js | 1 + 7 files changed, 238 insertions(+), 211 deletions(-) create mode 100644 frontend/presenter.js diff --git a/frontend/app.js b/frontend/app.js index b29e6d3..b3b8088 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -5971,215 +5971,14 @@ async function renderStats() { // like a phone, but only listens: the host's state messages carry the song id, // position, speed and lyric offset, and this view extrapolates the position // between updates. Lyrics come from the shared /api/notes store. -const Presenter = (() => { - const noop = { boot() {}, active: () => false }; - const view = $('presenterView'); - if (!WEB || !view || typeof WebSocket === 'undefined') return noop; - const overlay = LowerThird.active(); - const KEY = overlay ? `ytpOverlayPair:${new URLSearchParams(location.search).get('code') || ''}` : 'ytpPresenterPair'; - const load = () => { try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch { return null; } }; - const save = (v) => { try { if (v) localStorage.setItem(KEY, JSON.stringify(v)); else localStorage.removeItem(KEY); } catch { /* blocked */ } }; - const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/remote?${new URLSearchParams(q)}`; - const list = $('pvList'); - const st = { ws: null, state: null, stateAt: 0, hostName: '', vid: null, all: [], docOff: 0, idx: -2, retry: null, notes: new Map(), wake: null, idleTimer: null, seq: 0 }; +const Presenter = { + async boot() { + if (!new URLSearchParams(location.search).has('present') && !LowerThird.active()) return; + return Lazy.proxy('feature:presenter', ['boot'], 'Presenter').boot(); + }, + active: () => !document.getElementById('presenterView')?.classList.contains('hidden'), +}; - function setStatus(t) { $('pvStatus').textContent = t; } - - function show() { - view.classList.remove('hidden'); - document.body.classList.add('presenter-open'); - // The app underneath may have focused its search box; keys belong here now. - try { if (document.activeElement && !view.contains(document.activeElement)) document.activeElement.blur(); } catch { /* fine */ } - try { if (Player.master && !Player.master.paused) Player.pause(); } catch { /* nothing loaded */ } - keepAwake(); - bumpIdle(); - } - - async function keepAwake() { - try { if ('wakeLock' in navigator && !st.wake) { st.wake = await navigator.wakeLock.request('screen'); st.wake.addEventListener('release', () => { st.wake = null; }); } } catch { /* not allowed */ } - } - - function showPairForm(msg = '') { - $('pvPair').classList.remove('hidden'); - $('pvMsg').textContent = msg; - setStatus('Not paired'); - } - - async function pair(code) { - code = String(code || '').replace(/\D/g, ''); - if (code.length !== 6) { showPairForm('Enter the 6-digit code from the playing screen.'); return; } - $('pvMsg').textContent = 'Connecting…'; - try { - const res = await fetch('/api/remote/pair', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, name: '🖥 Presenter' }) }); - const j = await res.json().catch(() => null); - if (!j || !j.ok) { showPairForm('⚠ ' + ((j && j.error) || `HTTP ${res.status}`)); return; } - save({ roomId: j.roomId, remoteId: j.remoteId, token: j.token, hostName: j.hostName }); - $('pvPair').classList.add('hidden'); - connect(); - } catch { - showPairForm('⚠ Network error — try again'); - } - } - - function connect() { - const p = load(); - if (!p) { showPairForm(); return; } - clearTimeout(st.retry); - try { if (st.ws) st.ws.close(); } catch { /* gone */ } - setStatus('Connecting…'); - const ws = new WebSocket(wsUrl({ role: 'remote', room: p.roomId, rid: p.remoteId, token: p.token, name: '🖥 Presenter' })); - st.ws = ws; - ws.onmessage = (e) => { - let m; try { m = JSON.parse(e.data); } catch { return; } - if (!overlay) { DirectMedia.attach('presenter', { send: m => ws.send(JSON.stringify(m)), peers: () => [{ id: 'host', name: st.hostName || 'Screen' }] }); } - if (m.type === 'direct') { if (!overlay) DirectMedia.handle('presenter', m); return; } - if (m.type === 'hello') { st.hostName = m.hostName || 'screen'; if (m.state) onState(m.state); else setStatus(`Following ${st.hostName}`); } - else if (m.type === 'state') onState(m.state); - else if (m.type === 'host-offline') { if (overlay) { st.all = []; LowerThird.paint([], -1); } setStatus(`${st.hostName || 'The screen'} is offline — waiting…`); } - }; - ws.onclose = (e) => { - if (st.ws !== ws) return; - st.ws = null; - if (e.code === 4001) { save(null); showPairForm('This presenter was unpaired — enter a new code.'); return; } - setStatus(e.code === 4004 ? 'Screen offline — retrying…' : 'Reconnecting…'); - st.retry = setTimeout(connect, 3000); - }; - } - - function onState(s) { - st.state = s; - st.stateAt = Date.now(); - const v = s && s.v; - setStatus(v ? `● Following ${st.hostName} · ${v.title}` : `● Following ${st.hostName} · nothing playing`); - const id = v && v.id; - if (id !== st.vid) loadSong(id, v); - } - - async function loadSong(id, v) { - const seq = ++st.seq; - st.vid = id; - st.all = []; - st.docOff = 0; - render(v); - if (!id || !isMediaId(id)) return; - let notes = st.notes.get(id); - if (!notes) { - try { - const j = await (await fetch(`/api/notes/${encodeURIComponent(id)}`)).json(); - notes = j && j.ok ? j : null; - if (notes) { st.notes.set(id, notes); if (st.notes.size > 50) st.notes.delete(st.notes.keys().next().value); } - } catch { notes = null; } - } - if (seq !== st.seq) return; - const doc = notes && notes.lyrics && notes.lyrics.data; - st.all = (doc && doc.lines) || []; - st.docOff = (doc && Number(doc.offset)) || 0; - render(v); - } - - function render(v) { - if (overlay) { LowerThird.paint([], -1); st.idx = -2; tick(true); return; } - const sung = st.all.map((l, i) => ({ ...l, i })).filter((l) => l.kind === 'line'); - const title = $('pvTitle'); - if (!sung.length) { - list.innerHTML = ''; - title.innerHTML = v ? `${escapeHtml(v.title)}${v.channel ? `${escapeHtml(v.channel)}` : ''}` : ''; - title.classList.toggle('hidden', !v); - return; - } - title.classList.add('hidden'); - const pad = Math.round(list.clientHeight / 2); - list.style.paddingTop = pad + 'px'; - list.style.paddingBottom = pad + 'px'; - list.innerHTML = sung.map((l) => `
${LyricsDisplay.html(l)}
`).join(''); - refit(); - st.idx = -2; - tick(true); - setTimeout(refit, 900); // once more after fonts/layout settle - } - - function refit() { - fitLyricLines(list, { maxShare: 0.2, maxPx: 240 }); - } - - function liveTime() { - const s = st.state; - if (!s) return 0; - return s.paused ? s.cur : s.cur + ((Date.now() - st.stateAt) / 1000) * (s.rate || 1); - } - - function tick(force = false) { - if (view.classList.contains('hidden') || !st.all.length || !st.state) return; - if (overlay) { LowerThird.paint(st.all, LyricsCore.activeIndex(st.all, liveTime(), st.docOff + (Number(st.state.off) || 0))); return; } - const idx = LyricsCore.activeIndex(st.all, liveTime(), st.docOff + (Number(st.state.off) || 0)); - if (idx === st.idx && !force) return; - st.idx = idx; - const rows = [...list.querySelectorAll('.sl-line')]; - const pos = rows.findIndex((el) => Number(el.dataset.i) === idx); - rows.forEach((el, k) => { - const d = pos < 0 ? 99 : Math.abs(k - pos); - el.classList.toggle('active', d === 0); - el.classList.toggle('near', d === 1); - el.classList.toggle('past', pos >= 0 && k < pos); - }); - const target = pos >= 0 ? rows[pos] : rows[0]; - if (target) { - const go = () => list.scrollTo({ top: Math.max(0, target.offsetTop - list.clientHeight / 2 + target.offsetHeight / 2), behavior: 'smooth' }); - go(); - setTimeout(go, 380); - } - } - - function toggleFullscreen() { - if (document.fullscreenElement) document.exitFullscreen().catch(() => {}); - else view.requestFullscreen?.().catch(() => {}); - } - - // The status bar and cursor hide after 3 s without mouse movement. - function bumpIdle() { - view.classList.remove('idle'); - clearTimeout(st.idleTimer); - st.idleTimer = setTimeout(() => view.classList.add('idle'), 3000); - } - - function boot() { - let param = null; - try { param = new URLSearchParams(location.search).get(overlay ? 'code' : 'present'); } catch { /* no URL */ } - if (param === null) return; - try { - const u = new URL(location.href); - u.searchParams.delete('present'); - history.replaceState(null, '', u.pathname + (u.search || '') + u.hash); - } catch { /* keep */ } - show(); - const code = String(param).replace(/\D/g, ''); - if (overlay && load()) connect(); - else if (code.length === 6) pair(code); - else if (load()) connect(); - else showPairForm(); - setInterval(() => tick(), 200); - window.addEventListener('resize', () => { refit(); tick(true); }); - if (document.fonts) { - document.fonts.ready.then(refit); - document.fonts.addEventListener('loadingdone', refit); - } - view.addEventListener('mousemove', bumpIdle); - view.addEventListener('dblclick', toggleFullscreen); - $('pvFull').addEventListener('click', toggleFullscreen); - $('pvPairBtn').addEventListener('click', () => pair($('pvCode').value)); - $('pvCode').addEventListener('keydown', (e) => { e.stopPropagation(); if (e.key === 'Enter') pair($('pvCode').value); }); - document.addEventListener('keydown', (e) => { - if (view.classList.contains('hidden') || (e.target.closest && e.target.closest('#pvPair'))) return; - if (e.key === 'f' || e.key === 'F') { e.preventDefault(); e.stopImmediatePropagation(); toggleFullscreen(); } - else if (e.key === 'b' || e.key === 'B') { e.preventDefault(); e.stopImmediatePropagation(); $('pvBlank').classList.toggle('hidden'); } - }, true); - document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'visible') { keepAwake(); if (!st.ws && load()) connect(); } - }); - } - - return { boot, active: () => !view.classList.contains('hidden') }; -})(); // Open a video and jump to `t` seconds once it can play (deep links, notes). async function playVideoAt(v, t = 0) { @@ -10632,7 +10431,7 @@ async function boot() { syncOnLaunch(); startPlaylistInboxWatch(); if(LowerThird.active()) await Lazy.load('feature:lower-third'); - Presenter.boot(); + await Presenter.boot(); if (LowerThird.active()) return; SectionRail.boot(); Share.bootFromUrl(); diff --git a/frontend/assets.json b/frontend/assets.json index dd849b4..140186a 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -316,6 +316,14 @@ "eager": false, "background": true, "files": [] + }, + "feature:presenter": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/presenter.js" + ] } } } diff --git a/frontend/index.html b/frontend/index.html index 7798602..8eae8af 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + diff --git a/frontend/lazy.js b/frontend/lazy.js index a10e2bd..7bb4258 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -111,7 +111,8 @@ proxy(name, methods, globalName) { return Object.fromEntries(methods.map(method => [method, async (...args) => { await load(name); - const target = root[globalName || name.split(':')[1]]; + const key = globalName || name.split(':')[1]; + const target = root.YT?.[key] || root[key]; if (typeof target?.[method] !== 'function') throw new Error('Missing lazy method: ' + method); return target[method](...args); }])); diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index 8265580..b084413 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -76,3 +76,11 @@ test('new group files with a changed dependency contract cannot run against the const f=fixture(next,['/one.js?v=new','/two.js?v=2']);f.root.Lazy.manifest.groups['feature:test'].dependencies=['feature:dep'];f.root.Lazy.manifest.groups['feature:dep']={contract:1,files:[]}; await f.root.Lazy.load('feature:test');assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']);assert.equal(f.root.Lazy.reloadRequired,true); }); + +test('classic chunk registry proxies use window.YT and keep the executed singleton pinned',async()=>{ + const {root,inserted}=fixture();root.YT={TestApi:{open:n=>n+2}}; + const proxy=root.Lazy.proxy('feature:test',['open'],'TestApi'); + assert.equal(await proxy.open(3),5); + const singleton=root.YT.TestApi;await root.Lazy.load('feature:test'); + assert.equal(root.YT.TestApi,singleton);assert.equal(inserted.length,2); +}); diff --git a/frontend/presenter.js b/frontend/presenter.js new file mode 100644 index 0000000..0f7961a --- /dev/null +++ b/frontend/presenter.js @@ -0,0 +1,210 @@ +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).Presenter = (() => { + const noop = { boot() {}, active: () => false }; + const view = $('presenterView'); + if (!WEB || !view || typeof WebSocket === 'undefined') return noop; + const overlay = LowerThird.active(); + const KEY = overlay ? `ytpOverlayPair:${new URLSearchParams(location.search).get('code') || ''}` : 'ytpPresenterPair'; + const load = () => { try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch { return null; } }; + const save = (v) => { try { if (v) localStorage.setItem(KEY, JSON.stringify(v)); else localStorage.removeItem(KEY); } catch { /* blocked */ } }; + const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/remote?${new URLSearchParams(q)}`; + const list = $('pvList'); + const st = { ws: null, state: null, stateAt: 0, hostName: '', vid: null, all: [], docOff: 0, idx: -2, retry: null, notes: new Map(), wake: null, idleTimer: null, seq: 0 }; + + function setStatus(t) { $('pvStatus').textContent = t; } + + function show() { + view.classList.remove('hidden'); + document.body.classList.add('presenter-open'); + // The app underneath may have focused its search box; keys belong here now. + try { if (document.activeElement && !view.contains(document.activeElement)) document.activeElement.blur(); } catch { /* fine */ } + try { if (Player.master && !Player.master.paused) Player.pause(); } catch { /* nothing loaded */ } + keepAwake(); + bumpIdle(); + } + + async function keepAwake() { + try { if ('wakeLock' in navigator && !st.wake) { st.wake = await navigator.wakeLock.request('screen'); st.wake.addEventListener('release', () => { st.wake = null; }); } } catch { /* not allowed */ } + } + + function showPairForm(msg = '') { + $('pvPair').classList.remove('hidden'); + $('pvMsg').textContent = msg; + setStatus('Not paired'); + } + + async function pair(code) { + code = String(code || '').replace(/\D/g, ''); + if (code.length !== 6) { showPairForm('Enter the 6-digit code from the playing screen.'); return; } + $('pvMsg').textContent = 'Connecting…'; + try { + const res = await fetch('/api/remote/pair', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, name: '🖥 Presenter' }) }); + const j = await res.json().catch(() => null); + if (!j || !j.ok) { showPairForm('⚠ ' + ((j && j.error) || `HTTP ${res.status}`)); return; } + save({ roomId: j.roomId, remoteId: j.remoteId, token: j.token, hostName: j.hostName }); + $('pvPair').classList.add('hidden'); + connect(); + } catch { + showPairForm('⚠ Network error — try again'); + } + } + + function connect() { + const p = load(); + if (!p) { showPairForm(); return; } + clearTimeout(st.retry); + try { if (st.ws) st.ws.close(); } catch { /* gone */ } + setStatus('Connecting…'); + const ws = new WebSocket(wsUrl({ role: 'remote', room: p.roomId, rid: p.remoteId, token: p.token, name: '🖥 Presenter' })); + st.ws = ws; + ws.onmessage = (e) => { + let m; try { m = JSON.parse(e.data); } catch { return; } + if (!overlay) { DirectMedia.attach('presenter', { send: m => ws.send(JSON.stringify(m)), peers: () => [{ id: 'host', name: st.hostName || 'Screen' }] }); } + if (m.type === 'direct') { if (!overlay) DirectMedia.handle('presenter', m); return; } + if (m.type === 'hello') { st.hostName = m.hostName || 'screen'; if (m.state) onState(m.state); else setStatus(`Following ${st.hostName}`); } + else if (m.type === 'state') onState(m.state); + else if (m.type === 'host-offline') { if (overlay) { st.all = []; LowerThird.paint([], -1); } setStatus(`${st.hostName || 'The screen'} is offline — waiting…`); } + }; + ws.onclose = (e) => { + if (st.ws !== ws) return; + st.ws = null; + if (e.code === 4001) { save(null); showPairForm('This presenter was unpaired — enter a new code.'); return; } + setStatus(e.code === 4004 ? 'Screen offline — retrying…' : 'Reconnecting…'); + st.retry = setTimeout(connect, 3000); + }; + } + + function onState(s) { + st.state = s; + st.stateAt = Date.now(); + const v = s && s.v; + setStatus(v ? `● Following ${st.hostName} · ${v.title}` : `● Following ${st.hostName} · nothing playing`); + const id = v && v.id; + if (id !== st.vid) loadSong(id, v); + } + + async function loadSong(id, v) { + const seq = ++st.seq; + st.vid = id; + st.all = []; + st.docOff = 0; + render(v); + if (!id || !isMediaId(id)) return; + let notes = st.notes.get(id); + if (!notes) { + try { + const j = await (await fetch(`/api/notes/${encodeURIComponent(id)}`)).json(); + notes = j && j.ok ? j : null; + if (notes) { st.notes.set(id, notes); if (st.notes.size > 50) st.notes.delete(st.notes.keys().next().value); } + } catch { notes = null; } + } + if (seq !== st.seq) return; + const doc = notes && notes.lyrics && notes.lyrics.data; + st.all = (doc && doc.lines) || []; + st.docOff = (doc && Number(doc.offset)) || 0; + render(v); + } + + function render(v) { + if (overlay) { LowerThird.paint([], -1); st.idx = -2; tick(true); return; } + const sung = st.all.map((l, i) => ({ ...l, i })).filter((l) => l.kind === 'line'); + const title = $('pvTitle'); + if (!sung.length) { + list.innerHTML = ''; + title.innerHTML = v ? `${escapeHtml(v.title)}${v.channel ? `${escapeHtml(v.channel)}` : ''}` : ''; + title.classList.toggle('hidden', !v); + return; + } + title.classList.add('hidden'); + const pad = Math.round(list.clientHeight / 2); + list.style.paddingTop = pad + 'px'; + list.style.paddingBottom = pad + 'px'; + list.innerHTML = sung.map((l) => `
${LyricsDisplay.html(l)}
`).join(''); + refit(); + st.idx = -2; + tick(true); + setTimeout(refit, 900); // once more after fonts/layout settle + } + + function refit() { + fitLyricLines(list, { maxShare: 0.2, maxPx: 240 }); + } + + function liveTime() { + const s = st.state; + if (!s) return 0; + return s.paused ? s.cur : s.cur + ((Date.now() - st.stateAt) / 1000) * (s.rate || 1); + } + + function tick(force = false) { + if (view.classList.contains('hidden') || !st.all.length || !st.state) return; + if (overlay) { LowerThird.paint(st.all, LyricsCore.activeIndex(st.all, liveTime(), st.docOff + (Number(st.state.off) || 0))); return; } + const idx = LyricsCore.activeIndex(st.all, liveTime(), st.docOff + (Number(st.state.off) || 0)); + if (idx === st.idx && !force) return; + st.idx = idx; + const rows = [...list.querySelectorAll('.sl-line')]; + const pos = rows.findIndex((el) => Number(el.dataset.i) === idx); + rows.forEach((el, k) => { + const d = pos < 0 ? 99 : Math.abs(k - pos); + el.classList.toggle('active', d === 0); + el.classList.toggle('near', d === 1); + el.classList.toggle('past', pos >= 0 && k < pos); + }); + const target = pos >= 0 ? rows[pos] : rows[0]; + if (target) { + const go = () => list.scrollTo({ top: Math.max(0, target.offsetTop - list.clientHeight / 2 + target.offsetHeight / 2), behavior: 'smooth' }); + go(); + setTimeout(go, 380); + } + } + + function toggleFullscreen() { + if (document.fullscreenElement) document.exitFullscreen().catch(() => {}); + else view.requestFullscreen?.().catch(() => {}); + } + + // The status bar and cursor hide after 3 s without mouse movement. + function bumpIdle() { + view.classList.remove('idle'); + clearTimeout(st.idleTimer); + st.idleTimer = setTimeout(() => view.classList.add('idle'), 3000); + } + + function boot() { + let param = null; + try { param = new URLSearchParams(location.search).get(overlay ? 'code' : 'present'); } catch { /* no URL */ } + if (param === null) return; + try { + const u = new URL(location.href); + u.searchParams.delete('present'); + history.replaceState(null, '', u.pathname + (u.search || '') + u.hash); + } catch { /* keep */ } + show(); + const code = String(param).replace(/\D/g, ''); + if (overlay && load()) connect(); + else if (code.length === 6) pair(code); + else if (load()) connect(); + else showPairForm(); + setInterval(() => tick(), 200); + window.addEventListener('resize', () => { refit(); tick(true); }); + if (document.fonts) { + document.fonts.ready.then(refit); + document.fonts.addEventListener('loadingdone', refit); + } + view.addEventListener('mousemove', bumpIdle); + view.addEventListener('dblclick', toggleFullscreen); + $('pvFull').addEventListener('click', toggleFullscreen); + $('pvPairBtn').addEventListener('click', () => pair($('pvCode').value)); + $('pvCode').addEventListener('keydown', (e) => { e.stopPropagation(); if (e.key === 'Enter') pair($('pvCode').value); }); + document.addEventListener('keydown', (e) => { + if (view.classList.contains('hidden') || (e.target.closest && e.target.closest('#pvPair'))) return; + if (e.key === 'f' || e.key === 'F') { e.preventDefault(); e.stopImmediatePropagation(); toggleFullscreen(); } + else if (e.key === 'b' || e.key === 'B') { e.preventDefault(); e.stopImmediatePropagation(); $('pvBlank').classList.toggle('hidden'); } + }, true); + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible') { keepAwake(); if (!st.ws && load()) connect(); } + }); + } + + return { boot, active: () => !view.classList.contains('hidden') }; +})(); diff --git a/frontend/sw.js b/frontend/sw.js index ed90ab1..4bfd5b0 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -140,6 +140,7 @@ const SHELL = [ '/shell-core.js', '/views-core.js', '/section-rail.js', + '/presenter.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', From 8e7fa1959a21ed750ffe84e06e7673d0e1d0f295 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:41:30 +0800 Subject: [PATCH 34/81] Load remote UI on intent and preserve synchronous host hooks --- frontend/app-seams.test.js | 10 + frontend/app.js | 693 +------------------------------------ frontend/assets.json | 8 + frontend/index.html | 2 +- frontend/remote-client.js | 673 +++++++++++++++++++++++++++++++++++ frontend/sw.js | 1 + 6 files changed, 710 insertions(+), 677 deletions(-) create mode 100644 frontend/remote-client.js diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index 23890ad..c2031ce 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -38,3 +38,13 @@ test('eager shell and Settings definitions load before app state and defer readi const views=readFileSync(join(__dirname,'views-core.js'),'utf8'); assert.ok(views.includes('async function renderSettings()')); }); + +test('remote facade preserves synchronous no-session and loaded changed hooks',()=>{ + const source=app.match(/\/\* Remote facade \*\/([\s\S]*?)\/\* End remote facade \*\//)?.[1]; + assert.ok(source,'remote facade is present'); + const context=require('node:vm').createContext({window:{},Lazy:{proxy:()=>({}),onLoad(){}}}); + require('node:vm').runInContext(source+';globalThis.api=Remote;',context); + assert.equal(context.api.changed(),undefined); + let calls=0;context.window.YT={Remote:{changed:()=>{calls++;return 'sync';}}}; + assert.equal(context.api.changed(),'sync');assert.equal(calls,1); +}); diff --git a/frontend/app.js b/frontend/app.js index b3b8088..f2f0f87 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -4719,683 +4719,24 @@ const Notes = (() => { // Remote = this phone drives a host. Hosting survives reloads (the secret and // "enabled" flag live in localStorage), so a TV PC that restarts its browser // keeps its phones paired. -const Remote = (() => { - const noop = { boot() {}, changed() {} }; - if (!WEB || typeof WebSocket === 'undefined') return noop; +/* Remote facade */ +const Remote = { + ...Lazy.proxy('feature:remote-client', ['openChooser', 'openHostModal'], 'Remote'), + changed: () => window.YT?.Remote?.changed(), + boot() { + if (!WEB) return; + $('navRemoteBtn').addEventListener('click', () => { closeSidebar(); Remote.openChooser().catch(error => toast(error.message)); }); + $('remoteChip').addEventListener('click', () => Remote.openHostModal().catch(error => toast(error.message))); + Lazy.intent($('navRemoteBtn'), 'feature:remote-client'); + Lazy.intent($('remoteChip'), 'feature:remote-client'); + let configured = false; + try { configured = !!JSON.parse(localStorage.getItem('ytpRemoteHost') || 'null')?.enabled; } catch {} + if (configured || new URLSearchParams(location.search).has('pair')) Lazy.load('feature:remote-client').catch(error => toast(error.message)); + }, +}; +Lazy.onLoad('feature:remote-client', () => window.YT.Remote.boot()); +/* End remote facade */ - const HOST_KEY = 'ytpRemoteHost'; - const PAIR_KEY = 'ytpRemotePair'; - const load = (k) => { try { return JSON.parse(localStorage.getItem(k) || 'null'); } catch { return null; } }; - const save = (k, v) => { try { if (v) localStorage.setItem(k, JSON.stringify(v)); else localStorage.removeItem(k); } catch { /* storage blocked */ } }; - const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/remote?${new URLSearchParams(q)}`; - const newSecret = () => { - const b = new Uint8Array(32); - crypto.getRandomValues(b); - return btoa(String.fromCharCode(...b)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); - }; - const guessName = (fallback) => { - const ua = navigator.userAgent || ''; - if (/iPhone/.test(ua)) return 'iPhone'; - if (/iPad/.test(ua)) return 'iPad'; - if (/Android/.test(ua)) return 'Android phone'; - if (/Windows/.test(ua)) return 'Windows PC'; - if (/Mac/.test(ua)) return 'Mac'; - return fallback; - }; - const clock = (t) => (window.LyricsCore ? LyricsCore.fmtClock(t) : fmtTime(t)); - - // ========================================================================== - // Host (the screen being controlled) - // ========================================================================== - const host = { ws: null, remotes: [], code: '', codeExpires: 0, retryMs: 2000, timer: null, lastState: '', lastQueue: '', replaced: false, pending: false }; - - function hostCfg() { - let cfg = load(HOST_KEY); - if (!cfg || !cfg.secret) cfg = { secret: newSecret(), name: guessName('Desktop'), enabled: false }; - return cfg; - } - - function hostConnect() { - const cfg = hostCfg(); - if (!cfg.enabled) return; - try { if (host.ws) host.ws.close(); } catch { /* already closed */ } - const ws = new WebSocket(wsUrl({ role: 'host', secret: cfg.secret, name: cfg.name })); - host.ws = ws; - host.replaced = false; - ws.onopen = () => { host.retryMs = 2000; }; - ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onHostMessage(m); }; - ws.onclose = (e) => { - if (host.ws !== ws) return; - host.ws = null; - host.remotes = []; - renderChip(); - renderHostModal(); - if (e.code === 4000) { host.replaced = true; renderHostModal(); return; } // another tab hosts now - if (hostCfg().enabled) { - clearTimeout(host.timer); - host.timer = setTimeout(hostConnect, host.retryMs); - host.retryMs = Math.min(host.retryMs * 2, 30000); - } - }; - } - - const hostSend = (m) => { if (host.ws && host.ws.readyState === 1) host.ws.send(JSON.stringify(m)); }; - - function onHostMessage(m) { - DirectMedia.attach('remote-host', { send: hostSend, peers: () => host.remotes.map(r => ({ id: r.rid, name: r.name })) }); - if (m.type === 'direct') { DirectMedia.handle('remote-host', m); return; } - if (m.type === 'hello') { - host.code = m.code; host.codeExpires = m.codeExpires; host.remotes = m.remotes || []; - host.lastState = ''; host.lastQueue = ''; - pushState(); pushQueue(); - } else if (m.type === 'code') { - host.code = m.code; host.codeExpires = m.codeExpires; - } else if (m.type === 'remotes') { - host.remotes = m.remotes || []; - if (m.joined) { toast(`📱 ${m.joined} connected as a remote`); host.lastState = ''; host.lastQueue = ''; pushState(); pushQueue(); } - if (m.left) toast(`📱 ${m.left} disconnected`); - } else if (m.type === 'ping') { - hostSend({ type: 'pong', rid: m.rid, t: m.t }); - return; - } else if (m.type === 'cmd') { - runCommand(m); - return; - } - renderChip(); - renderHostModal(); - } - - function stateNow() { - const meta = current && current.meta; - const M = Player.master; - return { - directAvailable: !!meta && cachedIds.has(meta.id) && DirectMedia.enabled() && data.settings.p2pShare !== false, - v: meta ? { id: meta.id, title: meta.title || '', channel: meta.channel || '', thumbnail: meta.thumbnail || '' } : null, - cur: M ? Math.floor((M.currentTime || 0) * 10) / 10 : 0, - dur: (M && isFinite(M.duration) && M.duration) || (meta && meta.duration) || 0, - paused: !M || M.paused, - volume: data.settings.volume ?? 1, - service: isServiceModeOpen(), - sleep: sleepTimerRemaining || 0, - hostName: hostCfg().name, - // For the presenter screen: this screen's personal lyric offset for the - // song and the playback speed (to extrapolate between updates). - off: meta && data.lyricOffsets ? Number(data.lyricOffsets[meta.id]) || 0 : 0, - rate: (M && M.playbackRate) || 1, - }; - } - - function pushState(force = false) { - if (!host.ws || !host.remotes.length) return; - const st = stateNow(); - const key = JSON.stringify({ ...st, cur: Math.floor(st.cur) }); - if (!force && key === host.lastState) return; - host.lastState = key; - hostSend({ type: 'state', state: { ...st, at: Date.now() } }); - } - - function pushQueue() { - if (!host.ws || !host.remotes.length) return; - const items = queue.slice(0, 200).map((v) => ({ - id: v.id, title: v.title || '', channel: v.channel || '', duration: v.duration || 0, thumbnail: v.thumbnail || '', - })); - const key = queueIndex + '|' + items.map((v) => v.id).join(','); - if (key === host.lastQueue) return; - host.lastQueue = key; - hostSend({ type: 'queue', queue: { items, idx: queueIndex } }); - } - - // Coalesce bursts (play event + renderUpNext + afterLoad) into one push. - function changed() { - if (!host.ws || host.pending) return; - host.pending = true; - setTimeout(() => { host.pending = false; pushState(); pushQueue(); }, 50); - } - - const validIdx = (i) => Number.isInteger(i) && i > queueIndex && i < queue.length; - - function runCommand(m) { - const who = m.from || 'Phone'; - switch (m.cmd) { - case 'toggle': Player.toggle(); break; - case 'play': Player.play(); break; - case 'pause': Player.pause(); break; - case 'next': playNext(); break; - case 'prev': playPrev(); break; - case 'seek': { - const t = Number(m.t); - if (isFinite(t) && t >= 0) Player.seek(t); - break; - } - case 'volume': { - const v = Math.max(0, Math.min(1, Number(m.v))); - if (!isFinite(v)) break; - data.settings.volume = v; - els.volume.value = String(v); - Player.applyVolume(); - syncMuteIcon(); - persist(); - break; - } - case 'jump': { - const i = Number(m.i); - if (Number.isInteger(i) && i >= 0 && i < queue.length) { queueIndex = i - 1; playNext(); } - break; - } - case 'remove': { - const i = Number(m.i); - if (validIdx(i)) { queue.splice(i, 1); renderUpNext(); } - break; - } - case 'move': { - const from = Number(m.from), to = Number(m.to); - if (validIdx(from) && validIdx(to) && from !== to) { - const [v] = queue.splice(from, 1); - queue.splice(to, 0, v); - renderUpNext(); - } - break; - } - case 'add': { - const v = m.video; - if (!v || typeof v.id !== 'string' || !isMediaId(v.id)) break; - const item = slim({ ...v, title: String(v.title || v.id).slice(0, 300), channel: String(v.channel || '').slice(0, 200) }); - if (!current || !queue.length) { playFromList([item], 0, 'remote'); } - else if (!queue.slice(queueIndex + 1).some((x) => x.id === item.id)) { queue.push(item); renderUpNext(); } - toast(`📱 ${who} added “${item.title}”`); - break; - } - case 'sleep': { - const min = Number(m.min) || 0; - if (min > 0) startSleepTimer(Math.min(min, 240)); else cancelSleepTimer(); - break; - } - case 'service': - if (m.on) enterServiceMode(); else exitServiceMode(); - break; - default: return; - } - changed(); - } - - function startHosting() { - const cfg = hostCfg(); - cfg.enabled = true; - save(HOST_KEY, cfg); - hostConnect(); - renderHostModal(); - } - - function stopHosting() { - const cfg = hostCfg(); - cfg.enabled = false; - save(HOST_KEY, cfg); - clearTimeout(host.timer); - const ws = host.ws; - host.ws = null; - host.remotes = []; - try { if (ws) ws.close(); } catch { /* gone */ } - renderChip(); - renderHostModal(); - } - - function unpairAll() { - hostSend({ type: 'unpair-all' }); - const cfg = hostCfg(); - cfg.secret = newSecret(); // every phone's token was derived from the old one - save(HOST_KEY, cfg); - setTimeout(hostConnect, 300); - toast('All phones unpaired'); - } - - function renderChip() { - const chip = $('remoteChip'); - if (!chip) return; - const n = host.remotes.length; - chip.classList.toggle('hidden', !host.ws || !n); - if (n) { - $('remoteChipText').textContent = n === 1 - ? `Remote connected — ${host.remotes[0].name}` - : `${n} remotes connected`; - } - } - - let hostModalOpen = false; - function renderHostModal() { - if (!hostModalOpen) return; - const body = $('modalBody') && $('modalBody').querySelector('.remote-host'); - if (!body) { hostModalOpen = false; return; } - const cfg = hostCfg(); - const live = !!host.ws; - const mins = host.codeExpires ? Math.max(0, Math.round((host.codeExpires - Date.now()) / 60000)) : 0; - body.querySelector('.rh-body').innerHTML = !cfg.enabled ? ` - ` - : host.replaced ? `` - : !live ? `` - : ` -
- QR code to pair a phone -
-
Pairing code
-
${host.code.slice(0, 3)} ${host.code.slice(3)}
-
Valid ${mins} more min · one use
-
On the phone: open this app → 📱 Remote → Use this phone as a remote, or scan the QR code.
-
-
-
Presenter / projector screen
-
- QR code for the presenter screen -
-
Lyrics-only display that follows this screen. On the projector's computer or TV browser open - ${escapeHtml(location.origin)}/?present=${host.code} (same code), or scan the QR.
- - -
-
-
Connected phones & screens
- ${host.remotes.length ? host.remotes.map((r) => ` -
📱 ${escapeHtml(r.name)}
`).join('') - : '
None yet.
'}`; - const nameIn = body.querySelector('.rh-name'); - if (document.activeElement !== nameIn) nameIn.value = cfg.name; - body.querySelector('[data-act="start"]').classList.toggle('hidden', cfg.enabled && !host.replaced); - body.querySelector('[data-act="stop"]').classList.toggle('hidden', !cfg.enabled); - body.querySelector('[data-act="code"]').classList.toggle('hidden', !live); - body.querySelector('[data-act="unpair"]').classList.toggle('hidden', !live); - } - - async function openHostModal() { - try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } - const body = document.createElement('div'); - body.className = 'remote-host'; - body.innerHTML = ` -
- -
- - - - -
`; - body.addEventListener('click', (e) => { - const kick = e.target.closest('[data-kick]'); - if (kick) { hostSend({ type: 'kick', rid: kick.dataset.kick }); return; } - const act = e.target.closest('[data-act]'); - if (!act) return; - if (act.dataset.act === 'start') startHosting(); - else if (act.dataset.act === 'stop') stopHosting(); - else if (act.dataset.act === 'code') hostSend({ type: 'new-code' }); - else if (act.dataset.act === 'unpair') unpairAll(); - else if (act.dataset.act === 'obs') { navigator.clipboard.writeText(LowerThird.url(location.origin, host.code)).then(() => toast('OBS URL copied'), () => toast('Copy blocked')); } - else if (act.dataset.act === 'present') { - // A second window on this computer (drag it to the projector display). - window.open(`/?present=${host.code}`, 'ytp-presenter', 'popup,width=1280,height=720'); - } - }); - body.querySelector('.rh-name').addEventListener('change', (e) => { - const cfg = hostCfg(); - cfg.name = e.target.value.trim().slice(0, 40) || guessName('Desktop'); - save(HOST_KEY, cfg); - if (cfg.enabled) hostConnect(); // the server learns names on connect - }); - showModal('📱 Control this screen from a phone', body, [ - { label: 'Done', primary: true, onClick: () => { hostModalOpen = false; closeModal(); } }, - ]); - hostModalOpen = true; - renderHostModal(); - } - - // ========================================================================== - // Remote (this phone drives a host) - // ========================================================================== - const rc = { ws: null, open: false, state: null, stateAt: 0, queue: { items: [], idx: -1 }, retry: null, ping: null, seekTimer: null, latency: null, online: false, seeking: false, volTimer: null, drag: null }; - - const rcSend = (m) => { if (rc.ws && rc.ws.readyState === 1) rc.ws.send(JSON.stringify(m)); }; - const cmd = (name, args = {}) => rcSend({ type: 'cmd', cmd: name, ...args }); - - function setStatus(text, ok = false) { - $('rvStatus').textContent = text; - $('rvStatus').classList.toggle('ok', ok); - } - - function showPairForm(msg = '') { - $('rvPair').classList.remove('hidden'); - $('rvControl').classList.add('hidden'); - $('rvHostName').textContent = 'Remote'; - setStatus('Not paired'); - $('rvPairMsg').textContent = msg; - if (!$('rvName').value) $('rvName').value = (load(PAIR_KEY) || {}).name || guessName('Phone'); - } - - function rcConnect() { - const p = load(PAIR_KEY); - if (!p || !rc.open) return; - clearTimeout(rc.retry); - try { if (rc.ws) rc.ws.close(); } catch { /* gone */ } - $('rvPair').classList.add('hidden'); - $('rvControl').classList.remove('hidden'); - $('rvHostName').textContent = p.hostName || 'Screen'; - setStatus('Connecting…'); - const ws = new WebSocket(wsUrl({ role: 'remote', room: p.roomId, rid: p.remoteId, token: p.token, name: p.name || guessName('Phone') })); - rc.ws = ws; - ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onRemoteMessage(m); }; - ws.onclose = (e) => { - if (rc.ws !== ws) return; - rc.ws = null; - rc.online = false; - clearInterval(rc.ping); - if (e.code === 4001) { save(PAIR_KEY, null); showPairForm('This phone was unpaired by the screen — pair again.'); return; } - if (!rc.open) return; - setStatus(e.code === 4004 ? 'Screen offline — retrying…' : 'Reconnecting…'); - rc.retry = setTimeout(rcConnect, 4000); - }; - } - - function onRemoteMessage(m) { - DirectMedia.attach('remote-client', { send: rcSend, peers: () => [{ id: 'host', name: 'Paired screen', files: rc.state?.directAvailable && rc.state?.v ? [rc.state.v.id] : [] }] }); - if (m.type === 'direct') { DirectMedia.handle('remote-client', m); return; } - if (m.type === 'hello') { - rc.online = true; - $('rvHostName').textContent = m.hostName || 'Screen'; - if (m.state) { rc.state = m.state; rc.stateAt = Date.now(); } - if (m.queue) rc.queue = m.queue; - setStatus('Synced', true); - clearInterval(rc.ping); - const ping = () => rcSend({ type: 'ping', t: Date.now() }); - ping(); - rc.ping = setInterval(ping, 5000); - renderRemote(); renderQueue(); - } else if (m.type === 'state') { - rc.state = m.state; rc.stateAt = Date.now(); - renderRemote(); - } else if (m.type === 'queue') { - rc.queue = m.queue || { items: [], idx: -1 }; - renderQueue(); - } else if (m.type === 'pong') { - rc.latency = Date.now() - m.t; - if (rc.online) setStatus(`Synced · ${rc.latency} ms`, true); - } else if (m.type === 'host-offline') { - rc.online = false; - setStatus('Screen offline — waiting…'); - } - } - - function liveCur() { - const s = rc.state; - if (!s) return 0; - const cur = s.paused ? s.cur : s.cur + (Date.now() - rc.stateAt) / 1000; - return Math.min(cur, s.dur || cur); - } - - function renderRemote() { - const s = rc.state; - const v = s && s.v; - $('rvTitle').textContent = v ? v.title : 'Nothing playing'; - $('rvChannel').textContent = v ? v.channel : ''; - let directPlay = $('rvDirectPlay'); - if (!directPlay) { directPlay = document.createElement('button'); directPlay.id = 'rvDirectPlay'; directPlay.className = 'np-btn'; directPlay.style.minHeight = '44px'; directPlay.textContent = 'Play here from paired screen'; $('rvChannel').after(directPlay); } - directPlay.hidden = !v || !s.directAvailable || !DirectMedia.enabled(); - directPlay.onclick = () => v && playVideoAt({ ...v, duration: s.dur || 0 }, liveCur()); - - const thumb = $('rvThumb'); - if (v && v.thumbnail) { if (thumb.getAttribute('src') !== v.thumbnail) thumb.src = v.thumbnail; thumb.classList.remove('hidden'); } - else thumb.classList.add('hidden'); - $('rvToggle').textContent = s && !s.paused ? '⏸' : '▶'; - $('rvDur').textContent = clock((s && s.dur) || 0); - if (!rc.volTimer && document.activeElement !== $('rvVolume')) { - const pct = Math.round(((s && s.volume) ?? 1) * 100); - $('rvVolume').value = String(pct); - $('rvVolVal').textContent = pct + '%'; - } - const sleepMin = s && s.sleep ? Math.ceil(s.sleep / 60) : 0; - $('rvSleep').textContent = sleepMin ? `⏱ ${sleepMin} min` : '⏱ Sleep'; - $('rvSleep').classList.toggle('on', !!sleepMin); - $('rvService').classList.toggle('on', !!(s && s.service)); - renderSeek(); - } - - function renderSeek() { - if (rc.seeking || !rc.open) return; - const s = rc.state; - const cur = liveCur(); - $('rvCur').textContent = clock(cur); - $('rvSeek').value = s && s.dur ? String(Math.round((cur / s.dur) * 1000)) : '0'; - } - - function renderQueue() { - const q = rc.queue || { items: [], idx: -1 }; - const up = q.items.map((v, i) => ({ ...v, i })).filter((v) => v.i > q.idx); - $('rvQueueCount').textContent = up.length ? `${up.length} song${up.length === 1 ? '' : 's'}` : ''; - const list = $('rvQueue'); - list.innerHTML = up.length ? up.map((v) => ` -
- ⠿ -
-
${escapeHtml(v.title)}
-
${escapeHtml(v.channel)}
-
- ${v.duration ? clock(v.duration) : ''} - -
`).join('') : '
Nothing queued after this song.
'; - } - - // ---- drag to reorder (pointer events, works for touch + mouse) ---- - function onDragStart(e) { - const handle = e.target.closest('.rv-handle'); - if (!handle) return; - const row = handle.closest('.rv-row'); - e.preventDefault(); - const rows = [...$('rvQueue').querySelectorAll('.rv-row')]; - rc.drag = { row, rows, startY: e.clientY, from: Number(row.dataset.i), to: Number(row.dataset.i), h: row.offsetHeight }; - row.classList.add('dragging'); - row.setPointerCapture(e.pointerId); - row.addEventListener('pointermove', onDragMove); - row.addEventListener('pointerup', onDragEnd, { once: true }); - row.addEventListener('pointercancel', onDragEnd, { once: true }); - } - function onDragMove(e) { - const d = rc.drag; - if (!d) return; - const dy = e.clientY - d.startY; - d.row.style.transform = `translateY(${dy}px)`; - const pos = d.rows.indexOf(d.row); - const target = Math.max(0, Math.min(d.rows.length - 1, pos + Math.round(dy / d.h))); - d.to = Number(d.rows[target].dataset.i); - } - function onDragEnd() { - const d = rc.drag; - rc.drag = null; - if (!d) return; - d.row.removeEventListener('pointermove', onDragMove); - d.row.classList.remove('dragging'); - d.row.style.transform = ''; - if (d.to !== d.from) { - // Optimistic: reorder locally now, the host's queue push confirms it. - const items = rc.queue.items.slice(); - const [v] = items.splice(d.from, 1); - items.splice(d.to, 0, v); - rc.queue = { ...rc.queue, items }; - renderQueue(); - cmd('move', { from: d.from, to: d.to }); - } - } - - // ---- add to queue: search sheet ---- - function openAddSheet() { - const body = document.createElement('div'); - body.className = 'rv-add'; - body.innerHTML = ` -
-
`; - const results = body.querySelector('.rv-add-results'); - let found = []; - body.querySelector('form').addEventListener('submit', async (e) => { - e.preventDefault(); - const q = body.querySelector('.rv-add-q').value.trim(); - if (!q) return; - results.innerHTML = '
Searching…
'; - try { - const res = await API.search(q); - found = (res && res.ok && res.results) || []; - } catch { found = []; } - results.innerHTML = found.length ? found.slice(0, 20).map((v, i) => ` - `).join('') : '
No results.
'; - }); - results.addEventListener('click', (e) => { - const b = e.target.closest('[data-k]'); - if (!b) return; - const v = found[Number(b.dataset.k)]; - if (!v) return; - cmd('add', { video: { id: v.id, title: v.title, channel: v.channel, duration: v.duration, thumbnail: v.thumbnail } }); - b.classList.add('added'); - toast(`Added “${v.title}”`); - }); - showModal('+ Add to the screen’s queue', body, [{ label: 'Done', primary: true, onClick: closeModal }]); - setTimeout(() => body.querySelector('.rv-add-q').focus(), 50); - } - - async function doPair(codeRaw) { - const code = String(codeRaw || '').replace(/\D/g, ''); - const name = $('rvName').value.trim() || guessName('Phone'); - if (code.length !== 6) { $('rvPairMsg').textContent = 'Enter the 6-digit code from the screen.'; return; } - $('rvPairMsg').textContent = 'Pairing…'; - try { - const res = await fetch('/api/remote/pair', { - method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, name }), - }); - const j = await res.json().catch(() => null); - if (!j || !j.ok) { $('rvPairMsg').textContent = '⚠ ' + ((j && j.error) || `HTTP ${res.status}`); return; } - save(PAIR_KEY, { roomId: j.roomId, remoteId: j.remoteId, token: j.token, hostName: j.hostName, name: j.name }); - $('rvCode').value = ''; - rcConnect(); - } catch { - $('rvPairMsg').textContent = '⚠ Network error — try again'; - } - } - - async function openRemoteView({ code = '' } = {}) { - try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } - rc.open = true; - rc.seekTimer = VisibleTimer.setIntervalWhenVisible(renderSeek, 500); - // This phone is the remote now — don't also play here. - try { if (Player.master && !Player.master.paused) Player.pause(); } catch { /* nothing loaded */ } - $('remoteView').classList.remove('hidden'); - document.body.classList.add('remote-open'); - if (code) { save(PAIR_KEY, null); showPairForm(); $('rvCode').value = code; doPair(code); return; } - if (load(PAIR_KEY)) rcConnect(); else showPairForm(); - } - - function closeRemoteView() { - rc.open = false; - rc.seekTimer?.clear(); - rc.seekTimer = null; - clearTimeout(rc.retry); - clearInterval(rc.ping); - const ws = rc.ws; - rc.ws = null; - try { if (ws) ws.close(); } catch { /* gone */ } - $('remoteView').classList.add('hidden'); - document.body.classList.remove('remote-open'); - } - - function openChooser() { - const hosting = hostCfg().enabled; - const paired = load(PAIR_KEY); - const body = document.createElement('div'); - body.innerHTML = ``; - showModal('📱 Remote', body, [ - { label: paired ? `Control “${paired.hostName}”` : 'Use this phone as a remote', onClick: () => { closeModal(); openRemoteView(); } }, - { label: hosting ? 'This screen: remote on' : 'Control this screen from a phone', primary: true, onClick: () => { closeModal(); openHostModal(); } }, - ]); - } - - function bindUi() { - $('navRemoteBtn').addEventListener('click', () => { - if (typeof closeSidebar === 'function') { try { closeSidebar(); } catch { /* not open */ } } - openChooser(); - }); - $('remoteChip').addEventListener('click', openHostModal); - $('rvClose').addEventListener('click', closeRemoteView); - $('rvMenu').addEventListener('click', () => { - const p = load(PAIR_KEY); - showModal('Remote options', document.createTextNode(p ? `Paired with “${p.hostName}”.` : 'Not paired.'), [ - { label: 'Close', onClick: closeModal }, - ...(p ? [{ label: 'Unpair this phone', danger: true, onClick: () => { closeModal(); save(PAIR_KEY, null); try { rc.ws && rc.ws.close(); } catch { /* gone */ } showPairForm('Unpaired.'); } }] : []), - ]); - }); - $('rvPairBtn').addEventListener('click', () => doPair($('rvCode').value)); - $('rvCode').addEventListener('keydown', (e) => { if (e.key === 'Enter') doPair($('rvCode').value); }); - $('rvToggle').addEventListener('click', () => { - cmd('toggle'); - if (rc.state) { rc.state.cur = liveCur(); rc.stateAt = Date.now(); rc.state.paused = !rc.state.paused; renderRemote(); } - }); - $('rvPrev').addEventListener('click', () => cmd('prev')); - $('rvNext').addEventListener('click', () => cmd('next')); - const seek = $('rvSeek'); - seek.addEventListener('input', () => { - rc.seeking = true; - const dur = (rc.state && rc.state.dur) || 0; - $('rvCur').textContent = clock((Number(seek.value) / 1000) * dur); - }); - seek.addEventListener('change', () => { - const dur = (rc.state && rc.state.dur) || 0; - const t = (Number(seek.value) / 1000) * dur; - cmd('seek', { t }); - if (rc.state) { rc.state.cur = t; rc.stateAt = Date.now(); } - rc.seeking = false; - }); - $('rvVolume').addEventListener('input', (e) => { - const pct = Number(e.target.value); - $('rvVolVal').textContent = pct + '%'; - clearTimeout(rc.volTimer); - rc.volTimer = setTimeout(() => { rc.volTimer = null; cmd('volume', { v: pct / 100 }); }, 120); - }); - $('rvQueue').addEventListener('pointerdown', onDragStart); - $('rvQueue').addEventListener('click', (e) => { - const rm = e.target.closest('[data-rm]'); - if (rm) { cmd('remove', { i: Number(rm.dataset.rm) }); return; } - if (e.target.closest('.rv-handle')) return; - const row = e.target.closest('.rv-row'); - if (row) cmd('jump', { i: Number(row.dataset.i) }); - }); - $('rvAdd').addEventListener('click', openAddSheet); - $('rvSleep').addEventListener('click', () => { - const options = [0, 15, 30, 45, 60, 90]; - const curMin = rc.state && rc.state.sleep ? Math.ceil(rc.state.sleep / 60) : 0; - const next = options.find((o) => o > curMin) ?? 0; - cmd('sleep', { min: next }); - toast(next ? `Screen pauses in ${next} min` : 'Sleep timer off'); - }); - $('rvService').addEventListener('click', () => cmd('service', { on: !(rc.state && rc.state.service) })); - // Hosts keep phones current once a second while anything plays. - setInterval(() => { if (host.ws && host.remotes.length) { pushState(); pushQueue(); } }, 1000); - document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'visible' && rc.open && !rc.ws) rcConnect(); - }); - } - - function boot() { - bindUi(); - if (hostCfg().enabled) hostConnect(); - // A scanned QR / shared link: /?pair=482913 - let code = ''; - try { code = (new URLSearchParams(location.search).get('pair') || '').replace(/\D/g, ''); } catch { /* no URL */ } - if (code) { - try { - const u = new URL(location.href); - u.searchParams.delete('pair'); - history.replaceState(null, '', u.pathname + u.search + u.hash); - } catch { /* leave the URL */ } - openRemoteView({ code }); - } - } - - return { boot, changed }; -})(); // ============================================================================ // Playlist transitions: normal · gapless · crossfade diff --git a/frontend/assets.json b/frontend/assets.json index 140186a..af81548 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -324,6 +324,14 @@ "files": [ "/presenter.js" ] + }, + "feature:remote-client": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/remote-client.js" + ] } } } diff --git a/frontend/index.html b/frontend/index.html index 8eae8af..9ceac1d 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + diff --git a/frontend/remote-client.js b/frontend/remote-client.js new file mode 100644 index 0000000..ae68ceb --- /dev/null +++ b/frontend/remote-client.js @@ -0,0 +1,673 @@ +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).Remote = (() => { + const noop = { boot() {}, changed() {} }; + if (!WEB || typeof WebSocket === 'undefined') return noop; + + const HOST_KEY = 'ytpRemoteHost'; + const PAIR_KEY = 'ytpRemotePair'; + const load = (k) => { try { return JSON.parse(localStorage.getItem(k) || 'null'); } catch { return null; } }; + const save = (k, v) => { try { if (v) localStorage.setItem(k, JSON.stringify(v)); else localStorage.removeItem(k); } catch { /* storage blocked */ } }; + const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/remote?${new URLSearchParams(q)}`; + const newSecret = () => { + const b = new Uint8Array(32); + crypto.getRandomValues(b); + return btoa(String.fromCharCode(...b)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); + }; + const guessName = (fallback) => { + const ua = navigator.userAgent || ''; + if (/iPhone/.test(ua)) return 'iPhone'; + if (/iPad/.test(ua)) return 'iPad'; + if (/Android/.test(ua)) return 'Android phone'; + if (/Windows/.test(ua)) return 'Windows PC'; + if (/Mac/.test(ua)) return 'Mac'; + return fallback; + }; + const clock = (t) => (window.LyricsCore ? LyricsCore.fmtClock(t) : fmtTime(t)); + + // ========================================================================== + // Host (the screen being controlled) + // ========================================================================== + const host = { ws: null, remotes: [], code: '', codeExpires: 0, retryMs: 2000, timer: null, lastState: '', lastQueue: '', replaced: false, pending: false }; + + function hostCfg() { + let cfg = load(HOST_KEY); + if (!cfg || !cfg.secret) cfg = { secret: newSecret(), name: guessName('Desktop'), enabled: false }; + return cfg; + } + + function hostConnect() { + const cfg = hostCfg(); + if (!cfg.enabled) return; + try { if (host.ws) host.ws.close(); } catch { /* already closed */ } + const ws = new WebSocket(wsUrl({ role: 'host', secret: cfg.secret, name: cfg.name })); + host.ws = ws; + host.replaced = false; + ws.onopen = () => { host.retryMs = 2000; }; + ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onHostMessage(m); }; + ws.onclose = (e) => { + if (host.ws !== ws) return; + host.ws = null; + host.remotes = []; + renderChip(); + renderHostModal(); + if (e.code === 4000) { host.replaced = true; renderHostModal(); return; } // another tab hosts now + if (hostCfg().enabled) { + clearTimeout(host.timer); + host.timer = setTimeout(hostConnect, host.retryMs); + host.retryMs = Math.min(host.retryMs * 2, 30000); + } + }; + } + + const hostSend = (m) => { if (host.ws && host.ws.readyState === 1) host.ws.send(JSON.stringify(m)); }; + + function onHostMessage(m) { + DirectMedia.attach('remote-host', { send: hostSend, peers: () => host.remotes.map(r => ({ id: r.rid, name: r.name })) }); + if (m.type === 'direct') { DirectMedia.handle('remote-host', m); return; } + if (m.type === 'hello') { + host.code = m.code; host.codeExpires = m.codeExpires; host.remotes = m.remotes || []; + host.lastState = ''; host.lastQueue = ''; + pushState(); pushQueue(); + } else if (m.type === 'code') { + host.code = m.code; host.codeExpires = m.codeExpires; + } else if (m.type === 'remotes') { + host.remotes = m.remotes || []; + if (m.joined) { toast(`📱 ${m.joined} connected as a remote`); host.lastState = ''; host.lastQueue = ''; pushState(); pushQueue(); } + if (m.left) toast(`📱 ${m.left} disconnected`); + } else if (m.type === 'ping') { + hostSend({ type: 'pong', rid: m.rid, t: m.t }); + return; + } else if (m.type === 'cmd') { + runCommand(m); + return; + } + renderChip(); + renderHostModal(); + } + + function stateNow() { + const meta = current && current.meta; + const M = Player.master; + return { + directAvailable: !!meta && cachedIds.has(meta.id) && DirectMedia.enabled() && data.settings.p2pShare !== false, + v: meta ? { id: meta.id, title: meta.title || '', channel: meta.channel || '', thumbnail: meta.thumbnail || '' } : null, + cur: M ? Math.floor((M.currentTime || 0) * 10) / 10 : 0, + dur: (M && isFinite(M.duration) && M.duration) || (meta && meta.duration) || 0, + paused: !M || M.paused, + volume: data.settings.volume ?? 1, + service: isServiceModeOpen(), + sleep: sleepTimerRemaining || 0, + hostName: hostCfg().name, + // For the presenter screen: this screen's personal lyric offset for the + // song and the playback speed (to extrapolate between updates). + off: meta && data.lyricOffsets ? Number(data.lyricOffsets[meta.id]) || 0 : 0, + rate: (M && M.playbackRate) || 1, + }; + } + + function pushState(force = false) { + if (!host.ws || !host.remotes.length) return; + const st = stateNow(); + const key = JSON.stringify({ ...st, cur: Math.floor(st.cur) }); + if (!force && key === host.lastState) return; + host.lastState = key; + hostSend({ type: 'state', state: { ...st, at: Date.now() } }); + } + + function pushQueue() { + if (!host.ws || !host.remotes.length) return; + const items = queue.slice(0, 200).map((v) => ({ + id: v.id, title: v.title || '', channel: v.channel || '', duration: v.duration || 0, thumbnail: v.thumbnail || '', + })); + const key = queueIndex + '|' + items.map((v) => v.id).join(','); + if (key === host.lastQueue) return; + host.lastQueue = key; + hostSend({ type: 'queue', queue: { items, idx: queueIndex } }); + } + + // Coalesce bursts (play event + renderUpNext + afterLoad) into one push. + function changed() { + if (!host.ws || host.pending) return; + host.pending = true; + setTimeout(() => { host.pending = false; pushState(); pushQueue(); }, 50); + } + + const validIdx = (i) => Number.isInteger(i) && i > queueIndex && i < queue.length; + + function runCommand(m) { + const who = m.from || 'Phone'; + switch (m.cmd) { + case 'toggle': Player.toggle(); break; + case 'play': Player.play(); break; + case 'pause': Player.pause(); break; + case 'next': playNext(); break; + case 'prev': playPrev(); break; + case 'seek': { + const t = Number(m.t); + if (isFinite(t) && t >= 0) Player.seek(t); + break; + } + case 'volume': { + const v = Math.max(0, Math.min(1, Number(m.v))); + if (!isFinite(v)) break; + data.settings.volume = v; + els.volume.value = String(v); + Player.applyVolume(); + syncMuteIcon(); + persist(); + break; + } + case 'jump': { + const i = Number(m.i); + if (Number.isInteger(i) && i >= 0 && i < queue.length) { queueIndex = i - 1; playNext(); } + break; + } + case 'remove': { + const i = Number(m.i); + if (validIdx(i)) { queue.splice(i, 1); renderUpNext(); } + break; + } + case 'move': { + const from = Number(m.from), to = Number(m.to); + if (validIdx(from) && validIdx(to) && from !== to) { + const [v] = queue.splice(from, 1); + queue.splice(to, 0, v); + renderUpNext(); + } + break; + } + case 'add': { + const v = m.video; + if (!v || typeof v.id !== 'string' || !isMediaId(v.id)) break; + const item = slim({ ...v, title: String(v.title || v.id).slice(0, 300), channel: String(v.channel || '').slice(0, 200) }); + if (!current || !queue.length) { playFromList([item], 0, 'remote'); } + else if (!queue.slice(queueIndex + 1).some((x) => x.id === item.id)) { queue.push(item); renderUpNext(); } + toast(`📱 ${who} added “${item.title}”`); + break; + } + case 'sleep': { + const min = Number(m.min) || 0; + if (min > 0) startSleepTimer(Math.min(min, 240)); else cancelSleepTimer(); + break; + } + case 'service': + if (m.on) enterServiceMode(); else exitServiceMode(); + break; + default: return; + } + changed(); + } + + function startHosting() { + const cfg = hostCfg(); + cfg.enabled = true; + save(HOST_KEY, cfg); + hostConnect(); + renderHostModal(); + } + + function stopHosting() { + const cfg = hostCfg(); + cfg.enabled = false; + save(HOST_KEY, cfg); + clearTimeout(host.timer); + const ws = host.ws; + host.ws = null; + host.remotes = []; + try { if (ws) ws.close(); } catch { /* gone */ } + renderChip(); + renderHostModal(); + } + + function unpairAll() { + hostSend({ type: 'unpair-all' }); + const cfg = hostCfg(); + cfg.secret = newSecret(); // every phone's token was derived from the old one + save(HOST_KEY, cfg); + setTimeout(hostConnect, 300); + toast('All phones unpaired'); + } + + function renderChip() { + const chip = $('remoteChip'); + if (!chip) return; + const n = host.remotes.length; + chip.classList.toggle('hidden', !host.ws || !n); + if (n) { + $('remoteChipText').textContent = n === 1 + ? `Remote connected — ${host.remotes[0].name}` + : `${n} remotes connected`; + } + } + + let hostModalOpen = false; + function renderHostModal() { + if (!hostModalOpen) return; + const body = $('modalBody') && $('modalBody').querySelector('.remote-host'); + if (!body) { hostModalOpen = false; return; } + const cfg = hostCfg(); + const live = !!host.ws; + const mins = host.codeExpires ? Math.max(0, Math.round((host.codeExpires - Date.now()) / 60000)) : 0; + body.querySelector('.rh-body').innerHTML = !cfg.enabled ? ` + ` + : host.replaced ? `` + : !live ? `` + : ` +
+ QR code to pair a phone +
+
Pairing code
+
${host.code.slice(0, 3)} ${host.code.slice(3)}
+
Valid ${mins} more min · one use
+
On the phone: open this app → 📱 Remote → Use this phone as a remote, or scan the QR code.
+
+
+
Presenter / projector screen
+
+ QR code for the presenter screen +
+
Lyrics-only display that follows this screen. On the projector's computer or TV browser open + ${escapeHtml(location.origin)}/?present=${host.code} (same code), or scan the QR.
+ + +
+
+
Connected phones & screens
+ ${host.remotes.length ? host.remotes.map((r) => ` +
📱 ${escapeHtml(r.name)}
`).join('') + : '
None yet.
'}`; + const nameIn = body.querySelector('.rh-name'); + if (document.activeElement !== nameIn) nameIn.value = cfg.name; + body.querySelector('[data-act="start"]').classList.toggle('hidden', cfg.enabled && !host.replaced); + body.querySelector('[data-act="stop"]').classList.toggle('hidden', !cfg.enabled); + body.querySelector('[data-act="code"]').classList.toggle('hidden', !live); + body.querySelector('[data-act="unpair"]').classList.toggle('hidden', !live); + } + + async function openHostModal() { + try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } + const body = document.createElement('div'); + body.className = 'remote-host'; + body.innerHTML = ` +
+ +
+ + + + +
`; + body.addEventListener('click', (e) => { + const kick = e.target.closest('[data-kick]'); + if (kick) { hostSend({ type: 'kick', rid: kick.dataset.kick }); return; } + const act = e.target.closest('[data-act]'); + if (!act) return; + if (act.dataset.act === 'start') startHosting(); + else if (act.dataset.act === 'stop') stopHosting(); + else if (act.dataset.act === 'code') hostSend({ type: 'new-code' }); + else if (act.dataset.act === 'unpair') unpairAll(); + else if (act.dataset.act === 'obs') { navigator.clipboard.writeText(LowerThird.url(location.origin, host.code)).then(() => toast('OBS URL copied'), () => toast('Copy blocked')); } + else if (act.dataset.act === 'present') { + // A second window on this computer (drag it to the projector display). + window.open(`/?present=${host.code}`, 'ytp-presenter', 'popup,width=1280,height=720'); + } + }); + body.querySelector('.rh-name').addEventListener('change', (e) => { + const cfg = hostCfg(); + cfg.name = e.target.value.trim().slice(0, 40) || guessName('Desktop'); + save(HOST_KEY, cfg); + if (cfg.enabled) hostConnect(); // the server learns names on connect + }); + showModal('📱 Control this screen from a phone', body, [ + { label: 'Done', primary: true, onClick: () => { hostModalOpen = false; closeModal(); } }, + ]); + hostModalOpen = true; + renderHostModal(); + } + + // ========================================================================== + // Remote (this phone drives a host) + // ========================================================================== + const rc = { ws: null, open: false, state: null, stateAt: 0, queue: { items: [], idx: -1 }, retry: null, ping: null, seekTimer: null, latency: null, online: false, seeking: false, volTimer: null, drag: null }; + + const rcSend = (m) => { if (rc.ws && rc.ws.readyState === 1) rc.ws.send(JSON.stringify(m)); }; + const cmd = (name, args = {}) => rcSend({ type: 'cmd', cmd: name, ...args }); + + function setStatus(text, ok = false) { + $('rvStatus').textContent = text; + $('rvStatus').classList.toggle('ok', ok); + } + + function showPairForm(msg = '') { + $('rvPair').classList.remove('hidden'); + $('rvControl').classList.add('hidden'); + $('rvHostName').textContent = 'Remote'; + setStatus('Not paired'); + $('rvPairMsg').textContent = msg; + if (!$('rvName').value) $('rvName').value = (load(PAIR_KEY) || {}).name || guessName('Phone'); + } + + function rcConnect() { + const p = load(PAIR_KEY); + if (!p || !rc.open) return; + clearTimeout(rc.retry); + try { if (rc.ws) rc.ws.close(); } catch { /* gone */ } + $('rvPair').classList.add('hidden'); + $('rvControl').classList.remove('hidden'); + $('rvHostName').textContent = p.hostName || 'Screen'; + setStatus('Connecting…'); + const ws = new WebSocket(wsUrl({ role: 'remote', room: p.roomId, rid: p.remoteId, token: p.token, name: p.name || guessName('Phone') })); + rc.ws = ws; + ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onRemoteMessage(m); }; + ws.onclose = (e) => { + if (rc.ws !== ws) return; + rc.ws = null; + rc.online = false; + clearInterval(rc.ping); + if (e.code === 4001) { save(PAIR_KEY, null); showPairForm('This phone was unpaired by the screen — pair again.'); return; } + if (!rc.open) return; + setStatus(e.code === 4004 ? 'Screen offline — retrying…' : 'Reconnecting…'); + rc.retry = setTimeout(rcConnect, 4000); + }; + } + + function onRemoteMessage(m) { + DirectMedia.attach('remote-client', { send: rcSend, peers: () => [{ id: 'host', name: 'Paired screen', files: rc.state?.directAvailable && rc.state?.v ? [rc.state.v.id] : [] }] }); + if (m.type === 'direct') { DirectMedia.handle('remote-client', m); return; } + if (m.type === 'hello') { + rc.online = true; + $('rvHostName').textContent = m.hostName || 'Screen'; + if (m.state) { rc.state = m.state; rc.stateAt = Date.now(); } + if (m.queue) rc.queue = m.queue; + setStatus('Synced', true); + clearInterval(rc.ping); + const ping = () => rcSend({ type: 'ping', t: Date.now() }); + ping(); + rc.ping = setInterval(ping, 5000); + renderRemote(); renderQueue(); + } else if (m.type === 'state') { + rc.state = m.state; rc.stateAt = Date.now(); + renderRemote(); + } else if (m.type === 'queue') { + rc.queue = m.queue || { items: [], idx: -1 }; + renderQueue(); + } else if (m.type === 'pong') { + rc.latency = Date.now() - m.t; + if (rc.online) setStatus(`Synced · ${rc.latency} ms`, true); + } else if (m.type === 'host-offline') { + rc.online = false; + setStatus('Screen offline — waiting…'); + } + } + + function liveCur() { + const s = rc.state; + if (!s) return 0; + const cur = s.paused ? s.cur : s.cur + (Date.now() - rc.stateAt) / 1000; + return Math.min(cur, s.dur || cur); + } + + function renderRemote() { + const s = rc.state; + const v = s && s.v; + $('rvTitle').textContent = v ? v.title : 'Nothing playing'; + $('rvChannel').textContent = v ? v.channel : ''; + let directPlay = $('rvDirectPlay'); + if (!directPlay) { directPlay = document.createElement('button'); directPlay.id = 'rvDirectPlay'; directPlay.className = 'np-btn'; directPlay.style.minHeight = '44px'; directPlay.textContent = 'Play here from paired screen'; $('rvChannel').after(directPlay); } + directPlay.hidden = !v || !s.directAvailable || !DirectMedia.enabled(); + directPlay.onclick = () => v && playVideoAt({ ...v, duration: s.dur || 0 }, liveCur()); + + const thumb = $('rvThumb'); + if (v && v.thumbnail) { if (thumb.getAttribute('src') !== v.thumbnail) thumb.src = v.thumbnail; thumb.classList.remove('hidden'); } + else thumb.classList.add('hidden'); + $('rvToggle').textContent = s && !s.paused ? '⏸' : '▶'; + $('rvDur').textContent = clock((s && s.dur) || 0); + if (!rc.volTimer && document.activeElement !== $('rvVolume')) { + const pct = Math.round(((s && s.volume) ?? 1) * 100); + $('rvVolume').value = String(pct); + $('rvVolVal').textContent = pct + '%'; + } + const sleepMin = s && s.sleep ? Math.ceil(s.sleep / 60) : 0; + $('rvSleep').textContent = sleepMin ? `⏱ ${sleepMin} min` : '⏱ Sleep'; + $('rvSleep').classList.toggle('on', !!sleepMin); + $('rvService').classList.toggle('on', !!(s && s.service)); + renderSeek(); + } + + function renderSeek() { + if (rc.seeking || !rc.open) return; + const s = rc.state; + const cur = liveCur(); + $('rvCur').textContent = clock(cur); + $('rvSeek').value = s && s.dur ? String(Math.round((cur / s.dur) * 1000)) : '0'; + } + + function renderQueue() { + const q = rc.queue || { items: [], idx: -1 }; + const up = q.items.map((v, i) => ({ ...v, i })).filter((v) => v.i > q.idx); + $('rvQueueCount').textContent = up.length ? `${up.length} song${up.length === 1 ? '' : 's'}` : ''; + const list = $('rvQueue'); + list.innerHTML = up.length ? up.map((v) => ` +
+ ⠿ +
+
${escapeHtml(v.title)}
+
${escapeHtml(v.channel)}
+
+ ${v.duration ? clock(v.duration) : ''} + +
`).join('') : '
Nothing queued after this song.
'; + } + + // ---- drag to reorder (pointer events, works for touch + mouse) ---- + function onDragStart(e) { + const handle = e.target.closest('.rv-handle'); + if (!handle) return; + const row = handle.closest('.rv-row'); + e.preventDefault(); + const rows = [...$('rvQueue').querySelectorAll('.rv-row')]; + rc.drag = { row, rows, startY: e.clientY, from: Number(row.dataset.i), to: Number(row.dataset.i), h: row.offsetHeight }; + row.classList.add('dragging'); + row.setPointerCapture(e.pointerId); + row.addEventListener('pointermove', onDragMove); + row.addEventListener('pointerup', onDragEnd, { once: true }); + row.addEventListener('pointercancel', onDragEnd, { once: true }); + } + function onDragMove(e) { + const d = rc.drag; + if (!d) return; + const dy = e.clientY - d.startY; + d.row.style.transform = `translateY(${dy}px)`; + const pos = d.rows.indexOf(d.row); + const target = Math.max(0, Math.min(d.rows.length - 1, pos + Math.round(dy / d.h))); + d.to = Number(d.rows[target].dataset.i); + } + function onDragEnd() { + const d = rc.drag; + rc.drag = null; + if (!d) return; + d.row.removeEventListener('pointermove', onDragMove); + d.row.classList.remove('dragging'); + d.row.style.transform = ''; + if (d.to !== d.from) { + // Optimistic: reorder locally now, the host's queue push confirms it. + const items = rc.queue.items.slice(); + const [v] = items.splice(d.from, 1); + items.splice(d.to, 0, v); + rc.queue = { ...rc.queue, items }; + renderQueue(); + cmd('move', { from: d.from, to: d.to }); + } + } + + // ---- add to queue: search sheet ---- + function openAddSheet() { + const body = document.createElement('div'); + body.className = 'rv-add'; + body.innerHTML = ` +
+
`; + const results = body.querySelector('.rv-add-results'); + let found = []; + body.querySelector('form').addEventListener('submit', async (e) => { + e.preventDefault(); + const q = body.querySelector('.rv-add-q').value.trim(); + if (!q) return; + results.innerHTML = '
Searching…
'; + try { + const res = await API.search(q); + found = (res && res.ok && res.results) || []; + } catch { found = []; } + results.innerHTML = found.length ? found.slice(0, 20).map((v, i) => ` + `).join('') : '
No results.
'; + }); + results.addEventListener('click', (e) => { + const b = e.target.closest('[data-k]'); + if (!b) return; + const v = found[Number(b.dataset.k)]; + if (!v) return; + cmd('add', { video: { id: v.id, title: v.title, channel: v.channel, duration: v.duration, thumbnail: v.thumbnail } }); + b.classList.add('added'); + toast(`Added “${v.title}”`); + }); + showModal('+ Add to the screen’s queue', body, [{ label: 'Done', primary: true, onClick: closeModal }]); + setTimeout(() => body.querySelector('.rv-add-q').focus(), 50); + } + + async function doPair(codeRaw) { + const code = String(codeRaw || '').replace(/\D/g, ''); + const name = $('rvName').value.trim() || guessName('Phone'); + if (code.length !== 6) { $('rvPairMsg').textContent = 'Enter the 6-digit code from the screen.'; return; } + $('rvPairMsg').textContent = 'Pairing…'; + try { + const res = await fetch('/api/remote/pair', { + method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, name }), + }); + const j = await res.json().catch(() => null); + if (!j || !j.ok) { $('rvPairMsg').textContent = '⚠ ' + ((j && j.error) || `HTTP ${res.status}`); return; } + save(PAIR_KEY, { roomId: j.roomId, remoteId: j.remoteId, token: j.token, hostName: j.hostName, name: j.name }); + $('rvCode').value = ''; + rcConnect(); + } catch { + $('rvPairMsg').textContent = '⚠ Network error — try again'; + } + } + + async function openRemoteView({ code = '' } = {}) { + try { await Lazy.load('feature:direct'); } catch(error) { toast(error.message); return; } + rc.open = true; + rc.seekTimer = VisibleTimer.setIntervalWhenVisible(renderSeek, 500); + // This phone is the remote now — don't also play here. + try { if (Player.master && !Player.master.paused) Player.pause(); } catch { /* nothing loaded */ } + $('remoteView').classList.remove('hidden'); + document.body.classList.add('remote-open'); + if (code) { save(PAIR_KEY, null); showPairForm(); $('rvCode').value = code; doPair(code); return; } + if (load(PAIR_KEY)) rcConnect(); else showPairForm(); + } + + function closeRemoteView() { + rc.open = false; + rc.seekTimer?.clear(); + rc.seekTimer = null; + clearTimeout(rc.retry); + clearInterval(rc.ping); + const ws = rc.ws; + rc.ws = null; + try { if (ws) ws.close(); } catch { /* gone */ } + $('remoteView').classList.add('hidden'); + document.body.classList.remove('remote-open'); + } + + function openChooser() { + const hosting = hostCfg().enabled; + const paired = load(PAIR_KEY); + const body = document.createElement('div'); + body.innerHTML = ``; + showModal('📱 Remote', body, [ + { label: paired ? `Control “${paired.hostName}”` : 'Use this phone as a remote', onClick: () => { closeModal(); openRemoteView(); } }, + { label: hosting ? 'This screen: remote on' : 'Control this screen from a phone', primary: true, onClick: () => { closeModal(); openHostModal(); } }, + ]); + } + + function bindUi() { + $('rvClose').addEventListener('click', closeRemoteView); + $('rvMenu').addEventListener('click', () => { + const p = load(PAIR_KEY); + showModal('Remote options', document.createTextNode(p ? `Paired with “${p.hostName}”.` : 'Not paired.'), [ + { label: 'Close', onClick: closeModal }, + ...(p ? [{ label: 'Unpair this phone', danger: true, onClick: () => { closeModal(); save(PAIR_KEY, null); try { rc.ws && rc.ws.close(); } catch { /* gone */ } showPairForm('Unpaired.'); } }] : []), + ]); + }); + $('rvPairBtn').addEventListener('click', () => doPair($('rvCode').value)); + $('rvCode').addEventListener('keydown', (e) => { if (e.key === 'Enter') doPair($('rvCode').value); }); + $('rvToggle').addEventListener('click', () => { + cmd('toggle'); + if (rc.state) { rc.state.cur = liveCur(); rc.stateAt = Date.now(); rc.state.paused = !rc.state.paused; renderRemote(); } + }); + $('rvPrev').addEventListener('click', () => cmd('prev')); + $('rvNext').addEventListener('click', () => cmd('next')); + const seek = $('rvSeek'); + seek.addEventListener('input', () => { + rc.seeking = true; + const dur = (rc.state && rc.state.dur) || 0; + $('rvCur').textContent = clock((Number(seek.value) / 1000) * dur); + }); + seek.addEventListener('change', () => { + const dur = (rc.state && rc.state.dur) || 0; + const t = (Number(seek.value) / 1000) * dur; + cmd('seek', { t }); + if (rc.state) { rc.state.cur = t; rc.stateAt = Date.now(); } + rc.seeking = false; + }); + $('rvVolume').addEventListener('input', (e) => { + const pct = Number(e.target.value); + $('rvVolVal').textContent = pct + '%'; + clearTimeout(rc.volTimer); + rc.volTimer = setTimeout(() => { rc.volTimer = null; cmd('volume', { v: pct / 100 }); }, 120); + }); + $('rvQueue').addEventListener('pointerdown', onDragStart); + $('rvQueue').addEventListener('click', (e) => { + const rm = e.target.closest('[data-rm]'); + if (rm) { cmd('remove', { i: Number(rm.dataset.rm) }); return; } + if (e.target.closest('.rv-handle')) return; + const row = e.target.closest('.rv-row'); + if (row) cmd('jump', { i: Number(row.dataset.i) }); + }); + $('rvAdd').addEventListener('click', openAddSheet); + $('rvSleep').addEventListener('click', () => { + const options = [0, 15, 30, 45, 60, 90]; + const curMin = rc.state && rc.state.sleep ? Math.ceil(rc.state.sleep / 60) : 0; + const next = options.find((o) => o > curMin) ?? 0; + cmd('sleep', { min: next }); + toast(next ? `Screen pauses in ${next} min` : 'Sleep timer off'); + }); + $('rvService').addEventListener('click', () => cmd('service', { on: !(rc.state && rc.state.service) })); + // Hosts keep phones current once a second while anything plays. + setInterval(() => { if (host.ws && host.remotes.length) { pushState(); pushQueue(); } }, 1000); + document.addEventListener('visibilitychange', () => { + if (document.visibilityState === 'visible' && rc.open && !rc.ws) rcConnect(); + }); + } + + function boot() { + bindUi(); + if (hostCfg().enabled) hostConnect(); + // A scanned QR / shared link: /?pair=482913 + let code = ''; + try { code = (new URLSearchParams(location.search).get('pair') || '').replace(/\D/g, ''); } catch { /* no URL */ } + if (code) { + try { + const u = new URL(location.href); + u.searchParams.delete('pair'); + history.replaceState(null, '', u.pathname + u.search + u.hash); + } catch { /* leave the URL */ } + openRemoteView({ code }); + } + } + + return { boot, changed, openChooser, openHostModal }; +})(); diff --git a/frontend/sw.js b/frontend/sw.js index 4bfd5b0..f7dab0e 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -141,6 +141,7 @@ const SHELL = [ '/views-core.js', '/section-rail.js', '/presenter.js', + '/remote-client.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', From 94ea211605199d64d7dcc25bd866ad982d163d74 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:42:35 +0800 Subject: [PATCH 35/81] Lazy-load watch-party sessions behind synchronous playback hooks --- frontend/app-seams.test.js | 9 + frontend/app.js | 474 ++------------------------------- frontend/assets.json | 8 + frontend/index.html | 2 +- frontend/sw.js | 1 + frontend/watch-party-client.js | 458 +++++++++++++++++++++++++++++++ 6 files changed, 497 insertions(+), 455 deletions(-) create mode 100644 frontend/watch-party-client.js diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index c2031ce..d7dfc14 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -48,3 +48,12 @@ test('remote facade preserves synchronous no-session and loaded changed hooks',( let calls=0;context.window.YT={Remote:{changed:()=>{calls++;return 'sync';}}}; assert.equal(context.api.changed(),'sync');assert.equal(calls,1); }); + +test('watch-party facade keeps playback decisions synchronous before and after loading',()=>{ + const source=app.match(/\/\* Party facade \*\/([\s\S]*?)\/\* End party facade \*\//)?.[1];assert.ok(source); + const context=require('node:vm').createContext({window:{},Lazy:{proxy:()=>({}),onLoad(){}}}); + require('node:vm').runInContext(source+';globalThis.api=Party;',context); + for(const method of ['guestActive','intercept','nextDJ'])assert.equal(context.api[method]('next'),false); + context.window.YT={Party:{guestActive:()=>true,intercept:action=>action==='next',nextDJ:()=>true}}; + for(const method of ['guestActive','intercept','nextDJ'])assert.equal(context.api[method]('next'),true); +}); diff --git a/frontend/app.js b/frontend/app.js index f2f0f87..3706557 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -6169,461 +6169,27 @@ const External = (() => { // player either sends a command (when the host allows control) or goes // "off sync" until they tap Re-sync. Voice chat is a WebRTC mesh between // members who switch it on (STUN only — works on most home/mobile networks). -const Party = (() => { - const noop = { boot() {}, guestActive: () => false, intercept: () => false, afterLoad() {} }; - if (!WEB || typeof WebSocket === 'undefined') return noop; - const PID_KEY = 'ytpPartyPid', HOST_KEY = 'ytpPartyHost', NAME_KEY = 'ytpPartyName'; - const ls = { - get: (k) => { try { return localStorage.getItem(k); } catch { return null; } }, - set: (k, v) => { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, v); } catch { /* blocked */ } }, - }; - let pid = ls.get(PID_KEY); - if (!pid) { pid = 'p' + Math.random().toString(36).slice(2, 12) + Date.now().toString(36); ls.set(PID_KEY, pid); } - const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/party?${new URLSearchParams(q)}`; +/* Party facade */ +const Party = { + ...Lazy.proxy('feature:watch-party', ['open', '_join', '_start'], 'Party'), + guestActive: () => window.YT?.Party?.guestActive() || false, + intercept: action => window.YT?.Party?.intercept(action) || false, + nextDJ: () => window.YT?.Party?.nextDJ() || false, + afterLoad: () => window.YT?.Party?.afterLoad(), + renderLyricsToggle: () => window.YT?.Party?.renderLyricsToggle(), + state: () => window.YT?.Party?.state() || { role: null }, + boot() { + if (!WEB) return; + $('navPartyBtn').addEventListener('click', () => Party.open().catch(error => toast(error.message))); + Lazy.intent($('navPartyBtn'), 'feature:watch-party'); + let resume = false; + try { const host = JSON.parse(localStorage.getItem('ytpPartyHost') || 'null'); resume = !!(host?.code && host?.secret); } catch {} + if (resume || new URLSearchParams(location.search).has('party')) Lazy.load('feature:watch-party').catch(error => toast(error.message)); + }, +}; +Lazy.onLoad('feature:watch-party', () => window.YT.Party.boot()); +/* End party facade */ - const st = { - ws: null, role: null, code: '', secret: '', name: '', members: [], chat: [], state: null, offset: 0, - dj: { enabled: false, entries: [] }, djPending: false, - allowControl: false, quietUntil: 0, detached: false, retry: null, pushTimer: null, driftTimer: null, lastPush: '', - voice: { on: false, stream: null, muted: false, pcs: new Map(), audios: new Map() }, - minimized: false, - }; - const inParty = () => !!st.role; - const isHost = () => st.role === 'host'; - const guestActive = () => st.role === 'guest' && !st.detached; - const send = (m) => { if (st.ws && st.ws.readyState === 1) st.ws.send(JSON.stringify(m)); }; - const serverNow = () => Date.now() + st.offset; - const myName = () => st.name || (data.profile && data.profile.name) || ls.get(NAME_KEY) || ''; - - // ---------- connection ---------- - function connect() { - clearTimeout(st.retry); - const q = { role: st.role, pid, name: myName() || 'Guest' }; - if (st.code) q.code = st.code; - if (isHost() && st.secret) q.secret = st.secret; - const ws = new WebSocket(wsUrl(q)); - st.ws = ws; - ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onMessage(m); }; - ws.onclose = (e) => { - if (st.ws !== ws) return; - st.ws = null; - if (!inParty()) return; - if (e.code === 4010 || e.code === 4004 || e.code === 4003) { - const why = e.code === 4004 ? 'That party code doesn’t exist (or has ended).' : e.code === 4003 ? 'This party belongs to another host.' : 'The party ended.'; - leave(false); - toast(`🎉 ${why}`, { duration: 5000 }); - return; - } - setStatus('Reconnecting…'); - st.retry = setTimeout(connect, 3000); - }; - ws.onerror = () => { if (!st.code && isHost()) setStatus('Could not reach the server'); }; - } - - function onMessage(m) { - DirectMedia.attach('party', { send, peers: () => st.members.filter(m => m.pid !== pid).map(m => ({ id: m.pid, name: m.name, files: m.host && st.state?.directAvailable && st.state?.v ? [st.state.v.id] : [] })) }); - if (m.type === 'direct') { DirectMedia.handle('party', m); return; } - if (m.type === 'hello') { - st.code = m.code; - if (m.secret) { st.secret = m.secret; ls.set(HOST_KEY, JSON.stringify({ code: m.code, secret: m.secret })); } - st.offset = (m.now || Date.now()) - Date.now(); - st.members = m.members || []; - st.chat = m.chat || []; - st.dj = m.dj || { enabled: false, entries: [] }; st.djPending = false; - st.allowControl = !!m.allowControl; - setStatus(isHost() ? 'You’re hosting' : 'Synced with the host'); - render(); - if (isHost()) pushState(true); - else if (m.state) applyState(m.state); - if (st.voice.on) { send({ type: 'voice', on: true }); connectVoicePeers(); } - } else if (m.type === 'dj') { - st.dj = { enabled: m.enabled, entries: m.entries || [] }; render(); - } else if (m.type === 'dj-play' && isHost()) { - st.djPending = false; if (m.video) { Player._handoff = null; playVideoAt(m.video); } else { st.dj.entries = st.dj.entries.filter(e => !e.approved); advanceQueue(); } - } else if (m.type === 'state') { - st.state = m.state; - if (st.role === 'guest') applyState(m.state); - } else if (m.type === 'members') { - st.members = m.members || []; - if (m.joined) sysMsg(`${m.joined} joined`); - if (m.left) sysMsg(`${m.left} left${m.hostAway ? ' — waiting for the host to come back' : ''}`); - render(); - syncVoicePeers(); - } else if (m.type === 'chat') { - st.chat.push(m.msg); - if (st.chat.length > 100) st.chat.shift(); - renderChat(); - if (m.msg.pid !== pid && (st.minimized || $('partyPanel').classList.contains('hidden'))) toast(`💬 ${m.msg.from}: ${m.msg.text}`); - } else if (m.type === 'settings') { - st.allowControl = !!m.allowControl; - render(); - if (!isHost()) sysMsg(st.allowControl ? 'The host lets everyone control playback' : 'Only the host controls playback now'); - } else if (m.type === 'cmd' && isHost()) { - runCommand(m); - } else if (m.type === 'rtc') { - onRtc(m.from, m.data); - } else if (m.type === 'ended') { - toast(`🎉 ${m.reason || 'The party ended'}`, { duration: 5000 }); - } - } - - // ---------- host: broadcast ---------- - function stateNow() { - const meta = current && current.meta; - const M = Player.master; - return { - directAvailable: !!meta && cachedIds.has(meta.id) && DirectMedia.enabled() && data.settings.p2pShare !== false, - v: meta ? { id: meta.id, title: meta.title || '', channel: meta.channel || '', thumbnail: meta.thumbnail || '', duration: meta.duration || 0 } : null, - cur: M ? M.currentTime || 0 : 0, - paused: !M || M.paused, - rate: (M && M.playbackRate) || 1, - }; - } - function pushState(force = false) { - if (!isHost() || !st.ws) return; - const s = stateNow(); - const key = JSON.stringify({ ...s, cur: Math.round(s.cur) }); - if (!force && key === st.lastPush) return; - st.lastPush = key; - send({ type: 'state', state: s }); - } - function runCommand(m) { - switch (m.cmd) { - case 'toggle': Player.toggle(); break; - case 'play': Player.play(); break; - case 'pause': Player.pause(); break; - case 'seek': if (Number.isFinite(Number(m.t))) Player.seek(Math.max(0, Number(m.t))); break; - case 'next': playNext(); break; - case 'prev': playPrev(); break; - default: return; - } - toast(`🎉 ${m.from}: ${m.cmd === 'seek' ? `jumped to ${fmtTime(Number(m.t))}` : m.cmd}`); - setTimeout(() => pushState(true), 200); - } - - // ---------- guest: follow ---------- - const quiet = (ms = 1500) => { st.quietUntil = Date.now() + ms; }; - function targetTime(s) { - if (!s) return 0; - return s.paused ? s.cur : s.cur + ((serverNow() - (s.ts || serverNow())) / 1000) * (s.rate || 1); - } - async function applyState(s) { - st.state = s; - if (st.role !== 'guest' || st.detached || !s || !s.v) { render(); return; } - const target = targetTime(s); - if (!current || !current.meta || current.meta.id !== s.v.id) { - quiet(6000); - await playVideoAt({ ...s.v }, target); - return; - } - const M = Player.master; - if (!M) return; - if ((M.playbackRate || 1) !== (s.rate || 1)) { els.speed.value = String(s.rate || 1); Player.applySpeed(); } - if (Math.abs((M.currentTime || 0) - target) > 1.5) { quiet(); Player.seek(target); } - if (s.paused && !M.paused) { quiet(); Player.pause(); updatePlayBtn(); } - else if (!s.paused && M.paused) { quiet(); Player.play(); updatePlayBtn(); } - } - // A guest's own actions: forwarded when allowed, else they go off sync. - function onLocalAction(kind) { - if (st.role !== 'guest' || st.detached || Date.now() < st.quietUntil) return; - if (st.allowControl) { - const M = Player.master; - if (kind === 'seeked') send({ type: 'cmd', cmd: 'seek', t: M.currentTime }); - else send({ type: 'cmd', cmd: kind === 'pause' ? 'pause' : 'play' }); - return; - } - st.detached = true; - setStatus('Off sync — you paused or skipped on your own'); - render(); - } - // playNext/playPrev guard: guests don't change songs themselves. - function intercept(cmd) { - if (st.role !== 'guest' || st.detached) return false; - if (st.allowControl) send({ type: 'cmd', cmd }); - else toast('🎉 The host picks the songs in a watch party'); - return true; - } - function resync() { - st.detached = false; - setStatus('Synced with the host'); - render(); - applyState(st.state); - } - - // ---------- voice (WebRTC mesh) ---------- - const ICE = [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun1.l.google.com:19302' }]; - function peer(other) { - let pc = st.voice.pcs.get(other); - if (pc) return pc; - pc = new RTCPeerConnection({ iceServers: ICE }); - st.voice.pcs.set(other, pc); - if (st.voice.stream) st.voice.stream.getTracks().forEach((t) => pc.addTrack(t, st.voice.stream)); - pc.onicecandidate = (e) => { if (e.candidate) send({ type: 'rtc', to: other, data: { ice: e.candidate } }); }; - pc.ontrack = (e) => { - let a = st.voice.audios.get(other); - if (!a) { a = new Audio(); a.autoplay = true; a.setAttribute('playsinline', ''); st.voice.audios.set(other, a); } - a.srcObject = e.streams[0]; - a.play().catch(() => {}); - }; - pc.onconnectionstatechange = () => { if (['failed', 'closed'].includes(pc.connectionState)) dropPeer(other); render(); }; - return pc; - } - function dropPeer(other) { - const pc = st.voice.pcs.get(other); - if (pc) { try { pc.close(); } catch { /* closed */ } st.voice.pcs.delete(other); } - const a = st.voice.audios.get(other); - if (a) { a.srcObject = null; st.voice.audios.delete(other); } - } - async function offerTo(other) { - const pc = peer(other); - const offer = await pc.createOffer(); - await pc.setLocalDescription(offer); - send({ type: 'rtc', to: other, data: { sdp: pc.localDescription } }); - } - async function onRtc(from, d) { - if (!st.voice.on || !d) return; - try { - if (d.sdp) { - const pc = peer(from); - await pc.setRemoteDescription(d.sdp); - if (d.sdp.type === 'offer') { - const ans = await pc.createAnswer(); - await pc.setLocalDescription(ans); - send({ type: 'rtc', to: from, data: { sdp: pc.localDescription } }); - } - } else if (d.ice) { - await peer(from).addIceCandidate(d.ice); - } - } catch { /* a glare/ICE hiccup — the next members update retries */ } - } - // The member with the smaller pid makes the offer, so each pair connects once. - function connectVoicePeers() { - if (!st.voice.on) return; - for (const m of st.members) if (m.voice && m.pid !== pid && !st.voice.pcs.has(m.pid) && pid < m.pid) offerTo(m.pid).catch(() => {}); - } - function syncVoicePeers() { - const voiced = new Set(st.members.filter((m) => m.voice).map((m) => m.pid)); - for (const other of [...st.voice.pcs.keys()]) if (!voiced.has(other)) dropPeer(other); - connectVoicePeers(); - } - async function toggleVoice() { - if (st.voice.on) { - st.voice.on = false; - for (const other of [...st.voice.pcs.keys()]) dropPeer(other); - if (st.voice.stream) st.voice.stream.getTracks().forEach((t) => t.stop()); - st.voice.stream = null; - send({ type: 'voice', on: false }); - render(); - return; - } - if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia || typeof RTCPeerConnection === 'undefined') { toast('Voice chat isn’t supported in this browser'); return; } - try { - st.voice.stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } }); - } catch (e) { - toast('🎤 Microphone blocked: ' + (e.message || e.name)); - return; - } - st.voice.on = true; - st.voice.muted = false; - send({ type: 'voice', on: true }); - toast('🎤 Voice on — headphones stop the music echoing into your mic', { duration: 5000 }); - render(); - connectVoicePeers(); - } - function toggleMute() { - if (!st.voice.stream) return; - st.voice.muted = !st.voice.muted; - st.voice.stream.getAudioTracks().forEach((t) => { t.enabled = !st.voice.muted; }); - render(); - } - - // ---------- lifecycle ---------- - function start() { - st.role = 'host'; - st.code = ''; st.secret = ''; st.chat = []; st.members = []; - ls.set(HOST_KEY, null); - showPanel(); - setStatus('Starting…'); - connect(); - beginTimers(); - } - function join(code, name) { - code = String(code || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); - if (code.length !== 6) { toast('Party codes have 6 letters/numbers'); return; } - if (name) { st.name = name; ls.set(NAME_KEY, name); } - st.role = 'guest'; - st.code = code; st.detached = false; st.chat = []; st.members = []; - showPanel(); - setStatus('Joining…'); - connect(); - beginTimers(); - } - function beginTimers() { - clearInterval(st.pushTimer); clearInterval(st.driftTimer); - st.pushTimer = setInterval(() => pushState(), 3000); - st.driftTimer = setInterval(() => { if (st.role === 'guest' && st.state && !st.detached) applyState(st.state); }, 2500); - } - function leave(sendEnd = true) { - if (isHost() && sendEnd) send({ type: 'end' }); - if (st.voice.on) toggleVoice(); - const ws = st.ws; - st.ws = null; - st.role = null; st.code = ''; st.secret = ''; - clearTimeout(st.retry); clearInterval(st.pushTimer); clearInterval(st.driftTimer); - try { if (ws) ws.close(); } catch { /* gone */ } - ls.set(HOST_KEY, null); - $('partyPanel').classList.add('hidden'); - render(); - } - - // ---------- UI ---------- - // Lyrics-instead-of-video is a per-device view: each guest chooses it for - // themselves, and the host's playback is untouched (the video keeps playing - // behind the lyrics, so sync and audio carry on). - const lyricsOn = () => !!(Notes.stageLyrics && Notes.stageLyrics.on()); - function renderLyricsToggle() { - const b = document.querySelector('#partyPanel .pt-lyrics'); - if (!b) return; - b.textContent = lyricsOn() ? '📺 Show the video' : '🎤 Lyrics instead of video'; - b.classList.toggle('on', lyricsOn()); - } - function setStatus(t) { const el = $('ptStatus'); if (el) el.textContent = t; } - function sysMsg(text) { st.chat.push({ sys: true, text, at: Date.now() }); renderChat(); } - function link() { return `${location.origin}/?party=${st.code}`; } - function showPanel() { Lazy.load('feature:party-dj').then(render).catch(error=>toast(error.message)); Lazy.load('feature:direct').catch(error=>toast(error.message)); $('partyPanel').classList.remove('hidden'); st.minimized = false; $('partyPanel').classList.remove('min'); render(); } - - function render() { - const panel = $('partyPanel'); - const chip = $('navPartyBtn'); - if (chip) { - const label = chip.querySelector('.nav-label'); - if (label) label.textContent = inParty() ? `Party · ${st.members.length}` : 'Watch party'; - else chip.textContent = inParty() ? `🎉 Party · ${st.members.length}` : '🎉 Watch party'; - } - if (!panel || panel.classList.contains('hidden')) return; - const nameOk = !!myName(); - if (!inParty()) { - panel.querySelector('.pt-body').innerHTML = ` - - ${nameOk ? '' : ''} - -
or join one
-
`; - $('ptTitle').textContent = '🎉 Watch party'; - setStatus(''); - return; - } - $('ptTitle').textContent = `🎉 Party ${st.code || '…'}`; - const s = st.state && st.state.v; - panel.querySelector('.pt-body').innerHTML = ` - ${st.code ? `
${escapeHtml(link())}${navigator.share ? '' : ''}
` : ''} - ${!isHost() && s ? `
▶ ${escapeHtml(s.title)}
` : ''} - ${!isHost() && st.detached ? '' : ''} -
${st.members.map((m) => `${m.host ? '👑 ' : ''}${escapeHtml(m.name)}${m.voice ? ' 🎤' : ''}`).join('')}
- ${isHost() ? `` : ''} - -
- - ${st.voice.on ? `` : ''} - ${st.voice.on ? `${st.voice.pcs.size} connected` : ''} -
-
-
- `; - const dj = document.createElement('div'); panel.querySelector('.pt-body').append(dj); - if (Lazy.loaded('feature:party-dj')) PartyDJ.render(dj, { state: st.dj, host: isHost(), pid, send, search: async q => { const result = await API.search(q); return result.results || result.videos || []; } }); - renderChat(); - } - function renderChat() { - const box = $('ptChat'); - if (!box) return; - box.innerHTML = st.chat.map((c) => c.sys - ? `
${escapeHtml(c.text)}
` - : `
${escapeHtml(c.from)} ${escapeHtml(c.text)}
`).join(''); - box.scrollTop = box.scrollHeight; - } - - function bindUi() { - const panel = $('partyPanel'); - $('navPartyBtn').addEventListener('click', () => { - if (typeof closeSidebar === 'function') { try { closeSidebar(); } catch { /* not open */ } } - if (panel.classList.contains('hidden')) showPanel(); - else if (st.minimized) { st.minimized = false; panel.classList.remove('min'); } - else if (!inParty()) panel.classList.add('hidden'); - else { st.minimized = true; panel.classList.add('min'); } - }); - $('ptMin').addEventListener('click', () => { - if (!inParty()) { panel.classList.add('hidden'); return; } - st.minimized = !st.minimized; - panel.classList.toggle('min', st.minimized); - }); - panel.addEventListener('keydown', (e) => e.stopPropagation()); - panel.addEventListener('click', async (e) => { - const a = e.target.closest('[data-act]'); - if (!a || a.tagName === 'INPUT') return; - const act = a.dataset.act; - const nameIn = panel.querySelector('.pt-name'); - const name = nameIn ? nameIn.value.trim() : ''; - if ((act === 'start' || act === 'join') && !myName() && !name) { toast('Enter your name first'); if (nameIn) nameIn.focus(); return; } - if (name) { st.name = name; ls.set(NAME_KEY, name); } - if (act === 'start') start(); - else if (act === 'join') join(panel.querySelector('.pt-code').value); - else if (act === 'copy') { try { await navigator.clipboard.writeText(link()); toast('Party link copied ✓'); } catch { toast('Copy blocked'); } } - else if (act === 'share') { try { await navigator.share({ title: 'Join my watch party', url: link() }); } catch { /* dismissed */ } } - else if (act === 'resync') resync(); - else if (act === 'voice') toggleVoice(); - else if (act === 'mute') toggleMute(); - else if (act === 'lyrics') { Notes.stageLyrics.set(!lyricsOn()); renderLyricsToggle(); } - else if (act === 'leave') leave(true); - }); - panel.addEventListener('change', (e) => { - if (e.target.dataset.act === 'allow') { st.allowControl = e.target.checked; send({ type: 'settings', allowControl: st.allowControl }); } - }); - panel.addEventListener('submit', (e) => { - e.preventDefault(); - const input = panel.querySelector('.pt-msg'); - const text = input.value.trim(); - if (text) { send({ type: 'chat', text }); input.value = ''; } - }); - // Host: push on every player change; guests: detect their own actions. - ['play', 'pause', 'seeked', 'ratechange', 'loadedmetadata'].forEach((ev) => { - [els.video, els.audio].forEach((el) => el.addEventListener(ev, (e) => { - if (el !== Player.master) return; - if (isHost()) pushState(true); - else if (ev === 'play' || ev === 'pause' || ev === 'seeked') onLocalAction(ev); - })); - }); - } - - function boot() { - bindUi(); - render(); - // Resume hosting after a reload. - try { - const h = JSON.parse(ls.get(HOST_KEY) || 'null'); - if (h && h.code && h.secret) { st.role = 'host'; st.code = h.code; st.secret = h.secret; showPanel(); connect(); beginTimers(); } - } catch { /* none */ } - let code = ''; - try { code = (new URLSearchParams(location.search).get('party') || '').toUpperCase(); } catch { /* no URL */ } - if (code) { - try { const u = new URL(location.href); u.searchParams.delete('party'); history.replaceState(null, '', u.pathname + u.search + u.hash); } catch { /* keep */ } - if (myName()) join(code); - else { showPanel(); const c = $('partyPanel').querySelector('.pt-code'); if (c) c.value = code; toast('Enter your name, then tap Join'); } - } - } - - return { - nextDJ: () => { if (!isHost() || !st.dj.enabled || !st.dj.entries.some(e => e.approved)) return false; if (!st.djPending) { st.djPending = true; send({ type: 'dj', action: 'take' }); } return true; }, - boot, guestActive, intercept, renderLyricsToggle, afterLoad: () => pushState(true), - state: () => ({ - role: st.role, code: st.code, detached: st.detached, members: st.members.length, voice: st.voice.on, - peers: st.voice.pcs.size, peerStates: [...st.voice.pcs.values()].map((pc) => pc.connectionState), - remoteAudio: [...st.voice.audios.values()].filter((a) => a.srcObject && a.srcObject.getAudioTracks().some((t) => t.readyState === 'live')).length, - chat: st.chat.length, allowControl: st.allowControl, - }), - _join: join, _start: start, - }; -})(); function updateProgress() { const cur = Player.master.currentTime || 0; diff --git a/frontend/assets.json b/frontend/assets.json index af81548..ef30f6f 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -332,6 +332,14 @@ "files": [ "/remote-client.js" ] + }, + "feature:watch-party": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/watch-party-client.js" + ] } } } diff --git a/frontend/index.html b/frontend/index.html index 9ceac1d..e288275 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + diff --git a/frontend/sw.js b/frontend/sw.js index f7dab0e..74c2329 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -142,6 +142,7 @@ const SHELL = [ '/section-rail.js', '/presenter.js', '/remote-client.js', + '/watch-party-client.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', diff --git a/frontend/watch-party-client.js b/frontend/watch-party-client.js new file mode 100644 index 0000000..c88b8c2 --- /dev/null +++ b/frontend/watch-party-client.js @@ -0,0 +1,458 @@ +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).Party = (() => { + const noop = { boot() {}, guestActive: () => false, intercept: () => false, afterLoad() {} }; + if (!WEB || typeof WebSocket === 'undefined') return noop; + const PID_KEY = 'ytpPartyPid', HOST_KEY = 'ytpPartyHost', NAME_KEY = 'ytpPartyName'; + const ls = { + get: (k) => { try { return localStorage.getItem(k); } catch { return null; } }, + set: (k, v) => { try { if (v == null) localStorage.removeItem(k); else localStorage.setItem(k, v); } catch { /* blocked */ } }, + }; + let pid = ls.get(PID_KEY); + if (!pid) { pid = 'p' + Math.random().toString(36).slice(2, 12) + Date.now().toString(36); ls.set(PID_KEY, pid); } + const wsUrl = (q) => `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws/party?${new URLSearchParams(q)}`; + + const st = { + ws: null, role: null, code: '', secret: '', name: '', members: [], chat: [], state: null, offset: 0, + dj: { enabled: false, entries: [] }, djPending: false, + allowControl: false, quietUntil: 0, detached: false, retry: null, pushTimer: null, driftTimer: null, lastPush: '', + voice: { on: false, stream: null, muted: false, pcs: new Map(), audios: new Map() }, + minimized: false, + }; + const inParty = () => !!st.role; + const isHost = () => st.role === 'host'; + const guestActive = () => st.role === 'guest' && !st.detached; + const send = (m) => { if (st.ws && st.ws.readyState === 1) st.ws.send(JSON.stringify(m)); }; + const serverNow = () => Date.now() + st.offset; + const myName = () => st.name || (data.profile && data.profile.name) || ls.get(NAME_KEY) || ''; + + // ---------- connection ---------- + function connect() { + clearTimeout(st.retry); + const q = { role: st.role, pid, name: myName() || 'Guest' }; + if (st.code) q.code = st.code; + if (isHost() && st.secret) q.secret = st.secret; + const ws = new WebSocket(wsUrl(q)); + st.ws = ws; + ws.onmessage = (e) => { let m; try { m = JSON.parse(e.data); } catch { return; } onMessage(m); }; + ws.onclose = (e) => { + if (st.ws !== ws) return; + st.ws = null; + if (!inParty()) return; + if (e.code === 4010 || e.code === 4004 || e.code === 4003) { + const why = e.code === 4004 ? 'That party code doesn’t exist (or has ended).' : e.code === 4003 ? 'This party belongs to another host.' : 'The party ended.'; + leave(false); + toast(`🎉 ${why}`, { duration: 5000 }); + return; + } + setStatus('Reconnecting…'); + st.retry = setTimeout(connect, 3000); + }; + ws.onerror = () => { if (!st.code && isHost()) setStatus('Could not reach the server'); }; + } + + function onMessage(m) { + DirectMedia.attach('party', { send, peers: () => st.members.filter(m => m.pid !== pid).map(m => ({ id: m.pid, name: m.name, files: m.host && st.state?.directAvailable && st.state?.v ? [st.state.v.id] : [] })) }); + if (m.type === 'direct') { DirectMedia.handle('party', m); return; } + if (m.type === 'hello') { + st.code = m.code; + if (m.secret) { st.secret = m.secret; ls.set(HOST_KEY, JSON.stringify({ code: m.code, secret: m.secret })); } + st.offset = (m.now || Date.now()) - Date.now(); + st.members = m.members || []; + st.chat = m.chat || []; + st.dj = m.dj || { enabled: false, entries: [] }; st.djPending = false; + st.allowControl = !!m.allowControl; + setStatus(isHost() ? 'You’re hosting' : 'Synced with the host'); + render(); + if (isHost()) pushState(true); + else if (m.state) applyState(m.state); + if (st.voice.on) { send({ type: 'voice', on: true }); connectVoicePeers(); } + } else if (m.type === 'dj') { + st.dj = { enabled: m.enabled, entries: m.entries || [] }; render(); + } else if (m.type === 'dj-play' && isHost()) { + st.djPending = false; if (m.video) { Player._handoff = null; playVideoAt(m.video); } else { st.dj.entries = st.dj.entries.filter(e => !e.approved); advanceQueue(); } + } else if (m.type === 'state') { + st.state = m.state; + if (st.role === 'guest') applyState(m.state); + } else if (m.type === 'members') { + st.members = m.members || []; + if (m.joined) sysMsg(`${m.joined} joined`); + if (m.left) sysMsg(`${m.left} left${m.hostAway ? ' — waiting for the host to come back' : ''}`); + render(); + syncVoicePeers(); + } else if (m.type === 'chat') { + st.chat.push(m.msg); + if (st.chat.length > 100) st.chat.shift(); + renderChat(); + if (m.msg.pid !== pid && (st.minimized || $('partyPanel').classList.contains('hidden'))) toast(`💬 ${m.msg.from}: ${m.msg.text}`); + } else if (m.type === 'settings') { + st.allowControl = !!m.allowControl; + render(); + if (!isHost()) sysMsg(st.allowControl ? 'The host lets everyone control playback' : 'Only the host controls playback now'); + } else if (m.type === 'cmd' && isHost()) { + runCommand(m); + } else if (m.type === 'rtc') { + onRtc(m.from, m.data); + } else if (m.type === 'ended') { + toast(`🎉 ${m.reason || 'The party ended'}`, { duration: 5000 }); + } + } + + // ---------- host: broadcast ---------- + function stateNow() { + const meta = current && current.meta; + const M = Player.master; + return { + directAvailable: !!meta && cachedIds.has(meta.id) && DirectMedia.enabled() && data.settings.p2pShare !== false, + v: meta ? { id: meta.id, title: meta.title || '', channel: meta.channel || '', thumbnail: meta.thumbnail || '', duration: meta.duration || 0 } : null, + cur: M ? M.currentTime || 0 : 0, + paused: !M || M.paused, + rate: (M && M.playbackRate) || 1, + }; + } + function pushState(force = false) { + if (!isHost() || !st.ws) return; + const s = stateNow(); + const key = JSON.stringify({ ...s, cur: Math.round(s.cur) }); + if (!force && key === st.lastPush) return; + st.lastPush = key; + send({ type: 'state', state: s }); + } + function runCommand(m) { + switch (m.cmd) { + case 'toggle': Player.toggle(); break; + case 'play': Player.play(); break; + case 'pause': Player.pause(); break; + case 'seek': if (Number.isFinite(Number(m.t))) Player.seek(Math.max(0, Number(m.t))); break; + case 'next': playNext(); break; + case 'prev': playPrev(); break; + default: return; + } + toast(`🎉 ${m.from}: ${m.cmd === 'seek' ? `jumped to ${fmtTime(Number(m.t))}` : m.cmd}`); + setTimeout(() => pushState(true), 200); + } + + // ---------- guest: follow ---------- + const quiet = (ms = 1500) => { st.quietUntil = Date.now() + ms; }; + function targetTime(s) { + if (!s) return 0; + return s.paused ? s.cur : s.cur + ((serverNow() - (s.ts || serverNow())) / 1000) * (s.rate || 1); + } + async function applyState(s) { + st.state = s; + if (st.role !== 'guest' || st.detached || !s || !s.v) { render(); return; } + const target = targetTime(s); + if (!current || !current.meta || current.meta.id !== s.v.id) { + quiet(6000); + await playVideoAt({ ...s.v }, target); + return; + } + const M = Player.master; + if (!M) return; + if ((M.playbackRate || 1) !== (s.rate || 1)) { els.speed.value = String(s.rate || 1); Player.applySpeed(); } + if (Math.abs((M.currentTime || 0) - target) > 1.5) { quiet(); Player.seek(target); } + if (s.paused && !M.paused) { quiet(); Player.pause(); updatePlayBtn(); } + else if (!s.paused && M.paused) { quiet(); Player.play(); updatePlayBtn(); } + } + // A guest's own actions: forwarded when allowed, else they go off sync. + function onLocalAction(kind) { + if (st.role !== 'guest' || st.detached || Date.now() < st.quietUntil) return; + if (st.allowControl) { + const M = Player.master; + if (kind === 'seeked') send({ type: 'cmd', cmd: 'seek', t: M.currentTime }); + else send({ type: 'cmd', cmd: kind === 'pause' ? 'pause' : 'play' }); + return; + } + st.detached = true; + setStatus('Off sync — you paused or skipped on your own'); + render(); + } + // playNext/playPrev guard: guests don't change songs themselves. + function intercept(cmd) { + if (st.role !== 'guest' || st.detached) return false; + if (st.allowControl) send({ type: 'cmd', cmd }); + else toast('🎉 The host picks the songs in a watch party'); + return true; + } + function resync() { + st.detached = false; + setStatus('Synced with the host'); + render(); + applyState(st.state); + } + + // ---------- voice (WebRTC mesh) ---------- + const ICE = [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun1.l.google.com:19302' }]; + function peer(other) { + let pc = st.voice.pcs.get(other); + if (pc) return pc; + pc = new RTCPeerConnection({ iceServers: ICE }); + st.voice.pcs.set(other, pc); + if (st.voice.stream) st.voice.stream.getTracks().forEach((t) => pc.addTrack(t, st.voice.stream)); + pc.onicecandidate = (e) => { if (e.candidate) send({ type: 'rtc', to: other, data: { ice: e.candidate } }); }; + pc.ontrack = (e) => { + let a = st.voice.audios.get(other); + if (!a) { a = new Audio(); a.autoplay = true; a.setAttribute('playsinline', ''); st.voice.audios.set(other, a); } + a.srcObject = e.streams[0]; + a.play().catch(() => {}); + }; + pc.onconnectionstatechange = () => { if (['failed', 'closed'].includes(pc.connectionState)) dropPeer(other); render(); }; + return pc; + } + function dropPeer(other) { + const pc = st.voice.pcs.get(other); + if (pc) { try { pc.close(); } catch { /* closed */ } st.voice.pcs.delete(other); } + const a = st.voice.audios.get(other); + if (a) { a.srcObject = null; st.voice.audios.delete(other); } + } + async function offerTo(other) { + const pc = peer(other); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + send({ type: 'rtc', to: other, data: { sdp: pc.localDescription } }); + } + async function onRtc(from, d) { + if (!st.voice.on || !d) return; + try { + if (d.sdp) { + const pc = peer(from); + await pc.setRemoteDescription(d.sdp); + if (d.sdp.type === 'offer') { + const ans = await pc.createAnswer(); + await pc.setLocalDescription(ans); + send({ type: 'rtc', to: from, data: { sdp: pc.localDescription } }); + } + } else if (d.ice) { + await peer(from).addIceCandidate(d.ice); + } + } catch { /* a glare/ICE hiccup — the next members update retries */ } + } + // The member with the smaller pid makes the offer, so each pair connects once. + function connectVoicePeers() { + if (!st.voice.on) return; + for (const m of st.members) if (m.voice && m.pid !== pid && !st.voice.pcs.has(m.pid) && pid < m.pid) offerTo(m.pid).catch(() => {}); + } + function syncVoicePeers() { + const voiced = new Set(st.members.filter((m) => m.voice).map((m) => m.pid)); + for (const other of [...st.voice.pcs.keys()]) if (!voiced.has(other)) dropPeer(other); + connectVoicePeers(); + } + async function toggleVoice() { + if (st.voice.on) { + st.voice.on = false; + for (const other of [...st.voice.pcs.keys()]) dropPeer(other); + if (st.voice.stream) st.voice.stream.getTracks().forEach((t) => t.stop()); + st.voice.stream = null; + send({ type: 'voice', on: false }); + render(); + return; + } + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia || typeof RTCPeerConnection === 'undefined') { toast('Voice chat isn’t supported in this browser'); return; } + try { + st.voice.stream = await navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true } }); + } catch (e) { + toast('🎤 Microphone blocked: ' + (e.message || e.name)); + return; + } + st.voice.on = true; + st.voice.muted = false; + send({ type: 'voice', on: true }); + toast('🎤 Voice on — headphones stop the music echoing into your mic', { duration: 5000 }); + render(); + connectVoicePeers(); + } + function toggleMute() { + if (!st.voice.stream) return; + st.voice.muted = !st.voice.muted; + st.voice.stream.getAudioTracks().forEach((t) => { t.enabled = !st.voice.muted; }); + render(); + } + + // ---------- lifecycle ---------- + function start() { + st.role = 'host'; + st.code = ''; st.secret = ''; st.chat = []; st.members = []; + ls.set(HOST_KEY, null); + showPanel(); + setStatus('Starting…'); + connect(); + beginTimers(); + } + function join(code, name) { + code = String(code || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); + if (code.length !== 6) { toast('Party codes have 6 letters/numbers'); return; } + if (name) { st.name = name; ls.set(NAME_KEY, name); } + st.role = 'guest'; + st.code = code; st.detached = false; st.chat = []; st.members = []; + showPanel(); + setStatus('Joining…'); + connect(); + beginTimers(); + } + function beginTimers() { + clearInterval(st.pushTimer); clearInterval(st.driftTimer); + st.pushTimer = setInterval(() => pushState(), 3000); + st.driftTimer = setInterval(() => { if (st.role === 'guest' && st.state && !st.detached) applyState(st.state); }, 2500); + } + function leave(sendEnd = true) { + if (isHost() && sendEnd) send({ type: 'end' }); + if (st.voice.on) toggleVoice(); + const ws = st.ws; + st.ws = null; + st.role = null; st.code = ''; st.secret = ''; + clearTimeout(st.retry); clearInterval(st.pushTimer); clearInterval(st.driftTimer); + try { if (ws) ws.close(); } catch { /* gone */ } + ls.set(HOST_KEY, null); + $('partyPanel').classList.add('hidden'); + render(); + } + + // ---------- UI ---------- + // Lyrics-instead-of-video is a per-device view: each guest chooses it for + // themselves, and the host's playback is untouched (the video keeps playing + // behind the lyrics, so sync and audio carry on). + const lyricsOn = () => !!(Notes.stageLyrics && Notes.stageLyrics.on()); + function renderLyricsToggle() { + const b = document.querySelector('#partyPanel .pt-lyrics'); + if (!b) return; + b.textContent = lyricsOn() ? '📺 Show the video' : '🎤 Lyrics instead of video'; + b.classList.toggle('on', lyricsOn()); + } + function setStatus(t) { const el = $('ptStatus'); if (el) el.textContent = t; } + function sysMsg(text) { st.chat.push({ sys: true, text, at: Date.now() }); renderChat(); } + function link() { return `${location.origin}/?party=${st.code}`; } + function showPanel() { Lazy.load('feature:party-dj').then(render).catch(error=>toast(error.message)); Lazy.load('feature:direct').catch(error=>toast(error.message)); $('partyPanel').classList.remove('hidden'); st.minimized = false; $('partyPanel').classList.remove('min'); render(); } + + function render() { + const panel = $('partyPanel'); + const chip = $('navPartyBtn'); + if (chip) { + const label = chip.querySelector('.nav-label'); + if (label) label.textContent = inParty() ? `Party · ${st.members.length}` : 'Watch party'; + else chip.textContent = inParty() ? `🎉 Party · ${st.members.length}` : '🎉 Watch party'; + } + if (!panel || panel.classList.contains('hidden')) return; + const nameOk = !!myName(); + if (!inParty()) { + panel.querySelector('.pt-body').innerHTML = ` + + ${nameOk ? '' : ''} + +
or join one
+
`; + $('ptTitle').textContent = '🎉 Watch party'; + setStatus(''); + return; + } + $('ptTitle').textContent = `🎉 Party ${st.code || '…'}`; + const s = st.state && st.state.v; + panel.querySelector('.pt-body').innerHTML = ` + ${st.code ? `
${escapeHtml(link())}${navigator.share ? '' : ''}
` : ''} + ${!isHost() && s ? `
▶ ${escapeHtml(s.title)}
` : ''} + ${!isHost() && st.detached ? '' : ''} +
${st.members.map((m) => `${m.host ? '👑 ' : ''}${escapeHtml(m.name)}${m.voice ? ' 🎤' : ''}`).join('')}
+ ${isHost() ? `` : ''} + +
+ + ${st.voice.on ? `` : ''} + ${st.voice.on ? `${st.voice.pcs.size} connected` : ''} +
+
+
+ `; + const dj = document.createElement('div'); panel.querySelector('.pt-body').append(dj); + if (Lazy.loaded('feature:party-dj')) PartyDJ.render(dj, { state: st.dj, host: isHost(), pid, send, search: async q => { const result = await API.search(q); return result.results || result.videos || []; } }); + renderChat(); + } + function renderChat() { + const box = $('ptChat'); + if (!box) return; + box.innerHTML = st.chat.map((c) => c.sys + ? `
${escapeHtml(c.text)}
` + : `
${escapeHtml(c.from)} ${escapeHtml(c.text)}
`).join(''); + box.scrollTop = box.scrollHeight; + } + + function open() { + const panel = $('partyPanel'); + if (typeof closeSidebar === 'function') { try { closeSidebar(); } catch { /* not open */ } } + if (panel.classList.contains('hidden')) showPanel(); + else if (st.minimized) { st.minimized = false; panel.classList.remove('min'); } + else if (!inParty()) panel.classList.add('hidden'); + else { st.minimized = true; panel.classList.add('min'); } + } + + function bindUi() { + const panel = $('partyPanel'); + $('ptMin').addEventListener('click', () => { + if (!inParty()) { panel.classList.add('hidden'); return; } + st.minimized = !st.minimized; + panel.classList.toggle('min', st.minimized); + }); + panel.addEventListener('keydown', (e) => e.stopPropagation()); + panel.addEventListener('click', async (e) => { + const a = e.target.closest('[data-act]'); + if (!a || a.tagName === 'INPUT') return; + const act = a.dataset.act; + const nameIn = panel.querySelector('.pt-name'); + const name = nameIn ? nameIn.value.trim() : ''; + if ((act === 'start' || act === 'join') && !myName() && !name) { toast('Enter your name first'); if (nameIn) nameIn.focus(); return; } + if (name) { st.name = name; ls.set(NAME_KEY, name); } + if (act === 'start') start(); + else if (act === 'join') join(panel.querySelector('.pt-code').value); + else if (act === 'copy') { try { await navigator.clipboard.writeText(link()); toast('Party link copied ✓'); } catch { toast('Copy blocked'); } } + else if (act === 'share') { try { await navigator.share({ title: 'Join my watch party', url: link() }); } catch { /* dismissed */ } } + else if (act === 'resync') resync(); + else if (act === 'voice') toggleVoice(); + else if (act === 'mute') toggleMute(); + else if (act === 'lyrics') { Notes.stageLyrics.set(!lyricsOn()); renderLyricsToggle(); } + else if (act === 'leave') leave(true); + }); + panel.addEventListener('change', (e) => { + if (e.target.dataset.act === 'allow') { st.allowControl = e.target.checked; send({ type: 'settings', allowControl: st.allowControl }); } + }); + panel.addEventListener('submit', (e) => { + e.preventDefault(); + const input = panel.querySelector('.pt-msg'); + const text = input.value.trim(); + if (text) { send({ type: 'chat', text }); input.value = ''; } + }); + // Host: push on every player change; guests: detect their own actions. + ['play', 'pause', 'seeked', 'ratechange', 'loadedmetadata'].forEach((ev) => { + [els.video, els.audio].forEach((el) => el.addEventListener(ev, (e) => { + if (el !== Player.master) return; + if (isHost()) pushState(true); + else if (ev === 'play' || ev === 'pause' || ev === 'seeked') onLocalAction(ev); + })); + }); + } + + function boot() { + bindUi(); + render(); + // Resume hosting after a reload. + try { + const h = JSON.parse(ls.get(HOST_KEY) || 'null'); + if (h && h.code && h.secret) { st.role = 'host'; st.code = h.code; st.secret = h.secret; showPanel(); connect(); beginTimers(); } + } catch { /* none */ } + let code = ''; + try { code = (new URLSearchParams(location.search).get('party') || '').toUpperCase(); } catch { /* no URL */ } + if (code) { + try { const u = new URL(location.href); u.searchParams.delete('party'); history.replaceState(null, '', u.pathname + u.search + u.hash); } catch { /* keep */ } + if (myName()) join(code); + else { showPanel(); const c = $('partyPanel').querySelector('.pt-code'); if (c) c.value = code; toast('Enter your name, then tap Join'); } + } + } + + return { + nextDJ: () => { if (!isHost() || !st.dj.enabled || !st.dj.entries.some(e => e.approved)) return false; if (!st.djPending) { st.djPending = true; send({ type: 'dj', action: 'take' }); } return true; }, + open, boot, guestActive, intercept, renderLyricsToggle, afterLoad: () => pushState(true), + state: () => ({ + role: st.role, code: st.code, detached: st.detached, members: st.members.length, voice: st.voice.on, + peers: st.voice.pcs.size, peerStates: [...st.voice.pcs.values()].map((pc) => pc.connectionState), + remoteAudio: [...st.voice.audios.values()].filter((a) => a.srcObject && a.srcObject.getAudioTracks().some((t) => t.readyState === 'live')).length, + chat: st.chat.length, allowControl: st.allowControl, + }), + _join: join, _start: start, + }; +})(); From 0475a1826c0ab7d0d5584237cbd4d7422e136144 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:44:35 +0800 Subject: [PATCH 36/81] Load sharing and external-player tools on demand --- frontend/app-seams.test.js | 11 ++ frontend/app.js | 221 +------------------------------------ frontend/assets.json | 8 ++ frontend/index.html | 2 +- frontend/share-external.js | 221 +++++++++++++++++++++++++++++++++++++ frontend/sw.js | 1 + perf/seams.mjs | 4 +- 7 files changed, 249 insertions(+), 219 deletions(-) create mode 100644 frontend/share-external.js diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index d7dfc14..6f137c8 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -57,3 +57,14 @@ test('watch-party facade keeps playback decisions synchronous before and after l context.window.YT={Party:{guestActive:()=>true,intercept:action=>action==='next',nextDJ:()=>true}}; for(const method of ['guestActive','intercept','nextDJ'])assert.equal(context.api[method]('next'),true); }); + +test('Share and External stay behind lazy entry proxies',()=>{ + assert.match(app,/const Share = Lazy\.proxy\('feature:share-external'/); + assert.match(app,/const External = Lazy\.proxy\('feature:share-external'/); + const chunk=readFileSync(join(__dirname,'share-external.js'),'utf8'); + const context=require('node:vm').createContext({window:{},navigator:{userAgent:''},location:{origin:'https://fixture.test'},isUploadId:()=>false}); + require('node:vm').runInContext(chunk,context); + assert.equal(typeof context.window.YT.Share.open,'function'); + const text=context.window.YT.External.m3u([{id:'benchmedia01',title:'Fixture'}]); + assert.match(text,/#EXTM3U/);assert.match(text,/benchmedia01/); +}); diff --git a/frontend/app.js b/frontend/app.js index 3706557..a7be822 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -5349,152 +5349,8 @@ async function playVideoAt(v, t = 0) { // ============================================================================ // Timestamp sharing — deep links (/?v=ID&t=SEC) and GIFs of a moment // ============================================================================ -const Share = (() => { - const appLink = (id, t) => `${location.origin}/?v=${encodeURIComponent(id)}${t >= 1 ? `&t=${Math.floor(t)}` : ''}`; - const ytLink = (id, t) => `https://youtu.be/${encodeURIComponent(id)}${t >= 1 ? `?t=${Math.floor(t)}` : ''}`; +const Share = Lazy.proxy('feature:share-external', ['open', 'bootFromUrl'], 'Share'); - async function copy(text, label) { - try { await navigator.clipboard.writeText(text); toast(`${label} copied ✓`); } - catch { toast('Copy blocked — long-press the link to copy it'); } - } - - function open() { - const meta = current && current.meta; - if (!meta || !meta.id || meta.custom) { toast('Play a YouTube video first'); return; } - const t0 = Math.floor(Player.master.currentTime || 0); - const body = document.createElement('div'); - body.className = 'share-moment'; - body.innerHTML = ` - - -
-
- - -
-
-
-
-
- - - - -
-
-
`; - const timeIn = body.querySelector('.sm-time'); - const cur = () => { const v = LyricsCore.parseStamp(timeIn.value); return v === null ? t0 : v; }; - const refresh = () => { - body.querySelector('.sm-app').textContent = appLink(meta.id, cur()); - const yt = body.querySelector('.sm-yt'); - if (yt) yt.textContent = ytLink(meta.id, cur()); - }; - timeIn.addEventListener('input', refresh); - timeIn.addEventListener('keydown', (e) => e.stopPropagation()); - refresh(); - // Soundbite range: the A-B loop when one is set, else the next 20 s. - const bStart = abA !== null ? abA : t0; - const bEnd = abB !== null && abB > bStart ? abB : bStart + 20; - body.querySelector('.sm-b-start').value = LyricsCore.fmtClock(bStart); - body.querySelector('.sm-b-end').value = LyricsCore.fmtClock(bEnd); - body.querySelectorAll('.sm-bite input').forEach((i) => i.addEventListener('keydown', (e) => e.stopPropagation())); - let biteBlob = null; - let gifBlob = null; - body.addEventListener('click', async (e) => { - const act = e.target.closest('[data-act]'); - if (!act) return; - if (act.dataset.act === 'app') copy(appLink(meta.id, cur()), 'App link'); - else if (act.dataset.act === 'yt') copy(ytLink(meta.id, cur()), 'YouTube link'); - else if (act.dataset.act === 'gif') { - const out = body.querySelector('.sm-gif-out'); - out.innerHTML = '
Making the GIF…
'; - act.disabled = true; - try { - const d = body.querySelector('.sm-len').value; - const res = await fetch(`/api/media/${encodeURIComponent(meta.id)}/gif?t=${cur()}&d=${d}&w=480`); - if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } - gifBlob = await res.blob(); - const url = URL.createObjectURL(gifBlob); - const name = `${(meta.title || meta.id).replace(/[^\w\- ]+/g, '').trim().slice(0, 40) || meta.id}-${Math.floor(cur())}s.gif`; - out.innerHTML = `GIF preview -
⤓ Download - ${navigator.canShare && navigator.canShare({ files: [new File([gifBlob], name, { type: 'image/gif' })] }) ? '' : ''}
`; - out.dataset.name = name; - } catch (err) { - out.innerHTML = `
⚠ ${escapeHtml(err.message)}
`; - } finally { - act.disabled = false; - } - } else if (act.dataset.act === 'bite') { - const out = body.querySelector('.sm-bite-out'); - const a = LyricsCore.parseStamp(body.querySelector('.sm-b-start').value); - const b = LyricsCore.parseStamp(body.querySelector('.sm-b-end').value); - const fmt = body.querySelector('.sm-b-fmt').value; - const max = fmt === 'm4r' ? 40 : 60; - if (a === null || b === null || b <= a) { out.innerHTML = '
⚠ Times must look like 1:23, end after start
'; return; } - if (b - a > max) { out.innerHTML = `
⚠ Max ${max} s for ${fmt === 'm4r' ? 'an iPhone ringtone' : 'a soundbite'}
`; return; } - out.innerHTML = '
Cutting the soundbite…
'; - act.disabled = true; - try { - const res = await fetch(`/api/media/${encodeURIComponent(meta.id)}/clip?start=${a}&end=${b}&fmt=${fmt}`); - if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } - biteBlob = await res.blob(); - const url = URL.createObjectURL(biteBlob); - const name = `${(meta.title || meta.id).replace(/[^\w\- ]+/g, '').trim().slice(0, 40) || meta.id}-${Math.floor(a)}s.${fmt}`; - out.dataset.name = name; - out.dataset.type = fmt === 'mp3' ? 'audio/mpeg' : 'audio/mp4'; - out.innerHTML = ` -
⤓ Download - ${navigator.canShare && navigator.canShare({ files: [new File([biteBlob], name, { type: out.dataset.type })] }) ? '' : ''}
- ${fmt === 'm4r' ? '

iPhone: share it to GarageBand (or drag into Finder with the phone connected) to set it as a ringtone.

' : ''}`; - } catch (err) { - out.innerHTML = `
⚠ ${escapeHtml(err.message)}
`; - } finally { - act.disabled = false; - } - } else if (act.dataset.act === 'sharebite' && biteBlob) { - const o = body.querySelector('.sm-bite-out'); - try { await navigator.share({ files: [new File([biteBlob], o.dataset.name, { type: o.dataset.type })], title: meta.title }); } catch { /* dismissed */ } - } else if (act.dataset.act === 'sharegif' && gifBlob) { - const name = body.querySelector('.sm-gif-out').dataset.name; - try { await navigator.share({ files: [new File([gifBlob], name, { type: 'image/gif' })], title: meta.title }); } catch { /* dismissed */ } - } - }); - const actions = [{ label: 'Done', onClick: closeModal }]; - if (navigator.share) { - actions.push({ label: '↗ Share link', primary: true, onClick: async () => { - try { await navigator.share({ title: meta.title, text: `${meta.title} @ ${LyricsCore.fmtClock(cur())}`, url: appLink(meta.id, cur()) }); } catch { /* dismissed */ } - } }); - } else { - actions.push({ label: 'Copy app link', primary: true, onClick: () => copy(appLink(meta.id, cur()), 'App link') }); - } - showModal('🔗 Share this moment', body, actions); - } - - // /?v=&t= — open that video at that moment. - async function bootFromUrl() { - let id = '', t = 0; - try { - const q = new URLSearchParams(location.search); - id = (q.get('v') || '').trim(); - t = Math.max(0, parseFloat(q.get('t')) || 0); - } catch { return; } - if (!isMediaId(id)) return; - try { - const u = new URL(location.href); - u.searchParams.delete('v'); - u.searchParams.delete('t'); - history.replaceState(null, '', u.pathname + u.search + u.hash); - } catch { /* keep */ } - await playVideoAt(data.history.find((x) => x.id === id) || { id, title: '' }, t); - } - - return { open, bootFromUrl }; -})(); // ============================================================================ // Loudness levelling (EBU R128) — every track toward -14 LUFS @@ -6087,78 +5943,8 @@ const Gestures = (() => { * ========================================================================== */ -const External = (() => { - const isAndroid = /Android/i.test(navigator.userAgent); - const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); - const streamUrl = (id) => `${location.origin}${isUploadId(id) ? '/api/uploads/' : '/api/media/'}${encodeURIComponent(id)}`; - async function cached(id) { - if (isUploadId(id)) return true; // uploads are always a single file on the server - try { const j = await (await fetch(`/api/media/${encodeURIComponent(id)}/status`)).json(); return j && j.status === 'ready'; } catch { return false; } - } - const intent = (url, title, pkg) => `intent:${url}#Intent;action=android.intent.action.VIEW;type=video/*;${pkg ? `package=${pkg};` : ''}S.title=${encodeURIComponent(title || '')};end`; - function m3u(items) { - return ['#EXTM3U', ...items.flatMap((v) => [`#EXTINF:${Math.round(v.duration || -1)},${(v.title || v.id).replace(/[\r\n]/g, ' ')}`, streamUrl(v.id)])].join('\n') + '\n'; - } - function download(name, text) { - const a = document.createElement('a'); - a.href = URL.createObjectURL(new Blob([text], { type: 'audio/x-mpegurl' })); - a.download = name; - a.click(); - setTimeout(() => URL.revokeObjectURL(a.href), 2000); - } +const External = Lazy.proxy('feature:share-external', ['open', 'm3u', 'intent'], 'External'); - async function open() { - const meta = current && current.meta; - if (!meta || !meta.id || meta.custom) { toast('Play a YouTube video first'); return; } - const body = document.createElement('div'); - body.className = 'ext-panel'; - body.innerHTML = '
Checking the server copy…
'; - showModal('📺 Open in another player', body, [{ label: 'Close', primary: true, onClick: closeModal }]); - const ok = await cached(meta.id); - if (!ok) { - body.innerHTML = ``; - return; - } - const url = streamUrl(meta.id); - const title = meta.title || meta.id; - const inList = queue.length > 1 && queueIndex >= 0; - body.innerHTML = ` - -
- ${isAndroid ? ` - ▶ VLC - ▶ MX Player - ▶ Open with…` - : isIOS ? ` - ▶ VLC - ▶ Infuse` - : `▶ VLC`} - - ${inList ? '' : ''} -
-

${isAndroid ? 'VLC / MX Player must be installed; “Open with…” shows every video app.' - : isIOS ? 'Needs the VLC (or Infuse) app. The link streams from your server; nothing is downloaded first.' - : 'Desktop VLC may not register vlc:// links — the .m3u file opens in VLC, mpv, IINA or any media player.'}

`; - body.addEventListener('click', async (e) => { - const act = e.target.closest('[data-act]'); - if (!act) return; - if (act.dataset.act === 'copy') { - try { await navigator.clipboard.writeText(url); toast('Stream URL copied ✓'); } catch { toast('Copy blocked'); } - } else if (act.dataset.act === 'm3u') { - download(`${title.replace(/[^\w\- ]+/g, '').trim().slice(0, 50) || meta.id}.m3u`, m3u([meta])); - } else if (act.dataset.act === 'm3u-list') { - act.disabled = true; - const items = queue.slice(Math.max(0, queueIndex)); - const flags = await Promise.all(items.map((v) => (v.custom ? false : cached(v.id)))); - const ready = items.filter((_, i) => flags[i]); - download('ytplayer-queue.m3u', m3u(ready)); - toast(`Playlist with ${ready.length} of ${items.length} songs${ready.length < items.length ? ' (the rest aren’t cached on the server yet)' : ''}`, { duration: 5000 }); - act.disabled = false; - } - }); - } - return { open, m3u, intent }; -})(); // ============================================================================ // 🎉 Watch party — synced playback + chat + voice (server/party.js relays) @@ -9341,7 +9127,7 @@ async function boot() { await Presenter.boot(); if (LowerThird.active()) return; SectionRail.boot(); - Share.bootFromUrl(); + if (isMediaId(new URLSearchParams(location.search).get('v'))) Share.bootFromUrl().catch(error => toast(error.message)); bootViewFromUrl(); bootSearchFromUrl(); if (WEB) bootShareFromUrl(); @@ -9433,6 +9219,7 @@ async function boot() { window.addEventListener('ytp-lazy-error',event=>{ toast(event.detail?.error?.message||'Feature unavailable; try Refresh UI'); checkBuildTag(); }); Lazy.intent($('navPartyBtn'),'feature:party-dj'); Lazy.intent($('navRemoteBtn'),'feature:direct'); Lazy.intent($('remoteChip'),'feature:direct'); Lazy.intent($('eqBtn'),'feature:eq-core'); + Lazy.intent($('shareMomentBtn'),'feature:share-external'); Lazy.intent($('externalBtn'),'feature:share-external'); Lazy.reportLayout?.(); Lazy.warm?.(); if (WEB) { fetch('/api/user/sync', { diff --git a/frontend/assets.json b/frontend/assets.json index ef30f6f..d81c7be 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -340,6 +340,14 @@ "files": [ "/watch-party-client.js" ] + }, + "feature:share-external": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/share-external.js" + ] } } } diff --git a/frontend/index.html b/frontend/index.html index e288275..6230dec 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + diff --git a/frontend/share-external.js b/frontend/share-external.js new file mode 100644 index 0000000..cf52263 --- /dev/null +++ b/frontend/share-external.js @@ -0,0 +1,221 @@ +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).Share = (() => { + const appLink = (id, t) => `${location.origin}/?v=${encodeURIComponent(id)}${t >= 1 ? `&t=${Math.floor(t)}` : ''}`; + const ytLink = (id, t) => `https://youtu.be/${encodeURIComponent(id)}${t >= 1 ? `?t=${Math.floor(t)}` : ''}`; + + async function copy(text, label) { + try { await navigator.clipboard.writeText(text); toast(`${label} copied ✓`); } + catch { toast('Copy blocked — long-press the link to copy it'); } + } + + function open() { + const meta = current && current.meta; + if (!meta || !meta.id || meta.custom) { toast('Play a YouTube video first'); return; } + const t0 = Math.floor(Player.master.currentTime || 0); + const body = document.createElement('div'); + body.className = 'share-moment'; + body.innerHTML = ` + + +
+
+ + +
+
+
+
+
+ + + + +
+
+
`; + const timeIn = body.querySelector('.sm-time'); + const cur = () => { const v = LyricsCore.parseStamp(timeIn.value); return v === null ? t0 : v; }; + const refresh = () => { + body.querySelector('.sm-app').textContent = appLink(meta.id, cur()); + const yt = body.querySelector('.sm-yt'); + if (yt) yt.textContent = ytLink(meta.id, cur()); + }; + timeIn.addEventListener('input', refresh); + timeIn.addEventListener('keydown', (e) => e.stopPropagation()); + refresh(); + // Soundbite range: the A-B loop when one is set, else the next 20 s. + const bStart = abA !== null ? abA : t0; + const bEnd = abB !== null && abB > bStart ? abB : bStart + 20; + body.querySelector('.sm-b-start').value = LyricsCore.fmtClock(bStart); + body.querySelector('.sm-b-end').value = LyricsCore.fmtClock(bEnd); + body.querySelectorAll('.sm-bite input').forEach((i) => i.addEventListener('keydown', (e) => e.stopPropagation())); + let biteBlob = null; + let gifBlob = null; + body.addEventListener('click', async (e) => { + const act = e.target.closest('[data-act]'); + if (!act) return; + if (act.dataset.act === 'app') copy(appLink(meta.id, cur()), 'App link'); + else if (act.dataset.act === 'yt') copy(ytLink(meta.id, cur()), 'YouTube link'); + else if (act.dataset.act === 'gif') { + const out = body.querySelector('.sm-gif-out'); + out.innerHTML = '
Making the GIF…
'; + act.disabled = true; + try { + const d = body.querySelector('.sm-len').value; + const res = await fetch(`/api/media/${encodeURIComponent(meta.id)}/gif?t=${cur()}&d=${d}&w=480`); + if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } + gifBlob = await res.blob(); + const url = URL.createObjectURL(gifBlob); + const name = `${(meta.title || meta.id).replace(/[^\w\- ]+/g, '').trim().slice(0, 40) || meta.id}-${Math.floor(cur())}s.gif`; + out.innerHTML = `GIF preview +
⤓ Download + ${navigator.canShare && navigator.canShare({ files: [new File([gifBlob], name, { type: 'image/gif' })] }) ? '' : ''}
`; + out.dataset.name = name; + } catch (err) { + out.innerHTML = `
⚠ ${escapeHtml(err.message)}
`; + } finally { + act.disabled = false; + } + } else if (act.dataset.act === 'bite') { + const out = body.querySelector('.sm-bite-out'); + const a = LyricsCore.parseStamp(body.querySelector('.sm-b-start').value); + const b = LyricsCore.parseStamp(body.querySelector('.sm-b-end').value); + const fmt = body.querySelector('.sm-b-fmt').value; + const max = fmt === 'm4r' ? 40 : 60; + if (a === null || b === null || b <= a) { out.innerHTML = '
⚠ Times must look like 1:23, end after start
'; return; } + if (b - a > max) { out.innerHTML = `
⚠ Max ${max} s for ${fmt === 'm4r' ? 'an iPhone ringtone' : 'a soundbite'}
`; return; } + out.innerHTML = '
Cutting the soundbite…
'; + act.disabled = true; + try { + const res = await fetch(`/api/media/${encodeURIComponent(meta.id)}/clip?start=${a}&end=${b}&fmt=${fmt}`); + if (!res.ok) { const j = await res.json().catch(() => ({})); throw new Error(j.error || `HTTP ${res.status}`); } + biteBlob = await res.blob(); + const url = URL.createObjectURL(biteBlob); + const name = `${(meta.title || meta.id).replace(/[^\w\- ]+/g, '').trim().slice(0, 40) || meta.id}-${Math.floor(a)}s.${fmt}`; + out.dataset.name = name; + out.dataset.type = fmt === 'mp3' ? 'audio/mpeg' : 'audio/mp4'; + out.innerHTML = ` +
⤓ Download + ${navigator.canShare && navigator.canShare({ files: [new File([biteBlob], name, { type: out.dataset.type })] }) ? '' : ''}
+ ${fmt === 'm4r' ? '

iPhone: share it to GarageBand (or drag into Finder with the phone connected) to set it as a ringtone.

' : ''}`; + } catch (err) { + out.innerHTML = `
⚠ ${escapeHtml(err.message)}
`; + } finally { + act.disabled = false; + } + } else if (act.dataset.act === 'sharebite' && biteBlob) { + const o = body.querySelector('.sm-bite-out'); + try { await navigator.share({ files: [new File([biteBlob], o.dataset.name, { type: o.dataset.type })], title: meta.title }); } catch { /* dismissed */ } + } else if (act.dataset.act === 'sharegif' && gifBlob) { + const name = body.querySelector('.sm-gif-out').dataset.name; + try { await navigator.share({ files: [new File([gifBlob], name, { type: 'image/gif' })], title: meta.title }); } catch { /* dismissed */ } + } + }); + const actions = [{ label: 'Done', onClick: closeModal }]; + if (navigator.share) { + actions.push({ label: '↗ Share link', primary: true, onClick: async () => { + try { await navigator.share({ title: meta.title, text: `${meta.title} @ ${LyricsCore.fmtClock(cur())}`, url: appLink(meta.id, cur()) }); } catch { /* dismissed */ } + } }); + } else { + actions.push({ label: 'Copy app link', primary: true, onClick: () => copy(appLink(meta.id, cur()), 'App link') }); + } + showModal('🔗 Share this moment', body, actions); + } + + // /?v=&t= — open that video at that moment. + async function bootFromUrl() { + let id = '', t = 0; + try { + const q = new URLSearchParams(location.search); + id = (q.get('v') || '').trim(); + t = Math.max(0, parseFloat(q.get('t')) || 0); + } catch { return; } + if (!isMediaId(id)) return; + try { + const u = new URL(location.href); + u.searchParams.delete('v'); + u.searchParams.delete('t'); + history.replaceState(null, '', u.pathname + u.search + u.hash); + } catch { /* keep */ } + await playVideoAt(data.history.find((x) => x.id === id) || { id, title: '' }, t); + } + + return { open, bootFromUrl }; +})(); + +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).External = (() => { + const isAndroid = /Android/i.test(navigator.userAgent); + const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); + const streamUrl = (id) => `${location.origin}${isUploadId(id) ? '/api/uploads/' : '/api/media/'}${encodeURIComponent(id)}`; + async function cached(id) { + if (isUploadId(id)) return true; // uploads are always a single file on the server + try { const j = await (await fetch(`/api/media/${encodeURIComponent(id)}/status`)).json(); return j && j.status === 'ready'; } catch { return false; } + } + const intent = (url, title, pkg) => `intent:${url}#Intent;action=android.intent.action.VIEW;type=video/*;${pkg ? `package=${pkg};` : ''}S.title=${encodeURIComponent(title || '')};end`; + function m3u(items) { + return ['#EXTM3U', ...items.flatMap((v) => [`#EXTINF:${Math.round(v.duration || -1)},${(v.title || v.id).replace(/[\r\n]/g, ' ')}`, streamUrl(v.id)])].join('\n') + '\n'; + } + function download(name, text) { + const a = document.createElement('a'); + a.href = URL.createObjectURL(new Blob([text], { type: 'audio/x-mpegurl' })); + a.download = name; + a.click(); + setTimeout(() => URL.revokeObjectURL(a.href), 2000); + } + + async function open() { + const meta = current && current.meta; + if (!meta || !meta.id || meta.custom) { toast('Play a YouTube video first'); return; } + const body = document.createElement('div'); + body.className = 'ext-panel'; + body.innerHTML = '
Checking the server copy…
'; + showModal('📺 Open in another player', body, [{ label: 'Close', primary: true, onClick: closeModal }]); + const ok = await cached(meta.id); + if (!ok) { + body.innerHTML = ``; + return; + } + const url = streamUrl(meta.id); + const title = meta.title || meta.id; + const inList = queue.length > 1 && queueIndex >= 0; + body.innerHTML = ` + +
+ ${isAndroid ? ` + ▶ VLC + ▶ MX Player + ▶ Open with…` + : isIOS ? ` + ▶ VLC + ▶ Infuse` + : `▶ VLC`} + + ${inList ? '' : ''} +
+

${isAndroid ? 'VLC / MX Player must be installed; “Open with…” shows every video app.' + : isIOS ? 'Needs the VLC (or Infuse) app. The link streams from your server; nothing is downloaded first.' + : 'Desktop VLC may not register vlc:// links — the .m3u file opens in VLC, mpv, IINA or any media player.'}

`; + body.addEventListener('click', async (e) => { + const act = e.target.closest('[data-act]'); + if (!act) return; + if (act.dataset.act === 'copy') { + try { await navigator.clipboard.writeText(url); toast('Stream URL copied ✓'); } catch { toast('Copy blocked'); } + } else if (act.dataset.act === 'm3u') { + download(`${title.replace(/[^\w\- ]+/g, '').trim().slice(0, 50) || meta.id}.m3u`, m3u([meta])); + } else if (act.dataset.act === 'm3u-list') { + act.disabled = true; + const items = queue.slice(Math.max(0, queueIndex)); + const flags = await Promise.all(items.map((v) => (v.custom ? false : cached(v.id)))); + const ready = items.filter((_, i) => flags[i]); + download('ytplayer-queue.m3u', m3u(ready)); + toast(`Playlist with ${ready.length} of ${items.length} songs${ready.length < items.length ? ' (the rest aren’t cached on the server yet)' : ''}`, { duration: 5000 }); + act.disabled = false; + } + }); + } + return { open, m3u, intent }; +})(); diff --git a/frontend/sw.js b/frontend/sw.js index 74c2329..a1a84d2 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -143,6 +143,7 @@ const SHELL = [ '/presenter.js', '/remote-client.js', '/watch-party-client.js', + '/share-external.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', diff --git a/perf/seams.mjs b/perf/seams.mjs index e661828..1413091 100644 --- a/perf/seams.mjs +++ b/perf/seams.mjs @@ -54,7 +54,9 @@ async function run(name){ } if(groups.includes('feature:share-external')) { await page.evaluate(async()=>{current={meta:{id:'benchmedia01',title:'Cached smoke',channel:'Fixture'}};await Share.open();}); - await page.waitForSelector('.share-moment');assert.match(await page.locator('#modal').textContent(),/Cached smoke/); + await page.waitForSelector('.share-moment');assert.match(await page.locator('.sm-app').textContent(),/v=benchmedia01/); + await page.locator('.sm-time').fill('0:30');await page.locator('.sm-time').dispatchEvent('input'); + assert.match(await page.locator('.sm-app').textContent(),/t=30/); const m3u=await page.evaluate(async()=>{await Lazy.load('feature:share-external');return window.YT.External.m3u([{id:'benchmedia01',title:'Cached smoke'}]);});assert.match(m3u,/#EXTM3U/);assert.match(m3u,/benchmedia01/); await page.evaluate(()=>closeModal());checked.push('share'); } From b335f95f45c8461dd3efa042cc02b4dd600c5c38 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:46:40 +0800 Subject: [PATCH 37/81] Load Stats view separately from listening-stat tracking --- frontend/app-seams.test.js | 8 +++ frontend/app.js | 125 +------------------------------------ frontend/assets.json | 11 ++++ frontend/index.html | 2 +- frontend/stats-view.js | 124 ++++++++++++++++++++++++++++++++++++ frontend/sw.js | 1 + perf/seams.mjs | 2 +- 7 files changed, 149 insertions(+), 124 deletions(-) create mode 100644 frontend/stats-view.js diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index 6f137c8..0fa6e57 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -68,3 +68,11 @@ test('Share and External stay behind lazy entry proxies',()=>{ const text=context.window.YT.External.m3u([{id:'benchmedia01',title:'Fixture'}]); assert.match(text,/#EXTM3U/);assert.match(text,/benchmedia01/); }); + +test('listening tracking does not pull in the lazy Stats view',()=>{ + const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); + assert.deepEqual(groups['feature:stats-view'].files,['/stats-view.js']); + assert.deepEqual(groups['feature:stats-view'].dependencies,['feature:stats']); + assert.deepEqual(groups['feature:stats'].files,['/stats-core.js']); + assert.match(app,/Lazy\.proxy\('feature:stats-view', \['render'\], 'StatsView'\)/); +}); diff --git a/frontend/app.js b/frontend/app.js index a7be822..e2a778b 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -5180,130 +5180,11 @@ const StatsTrack = (() => { // ============================================================================ // Stats view // ============================================================================ -async function renderStats() { - try { await Lazy.load('feature:stats'); } catch (error) { toast(error.message); return; } - if (view.type !== 'stats') return; - StatsTrack.flush(); - els.listTitle.textContent = 'Stats'; - resetListHeaderExtras(); - els.listActions.innerHTML = ''; - els.status.classList.add('hidden'); - const c = els.cards; - const S = StatsCore.summarize(data.stats); - if (!S.totalPlays && S.totalSec < 60) { - c.innerHTML = ` -
-
📊
-

No listening stats yet

-

Stats start counting now — a song counts as played after 30 seconds. They sync with your online profile.

-
`; - return; - } - const hrs = (sec) => StatsCore.fmtHours(sec); - const delta = S.thisMonthSec - S.lastMonthSec; - const deltaTxt = S.lastMonthSec || S.thisMonthSec - ? `${delta >= 0 ? '▲ +' : '▼ −'}${(Math.abs(delta) / 3600).toFixed(1)}h vs last month` - : ''; - const maxArtist = Math.max(1, ...S.topArtists.map((a) => a.plays)); - const spark = (vals) => { - const w = 96, h = 26, max = Math.max(1, ...vals); - const pts = vals.map((v, i) => `${(i / (vals.length - 1)) * w},${h - 3 - (v / max) * (h - 6)}`).join(' '); - return ``; - }; - const heatMax = Math.max(1, ...S.heat.flat().map((x) => x.minutes)); - const level = (m) => (m <= 0 ? 0 : Math.min(4, 1 + Math.floor((m / heatMax) * 3.999))); - const fmtDay = (k) => new Date(`${k}T12:00:00`).toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' }); - // Month label over the first week column of each month. - const months = S.heat.map((col, w) => { - const d = new Date(`${col[0].date}T12:00:00`); - const prev = w ? new Date(`${S.heat[w - 1][0].date}T12:00:00`) : null; - return !prev || prev.getMonth() !== d.getMonth() ? d.toLocaleDateString(undefined, { month: 'short' }) : ''; - }); - const playlistsWith = data.playlists.length; - - c.innerHTML = ` -
-
-
-
⏱ Listening this month
-
${hrs(S.thisMonthSec)}
-
${escapeHtml(deltaTxt)}${deltaTxt ? ' · ' : ''}${hrs(S.totalSec)} all time
-
-
-
▶ Track plays
-
${S.totalPlays}
-
${S.songsPlayed} song${S.songsPlayed === 1 ? '' : 's'} · ${playlistsWith} playlist${playlistsWith === 1 ? '' : 's'}
-
-
-
🔥 Practice streak
-
${S.streak.current}-day
-
${S.streak.current ? 'Streak active' : 'Listen 5 min today to start one'} · best ${S.streak.best} day${S.streak.best === 1 ? '' : 's'}
-
-
- -
-
-
🎤 Top artistsplays this month
- ${S.topArtists.length ? S.topArtists.map((a) => ` -
- ${escapeHtml(a.name)} - - ${a.plays} -
`).join('') : '
No plays this month yet.
'} -
-
-
🎵 Top songslast 30 days
- ${S.topSongs.length ? S.topSongs.map((t, i) => ` -
- ${String(i + 1).padStart(2, '0')} - ${escapeHtml(t.title)}${escapeHtml(t.channel)} - ${spark(t.spark)} - ${t.plays} -
`).join('') : '
No plays in the last 30 days.
'} -
-
- -
-
🗓 Listening habitslast 16 weeks${S.peak ? ` · peak day: ${S.peak.day}s (avg ${S.peak.avgHours.toFixed(1)} h)` : ''}
-
-
MonWedFriSun
-
-
${months.map((m) => `${m}`).join('')}
-
${S.heat.map((col) => col.map((x) => x.future - ? '' - : ``).join('')).join('')}
-
-
-
Less${[0, 1, 2, 3, 4].map((l) => ``).join('')}More
-
Show as table - - ${S.heat.flat().filter((x) => !x.future && x.minutes > 0).reverse().map((x) => ``).join('') || ''} -
DayMinutes
${fmtDay(x.date)}${x.minutes}
No listening in this window.
-
-
- -
`; - - // One tooltip for every mark (bars, songs, heat cells). - const root = c.querySelector('.stats'); - const tip = $('statsTip'); - root.addEventListener('pointermove', (e) => { - const el = e.target.closest('[data-tip]'); - if (!el) { tip.classList.add('hidden'); return; } - tip.textContent = el.dataset.tip; - tip.classList.remove('hidden'); - const r = root.getBoundingClientRect(); - const half = tip.offsetWidth / 2 + 4; // keep the whole tip inside the panel - tip.style.left = `${Math.min(r.width - half, Math.max(half, e.clientX - r.left))}px`; - tip.style.top = `${e.clientY - r.top - 14}px`; - }); - root.addEventListener('pointerleave', () => tip.classList.add('hidden')); - root.querySelectorAll('.st-song').forEach((row) => row.addEventListener('click', () => { - const v = data.history.find((x) => x.id === row.dataset.id) || { id: row.dataset.id, title: row.querySelector('b').textContent }; - Player.loadVideo(v); - })); +function renderStats() { + return Lazy.proxy('feature:stats-view', ['render'], 'StatsView').render(); } + // ============================================================================ // Presenter / projector view (/?present=) // ============================================================================ diff --git a/frontend/assets.json b/frontend/assets.json index d81c7be..c8469f1 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -348,6 +348,17 @@ "files": [ "/share-external.js" ] + }, + "feature:stats-view": { + "contract": 1, + "eager": false, + "background": true, + "files": [ + "/stats-view.js" + ], + "dependencies": [ + "feature:stats" + ] } } } diff --git a/frontend/index.html b/frontend/index.html index 6230dec..ead66fd 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + diff --git a/frontend/stats-view.js b/frontend/stats-view.js new file mode 100644 index 0000000..abfffc5 --- /dev/null +++ b/frontend/stats-view.js @@ -0,0 +1,124 @@ +/* Lazy classic chunk; its executing singleton stays pinned until reload. */ +(window.YT ||= {}).StatsView = { render: async function renderStats() { + try { await Lazy.load('feature:stats'); } catch (error) { toast(error.message); return; } + if (view.type !== 'stats') return; + StatsTrack.flush(); + els.listTitle.textContent = 'Stats'; + resetListHeaderExtras(); + els.listActions.innerHTML = ''; + els.status.classList.add('hidden'); + const c = els.cards; + const S = StatsCore.summarize(data.stats); + if (!S.totalPlays && S.totalSec < 60) { + c.innerHTML = ` +
+
📊
+

No listening stats yet

+

Stats start counting now — a song counts as played after 30 seconds. They sync with your online profile.

+
`; + return; + } + const hrs = (sec) => StatsCore.fmtHours(sec); + const delta = S.thisMonthSec - S.lastMonthSec; + const deltaTxt = S.lastMonthSec || S.thisMonthSec + ? `${delta >= 0 ? '▲ +' : '▼ −'}${(Math.abs(delta) / 3600).toFixed(1)}h vs last month` + : ''; + const maxArtist = Math.max(1, ...S.topArtists.map((a) => a.plays)); + const spark = (vals) => { + const w = 96, h = 26, max = Math.max(1, ...vals); + const pts = vals.map((v, i) => `${(i / (vals.length - 1)) * w},${h - 3 - (v / max) * (h - 6)}`).join(' '); + return ``; + }; + const heatMax = Math.max(1, ...S.heat.flat().map((x) => x.minutes)); + const level = (m) => (m <= 0 ? 0 : Math.min(4, 1 + Math.floor((m / heatMax) * 3.999))); + const fmtDay = (k) => new Date(`${k}T12:00:00`).toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' }); + // Month label over the first week column of each month. + const months = S.heat.map((col, w) => { + const d = new Date(`${col[0].date}T12:00:00`); + const prev = w ? new Date(`${S.heat[w - 1][0].date}T12:00:00`) : null; + return !prev || prev.getMonth() !== d.getMonth() ? d.toLocaleDateString(undefined, { month: 'short' }) : ''; + }); + const playlistsWith = data.playlists.length; + + c.innerHTML = ` +
+
+
+
⏱ Listening this month
+
${hrs(S.thisMonthSec)}
+
${escapeHtml(deltaTxt)}${deltaTxt ? ' · ' : ''}${hrs(S.totalSec)} all time
+
+
+
▶ Track plays
+
${S.totalPlays}
+
${S.songsPlayed} song${S.songsPlayed === 1 ? '' : 's'} · ${playlistsWith} playlist${playlistsWith === 1 ? '' : 's'}
+
+
+
🔥 Practice streak
+
${S.streak.current}-day
+
${S.streak.current ? 'Streak active' : 'Listen 5 min today to start one'} · best ${S.streak.best} day${S.streak.best === 1 ? '' : 's'}
+
+
+ +
+
+
🎤 Top artistsplays this month
+ ${S.topArtists.length ? S.topArtists.map((a) => ` +
+ ${escapeHtml(a.name)} + + ${a.plays} +
`).join('') : '
No plays this month yet.
'} +
+
+
🎵 Top songslast 30 days
+ ${S.topSongs.length ? S.topSongs.map((t, i) => ` +
+ ${String(i + 1).padStart(2, '0')} + ${escapeHtml(t.title)}${escapeHtml(t.channel)} + ${spark(t.spark)} + ${t.plays} +
`).join('') : '
No plays in the last 30 days.
'} +
+
+ +
+
🗓 Listening habitslast 16 weeks${S.peak ? ` · peak day: ${S.peak.day}s (avg ${S.peak.avgHours.toFixed(1)} h)` : ''}
+
+
MonWedFriSun
+
+
${months.map((m) => `${m}`).join('')}
+
${S.heat.map((col) => col.map((x) => x.future + ? '' + : ``).join('')).join('')}
+
+
+
Less${[0, 1, 2, 3, 4].map((l) => ``).join('')}More
+
Show as table + + ${S.heat.flat().filter((x) => !x.future && x.minutes > 0).reverse().map((x) => ``).join('') || ''} +
DayMinutes
${fmtDay(x.date)}${x.minutes}
No listening in this window.
+
+
+ +
`; + + // One tooltip for every mark (bars, songs, heat cells). + const root = c.querySelector('.stats'); + const tip = $('statsTip'); + root.addEventListener('pointermove', (e) => { + const el = e.target.closest('[data-tip]'); + if (!el) { tip.classList.add('hidden'); return; } + tip.textContent = el.dataset.tip; + tip.classList.remove('hidden'); + const r = root.getBoundingClientRect(); + const half = tip.offsetWidth / 2 + 4; // keep the whole tip inside the panel + tip.style.left = `${Math.min(r.width - half, Math.max(half, e.clientX - r.left))}px`; + tip.style.top = `${e.clientY - r.top - 14}px`; + }); + root.addEventListener('pointerleave', () => tip.classList.add('hidden')); + root.querySelectorAll('.st-song').forEach((row) => row.addEventListener('click', () => { + const v = data.history.find((x) => x.id === row.dataset.id) || { id: row.dataset.id, title: row.querySelector('b').textContent }; + Player.loadVideo(v); + })); +} }; diff --git a/frontend/sw.js b/frontend/sw.js index a1a84d2..0551c1b 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -144,6 +144,7 @@ const SHELL = [ '/remote-client.js', '/watch-party-client.js', '/share-external.js', + '/stats-view.js', '/app.js', '/manifest.webmanifest', '/icons/icon-192.png', diff --git a/perf/seams.mjs b/perf/seams.mjs index 1413091..58d705b 100644 --- a/perf/seams.mjs +++ b/perf/seams.mjs @@ -61,7 +61,7 @@ async function run(name){ await page.evaluate(()=>closeModal());checked.push('share'); } if(groups.includes('feature:stats-view')) { - await page.evaluate(async()=>{view={type:'stats'};await renderStats();});await page.waitForSelector('.stats-empty');checked.push('stats'); + await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');checked.push('stats'); } assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network'); // Ignore only verified disconnected version/recommendation API transports in WebKit. From 2c5003575c641fddb128c6d1d14bb5d1e3999efb Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 04:48:52 +0800 Subject: [PATCH 38/81] Report unavailable lazy chunks without rejecting UI actions --- frontend/app-seams.test.js | 7 +++++++ frontend/app.js | 8 ++++---- perf/seams.mjs | 4 ++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index 0fa6e57..ced5ccd 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -76,3 +76,10 @@ test('listening tracking does not pull in the lazy Stats view',()=>{ assert.deepEqual(groups['feature:stats'].files,['/stats-core.js']); assert.match(app,/Lazy\.proxy\('feature:stats-view', \['render'\], 'StatsView'\)/); }); + +test('an unavailable Stats chunk reports an error without rejecting the UI navigation',async()=>{ + const source=app.match(/function renderStats\(\) \{[\s\S]*?\n\}/)?.[0];assert.ok(source); + const seen=[],context=require('node:vm').createContext({Lazy:{proxy:()=>({render:()=>Promise.reject(new Error('Unavailable fixture chunk'))})},toast:text=>seen.push(text)}); + require('node:vm').runInContext(source+';globalThis.render=renderStats;',context); + await context.render();assert.deepEqual(seen,['Unavailable fixture chunk']); +}); diff --git a/frontend/app.js b/frontend/app.js index e2a778b..869ed00 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -5181,7 +5181,7 @@ const StatsTrack = (() => { // Stats view // ============================================================================ function renderStats() { - return Lazy.proxy('feature:stats-view', ['render'], 'StatsView').render(); + return Lazy.proxy('feature:stats-view', ['render'], 'StatsView').render().catch(error => toast(error.message)); } @@ -7798,8 +7798,8 @@ document.querySelectorAll('.chip').forEach((c) => { $('sleepCurtain').addEventListener('click', () => $('sleepCurtain').classList.add('hidden')); $('sleepCancelBtn').addEventListener('click', () => { cancelSleepTimer(); toast('Sleep timer cancelled'); }); $('transitionBtn').addEventListener('click', () => Transition.cycle()); - $('shareMomentBtn').addEventListener('click', () => Share.open()); - $('externalBtn').addEventListener('click', () => External.open()); + $('shareMomentBtn').addEventListener('click', () => Share.open().catch(error => toast(error.message))); + $('externalBtn').addEventListener('click', () => External.open().catch(error => toast(error.message))); $('pipBtn').addEventListener('click', () => PiP.toggle()); $('eqBtn').addEventListener('click', () => EQ.open()); @@ -9005,7 +9005,7 @@ async function boot() { syncOnLaunch(); startPlaylistInboxWatch(); if(LowerThird.active()) await Lazy.load('feature:lower-third'); - await Presenter.boot(); + await Presenter.boot().catch(error => toast(error.message)); if (LowerThird.active()) return; SectionRail.boot(); if (isMediaId(new URLSearchParams(location.search).get('v'))) Share.bootFromUrl().catch(error => toast(error.message)); diff --git a/perf/seams.mjs b/perf/seams.mjs index 58d705b..39ff1e0 100644 --- a/perf/seams.mjs +++ b/perf/seams.mjs @@ -63,6 +63,10 @@ async function run(name){ if(groups.includes('feature:stats-view')) { await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');checked.push('stats'); } + if(groups.includes('feature:share-external')) { + await page.evaluate(()=>{Share.open=()=>Promise.reject(new Error('Unavailable fixture chunk'));document.querySelector('#shareMomentBtn').click();}); + await page.getByText('Unavailable fixture chunk',{exact:true}).waitFor(); + } assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network'); // Ignore only verified disconnected version/recommendation API transports in WebKit. const scriptErrors=errors.filter(e=>!(name==='webkit'&&(e==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(e))));assert.deepEqual(scriptErrors,[]); From a7473cbca2c7ace7d34a546c2584fc9b3bf65afb Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 05:03:55 +0800 Subject: [PATCH 39/81] Verify six app seams and record Phase 4 performance measurements --- perf/README.md | 40 + perf/analyze-app.cjs | 7 +- perf/baseline.mjs | 52 +- perf/migration.mjs | 2 +- .../phase4-cold-isolated-2026-10-08.json | 931 ++++++ perf/results/phase4-final-2026-10-08.json | 2619 +++++++++++++++++ .../phase4-hashing-rollback-2026-10-08.json | 133 + perf/results/phase4-lazy-2026-10-08.json | 79 + .../phase4-migration-lossy-2026-10-08.json | 41 + ...ase4-migration-unthrottled-2026-10-08.json | 41 + perf/results/phase4-seams-2026-10-08.json | 28 + .../phase4-sync-rollback-2026-10-08.json | 133 + perf/seams.mjs | 17 +- plans/phase4-seams.md | 33 +- plans/phase4-verification.md | 119 + 15 files changed, 4263 insertions(+), 12 deletions(-) create mode 100644 perf/results/phase4-cold-isolated-2026-10-08.json create mode 100644 perf/results/phase4-final-2026-10-08.json create mode 100644 perf/results/phase4-hashing-rollback-2026-10-08.json create mode 100644 perf/results/phase4-lazy-2026-10-08.json create mode 100644 perf/results/phase4-migration-lossy-2026-10-08.json create mode 100644 perf/results/phase4-migration-unthrottled-2026-10-08.json create mode 100644 perf/results/phase4-seams-2026-10-08.json create mode 100644 perf/results/phase4-sync-rollback-2026-10-08.json create mode 100644 plans/phase4-verification.md diff --git a/perf/README.md b/perf/README.md index 90fbbb7..3fa5b38 100644 --- a/perf/README.md +++ b/perf/README.md @@ -271,3 +271,43 @@ Legacy pages cannot report their selected layout. Their one-time migration block all layouts to preserve immediate offline selection; modern pages block only the reported layout and its shared controls. Executing groups never re-evaluate live. See plans/phase3-staged-apply-decision.md: Phase 4 must add disposal/state handoff. + +## Phase 4 seams and verification + +The dependency inventory in `plans/phase4-seams.md` records Phase 3 declarations, +resolved outside references and byte/coupling rankings. Reproduce its source using +`npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8` +and `node perf/analyze-app.cjs cd4a25a` (development scratch dependencies only). +Shell/shared view/Settings/section-rail definitions remain eager before app.js. +Presenter, Remote client, Watch party, Share/External and Stats view register +classic singletons on `window.YT`; synchronous playback hooks remain facades. +Executing chunks remain pinned: disposal/state handoff is still required before +any live replacement can be enabled. + +```bash +node --test frontend/*.test.js +(cd server && bun install && bun run test) +node perf/hidden-timers.mjs +node perf/seams.mjs --browser all +node perf/lazy.mjs --browser all +node perf/migration.mjs --browser all --profile lossy \ + --out perf/results/phase4-migration-lossy-2026-10-08.json +node perf/migration.mjs --browser all --profile unthrottled \ + --out perf/results/phase4-migration-unthrottled-2026-10-08.json +node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all \ + --out perf/results/phase4-final-2026-10-08.json \ + --compare perf/results/after-phase0-2026-10-07.json +node perf/baseline.mjs --runs 3 --browser chromium --profile lte --scenario cold \ + --out perf/results/phase4-cold-isolated-2026-10-08.json +``` + +`update-feature` appends one comment to presenter.js in scratch, installs the worker, +explicitly activates, then waits for the changed background chunk to be verified +in CacheStorage. It asserts that no other application JS/CSS/font/icon payload +transfers; derived index/manifest and worker script checks are included in totals. +`all` includes this scenario when the source contains presenter.js. Cold records +now include individual long-task timing without changing the aggregate metric, +plus the source frontend build tag. WebKit does not expose the long-task API. +Migration supports `--out` to preserve earlier phase evidence. Existing lazy +harness results are copied to `phase4-lazy-2026-10-08.json` after each Phase 4 run +and the Phase 3 result is restored. No production requests or deploys are needed. diff --git a/perf/analyze-app.cjs b/perf/analyze-app.cjs index 6df26e4..5cb00d7 100644 --- a/perf/analyze-app.cjs +++ b/perf/analyze-app.cjs @@ -1,11 +1,14 @@ const fs=require('fs'), acorn=require('./.tmp/analysis/node_modules/acorn'), scope=require('./.tmp/analysis/node_modules/eslint-scope'); -const src=fs.readFileSync('frontend/app.js','utf8'); +const {execFileSync}=require('node:child_process'); +const commit=process.argv[2]; +const read=file=>commit?execFileSync('git',['show',commit+':'+file],{encoding:'utf8',maxBuffer:2000000}):fs.readFileSync(file,'utf8'); +const src=read('frontend/app.js'); function parse(s){return acorn.parse(s,{ecmaVersion:2024,sourceType:'script',locations:true,ranges:true});} const ast=parse(src), mgr=scope.analyze(ast,{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true}); const vars=mgr.globalScope.variables, names=new Set(vars.map(v=>v.name)); const rows=vars.map(v=>{const decl=v.defs[0].parent||v.defs[0].node;const stmt=ast.body.find(n=>n.start<=decl.start&&n.end>=decl.end);return {name:v.name,start:stmt.start,end:stmt.end,line:stmt.loc.start.line,bytes:Buffer.byteLength(src.slice(stmt.start,stmt.end)),outside:v.references.filter(r=>r.identifier.start=stmt.end).map(r=>r.identifier.loc.start.line),imports:[]};}); for(const row of rows){const deps=new Set();for(const v of vars)if(v.name!==row.name&&v.references.some(r=>r.identifier.start>=row.start&&r.identifier.startf.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(fs.readFileSync('frontend/'+file,'utf8')),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}} +for(const file of (commit?execFileSync('git',['ls-tree','--name-only',commit+':frontend'],{encoding:'utf8'}).trim().split('\n'):fs.readdirSync('frontend')).filter(f=>f.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(read('frontend/'+file)),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}} fs.writeFileSync('perf/.tmp/analysis/declarations.json',JSON.stringify(rows,null,2)); const candidates={shell:['Recommendations','renderSidebar','renderHomePlaylists','updateHomeGridScrollState','updateBottomChrome','setHomeOverPlayer','showMiniBar','updateMiniBar','hideMiniBar','setTile','updateNowPlayingActions','renderSmartSidebar'],presenter:['Presenter'],remote:['Remote'],party:['Party'],share:['Share','External'],stats:['renderStats'],notes:['Notes'],settings:['renderSettings'],service:['ServiceVisual','enterServiceMode','exitServiceMode'],editor:['openVideoEditor'],export:['exportToDevice'],sectionRail:['SectionRail'],gestures:['Gestures']}; const summary=Object.entries(candidates).map(([name,list])=>{const chosen=rows.filter(r=>list.includes(r.name));const coupling=new Set(chosen.flatMap(r=>r.imports).filter(n=>!list.includes(n)));return {name,bytes:chosen.reduce((s,r)=>s+r.bytes,0),coupling:coupling.size,ratio:Math.round(chosen.reduce((s,r)=>s+r.bytes,0)/Math.max(1,coupling.size)),imports:[...coupling],outside:chosen.flatMap(r=>r.outside),list};}).sort((a,b)=>b.ratio-a.ratio);fs.writeFileSync('perf/.tmp/analysis/candidates.json',JSON.stringify(summary,null,2));console.log(summary.map(r=>[r.name,r.bytes,r.coupling,r.ratio].join(' ')).join('\n')); diff --git a/perf/baseline.mjs b/perf/baseline.mjs index f3d4bbf..142febd 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -25,6 +25,8 @@ * --compare Compare results against a previous baseline JSON */ +import assert from 'node:assert/strict'; +import { createHash } from 'node:crypto'; import { spawn, spawnSync, execFileSync } from 'node:child_process'; import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs'; import path from 'node:path'; @@ -244,6 +246,7 @@ async function setupPageMetrics(page) { window.__fcp = null; window.__lcp = null; window.__longTasksTotal = 0; + window.__longTasks = []; // Observe boot completion landmark (#cards view set by renderList()) const markBoot = () => { @@ -263,6 +266,7 @@ async function setupPageMetrics(page) { new PerformanceObserver((list) => { for (const entry of list.getEntries()) { window.__longTasksTotal += entry.duration; + window.__longTasks.push({start:Math.round(entry.startTime),duration:Math.round(entry.duration)}); } }).observe({ type: 'longtask', buffered: true }); } catch {} @@ -374,6 +378,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) { domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, bootDone: window.__bootDone ? Math.round(window.__bootDone) : null, longTaskTotal: Math.round(window.__longTasksTotal || 0), + longTasks: window.__longTasks || [], }; }); @@ -396,6 +401,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) { domContentLoaded: pageMetrics.domContentLoaded, bootDone: pageMetrics.bootDone, longTaskTotal: pageMetrics.longTaskTotal, + longTasks: pageMetrics.longTasks, requests: stats.requests, initialJsCss: pageMetrics.initialJsCss, initialAssetRequests: pageMetrics.initialAssetRequests, @@ -478,6 +484,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, bootDone: window.__bootDone ? Math.round(window.__bootDone) : null, longTaskTotal: Math.round(window.__longTasksTotal || 0), + longTasks: window.__longTasks || [], }; }); @@ -492,6 +499,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { domContentLoaded: pageMetrics.domContentLoaded, bootDone: pageMetrics.bootDone, longTaskTotal: pageMetrics.longTaskTotal, + longTasks: pageMetrics.longTasks, }; } @@ -634,7 +642,7 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi } // Switch server to Tree N+1 (app.js or theme-glass.css modification) - const targetTree = updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss; + const targetTree = updateKind === 'feature' ? trees.treeUpdateFeature : updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss; await server.restartWithPublic(targetTree); // Measure wire bytes and duration from reg.update() until new SW is waiting/installed @@ -654,10 +662,32 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi await sleep(50); } + if (updateKind === 'feature') { + // Readiness excludes background chunks. Include activation and the changed + // feature's actual idle transfer rather than reporting readiness as its cost. + const expected = createHash('sha256').update(readFileSync(path.join(targetTree,'presenter.js'))).digest('hex').slice(0,10); + await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});}); + const end=Date.now()+90000; + while(true) { + const complete=await page.evaluate(async h=>{ + const r=await navigator.serviceWorker.getRegistration(); + if(r.waiting || r.installing)return false; + r.active?.postMessage({type:'WARM_ASSETS',saveData:false}); + const c=await caches.open('ytplayer-assets'),entry=await c.match('/presenter.js?v='+h); + return entry?.headers.get('X-Asset-Hash')===h; + },expected); + if(complete)break; + if(Date.now()>end)throw Error('Changed feature was not cached after activation'); + await sleep(100); + } + } const duration = Date.now() - t0; proxy.stopTracking(); const stats = proxy.getStats(); - + if(updateKind==='feature') { + const assetDownloads=stats.requests.filter(r=>r.bytes>0).map(r=>new URL(r.url,navUrl).pathname).filter(p=>/\.(?:js|css|woff2?|png|svg)$/.test(p)&&!['/sw.js','/asset-sync-core.js'].includes(p)); + assert.deepEqual([...new Set(assetDownloads)],['/presenter.js'],'feature edit transfers only its chunk; no app/core/font/icon payload'); + } await browser.close(); return { @@ -696,6 +726,7 @@ async function main() { const treeBase = path.join(tmpRoot, 'tree-base'); const treeUpdateJs = path.join(tmpRoot, 'tree-update-js'); const treeUpdateCss = path.join(tmpRoot, 'tree-update-css'); + const treeUpdateFeature = path.join(tmpRoot, 'tree-update-feature'); let frontendSource=path.join(REPO_ROOT,'frontend'); if(options.frontendCommit) { @@ -704,14 +735,15 @@ async function main() { execFileSync('tar',['-xf',archive,'-C',tmpRoot]); frontendSource=path.join(tmpRoot,'frontend'); } - for(const tree of [treeBase,treeUpdateJs,treeUpdateCss])cpSync(frontendSource,tree,{recursive:true}); + for(const tree of [treeBase,treeUpdateJs,treeUpdateCss,treeUpdateFeature])cpSync(frontendSource,tree,{recursive:true}); // Append 1 comment line to app.js in treeUpdateJs appendFileSync(path.join(treeUpdateJs, 'app.js'), '\n// baseline bench: 1-line app.js comment\n'); // Append 1 rule to theme-glass.css in treeUpdateCss appendFileSync(path.join(treeUpdateCss, 'theme-glass.css'), '\n/* baseline bench: 1-line css rule */\n.baseline-marker { opacity: 0.99; }\n'); - const trees = { treeBase, treeUpdateJs, treeUpdateCss }; + if(existsSync(path.join(treeUpdateFeature,'presenter.js')))appendFileSync(path.join(treeUpdateFeature,'presenter.js'),'\n// baseline bench: 1-line presenter chunk comment\n'); + const trees = { treeBase, treeUpdateJs, treeUpdateCss, treeUpdateFeature }; const serverScratch = path.join(tmpRoot, 'server-run'); const server = new ServerManager(serverScratch, treeBase); @@ -721,6 +753,7 @@ async function main() { const results = { date: new Date().toISOString(), frontendCommit: options.frontendCommit, + frontendBuildTag: (await (await fetch('http://127.0.0.1:'+server.port+'/api/version')).json()).buildTag, commit: spawnSync('git', ['rev-parse', 'HEAD'], { cwd: REPO_ROOT }).stdout.toString().trim(), runsConfigured: options.runs, browsers: {}, @@ -759,6 +792,7 @@ async function main() { domContentLoaded: summarizeList(coldRuns.map((r) => r.domContentLoaded)), bootDone: summarizeList(coldRuns.map((r) => r.bootDone)), longTaskTotal: summarizeList(coldRuns.map((r) => r.longTaskTotal)), + longTasks: coldRuns.map(r=>r.longTasks), swInstallDuration: summarizeList(coldRuns.map((r) => r.swInstallDuration)), swInstallBytes: summarizeList(coldRuns.map((r) => r.swInstallBytes)), storageEstimate: coldRuns[0]?.storageEstimate || null, @@ -869,6 +903,16 @@ async function main() { }; } + if ((options.scenario === 'all' || options.scenario === 'update-feature') && existsSync(path.join(treeBase,'presenter.js'))) { + console.log(` [Scenario: Update split-out presenter, including idle cache fill] running ${options.runs} iterations...`); + const runs=[]; + for(let r=0;rr.requestCount)),wireBytes:summarizeList(runs.map(r=>r.wireBytes)),duration:summarizeList(runs.map(r=>r.duration)),wireBytesByType:runs[0]?.wireBytesByType||{},requests:runs[0]?.requests||[]}; + } + await proxy.close(); } } diff --git a/perf/migration.mjs b/perf/migration.mjs index 18b2683..dbe97d7 100644 --- a/perf/migration.mjs +++ b/perf/migration.mjs @@ -234,5 +234,5 @@ async function run(name) { try { const results = []; for (const name of browserName === 'all' ? ['chromium', 'webkit'] : [browserName]) results.push(await run(name)); - writeFileSync(join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n'); + writeFileSync(args.includes('--out') ? resolve(args[args.indexOf('--out')+1]) : join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n'); } finally { rmSync(scratch, { recursive: true, force: true }); } diff --git a/perf/results/phase4-cold-isolated-2026-10-08.json b/perf/results/phase4-cold-isolated-2026-10-08.json new file mode 100644 index 0000000..7b39585 --- /dev/null +++ b/perf/results/phase4-cold-isolated-2026-10-08.json @@ -0,0 +1,931 @@ +{ + "date": "2026-10-07T20:55:14.741Z", + "frontendCommit": null, + "frontendBuildTag": "c3dbdd7039db", + "commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb", + "runsConfigured": 3, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 115, + "min": 115, + "max": 115, + "values": [ + 115, + 115, + 115 + ] + }, + "wireBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012, + 651012, + 651012 + ] + }, + "fcp": { + "median": 1352, + "min": 1352, + "max": 1384, + "values": [ + 1384, + 1352, + 1352 + ] + }, + "lcp": { + "median": 1352, + "min": 1352, + "max": 1384, + "values": [ + 1384, + 1352, + 1352 + ] + }, + "domContentLoaded": { + "median": 6992, + "min": 6973, + "max": 7373, + "values": [ + 7373, + 6992, + 6973 + ] + }, + "bootDone": { + "median": 7010, + "min": 6989, + "max": 7389, + "values": [ + 7389, + 7010, + 6989 + ] + }, + "longTaskTotal": { + "median": 275, + "min": 274, + "max": 297, + "values": [ + 297, + 274, + 275 + ] + }, + "longTasks": [ + [ + { + "start": 1232, + "duration": 135 + }, + { + "start": 7216, + "duration": 162 + } + ], + [ + { + "start": 1223, + "duration": 109 + }, + { + "start": 6834, + "duration": 165 + } + ], + [ + { + "start": 1225, + "duration": 111 + }, + { + "start": 6814, + "duration": 164 + } + ] + ], + "swInstallDuration": { + "median": 36619, + "min": 36567, + "max": 36956, + "values": [ + 36956, + 36567, + 36619 + ] + }, + "swInstallBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012, + 651012, + 651012 + ] + }, + "storageEstimate": { + "usage": 2801669, + "quota": 5371510789 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 22882, + "js": 296653, + "css": 65916, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 4604, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:6199/?v=benchmedia01", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6199/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6199/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:6199/views-core.js?v=49be16274c", + "status": 200, + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:6199/app.js?v=f485286cbc", + "status": 200, + "bytes": 95477 + }, + { + "url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6199/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6199/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:6199/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6199/api/manifest", + "status": 200, + "bytes": 3210 + }, + { + "url": "http://127.0.0.1:6199/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1058 + }, + { + "url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:6199/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6199/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:6199/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:6199/index.html?v=b556b50667", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:6199/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:6199/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 3487 + }, + { + "url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6199/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:6199/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6199/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:6199/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:6199/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 1727 + }, + { + "url": "http://127.0.0.1:6199/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:6199/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 3697 + }, + { + "url": "http://127.0.0.1:6199/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:6199/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 875 + }, + { + "url": "http://127.0.0.1:6199/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6199/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:6199/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4158 + }, + { + "url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:6199/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:6199/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:6199/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:6199/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 542 + }, + { + "url": "http://127.0.0.1:6199/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:6199/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:6199/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2048 + }, + { + "url": "http://127.0.0.1:6199/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2431 + }, + { + "url": "http://127.0.0.1:6199/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:6199/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1267 + }, + { + "url": "http://127.0.0.1:6199/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:6199/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 3850 + }, + { + "url": "http://127.0.0.1:6199/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:6199/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:6199/piano.js?v=e82bc30884", + "status": 200, + "bytes": 3453 + }, + { + "url": "http://127.0.0.1:6199/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3094 + }, + { + "url": "http://127.0.0.1:6199/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:6199/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 7926 + }, + { + "url": "http://127.0.0.1:6199/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:6199/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:6199/share-external.js?v=9de67de710", + "status": 200, + "bytes": 3653 + }, + { + "url": "http://127.0.0.1:6199/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:6199/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:6199/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:6199/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2294 + }, + { + "url": "http://127.0.0.1:6199/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:6199/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:6199/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:6199/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:6199/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 6513 + }, + { + "url": "http://127.0.0.1:6199/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5068 + }, + { + "url": "http://127.0.0.1:6199/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:6199/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:6199/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 210419, + "min": 210419, + "max": 210419, + "values": [ + 210419, + 210419, + 210419 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd", + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6199/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b", + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6199/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391", + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f", + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b", + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20", + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859", + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424", + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7", + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad", + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:6199/views-core.js?v=49be16274c", + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc", + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:6199/app.js?v=f485286cbc", + "bytes": 95477 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase4-final-2026-10-08.json b/perf/results/phase4-final-2026-10-08.json new file mode 100644 index 0000000..9d5f7a3 --- /dev/null +++ b/perf/results/phase4-final-2026-10-08.json @@ -0,0 +1,2619 @@ +{ + "date": "2026-10-07T20:46:43.563Z", + "frontendCommit": null, + "commit": "b335f95f45c8461dd3efa042cc02b4dd600c5c38", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 115, + "min": 115, + "max": 115, + "values": [ + 115 + ] + }, + "wireBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012 + ] + }, + "fcp": { + "median": 1492, + "min": 1492, + "max": 1492, + "values": [ + 1492 + ] + }, + "lcp": { + "median": 1492, + "min": 1492, + "max": 1492, + "values": [ + 1492 + ] + }, + "domContentLoaded": { + "median": 7956, + "min": 7956, + "max": 7956, + "values": [ + 7956 + ] + }, + "bootDone": { + "median": 7979, + "min": 7979, + "max": 7979, + "values": [ + 7979 + ] + }, + "longTaskTotal": { + "median": 495, + "min": 495, + "max": 495, + "values": [ + 495 + ] + }, + "swInstallDuration": { + "median": 37715, + "min": 37715, + "max": 37715, + "values": [ + 37715 + ] + }, + "swInstallBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012 + ] + }, + "storageEstimate": { + "usage": 2801669, + "quota": 4297768965 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 22882, + "js": 296653, + "css": 65916, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 4604, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/?v=benchmedia01", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:6189/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6189/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6189/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:6189/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6189/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6189/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6189/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6189/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6189/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6189/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6189/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6189/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6189/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6189/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6189/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6189/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6189/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6189/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6189/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6189/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6189/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6189/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6189/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6189/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6189/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6189/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6189/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6189/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6189/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6189/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6189/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6189/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6189/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6189/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6189/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6189/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6189/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6189/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6189/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:6189/views-core.js?v=49be16274c", + "status": 200, + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:6189/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=f485286cbc", + "status": 200, + "bytes": 95477 + }, + { + "url": "http://127.0.0.1:6189/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:6189/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3210 + }, + { + "url": "http://127.0.0.1:6189/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1058 + }, + { + "url": "http://127.0.0.1:6189/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6189/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:6189/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:6189/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:6189/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6189/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:6189/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:6189/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=b556b50667", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:6189/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:6189/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 3487 + }, + { + "url": "http://127.0.0.1:6189/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:6189/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:6189/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 1727 + }, + { + "url": "http://127.0.0.1:6189/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:6189/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 3697 + }, + { + "url": "http://127.0.0.1:6189/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:6189/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6189/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:6189/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:6189/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 875 + }, + { + "url": "http://127.0.0.1:6189/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:6189/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:6189/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4158 + }, + { + "url": "http://127.0.0.1:6189/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:6189/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:6189/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:6189/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 542 + }, + { + "url": "http://127.0.0.1:6189/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:6189/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2048 + }, + { + "url": "http://127.0.0.1:6189/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:6189/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 3850 + }, + { + "url": "http://127.0.0.1:6189/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:6189/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1267 + }, + { + "url": "http://127.0.0.1:6189/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:6189/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:6189/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2431 + }, + { + "url": "http://127.0.0.1:6189/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:6189/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 7926 + }, + { + "url": "http://127.0.0.1:6189/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3094 + }, + { + "url": "http://127.0.0.1:6189/share-external.js?v=9de67de710", + "status": 200, + "bytes": 3653 + }, + { + "url": "http://127.0.0.1:6189/piano.js?v=e82bc30884", + "status": 200, + "bytes": 3453 + }, + { + "url": "http://127.0.0.1:6189/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:6189/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2294 + }, + { + "url": "http://127.0.0.1:6189/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:6189/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:6189/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:6189/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:6189/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5068 + }, + { + "url": "http://127.0.0.1:6189/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:6189/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:6189/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:6189/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:6189/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 6513 + }, + { + "url": "http://127.0.0.1:6189/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:6189/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:6189/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 210419, + "min": 210419, + "max": 210419, + "values": [ + 210419 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:6189/lazy.js?v=99caff8ebd", + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:6189/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:6189/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:6189/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:6189/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:6189/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:6189/layout-base.css?v=4f3307cd3b", + "bytes": 278 + }, + { + "url": "http://127.0.0.1:6189/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:6189/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:6189/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:6189/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:6189/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:6189/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:6189/opfs.js?v=df7a8d0391", + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:6189/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:6189/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:6189/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:6189/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:6189/sha256.js?v=cd9b980e6f", + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:6189/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:6189/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:6189/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:6189/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:6189/sw-update.js?v=772c123c20", + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:6189/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:6189/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.js?v=1101425859", + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:6189/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:6189/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:6189/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:6189/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:6189/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:6189/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:6189/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:6189/prewarm-next.js?v=ed16a51424", + "bytes": 567 + }, + { + "url": "http://127.0.0.1:6189/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 722 + }, + { + "url": "http://127.0.0.1:6189/feature-bootstrap.js?v=33779ecef7", + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:6189/shell-core.js?v=a04305c2ad", + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:6189/views-core.js?v=49be16274c", + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:6189/section-rail.js?v=07417c1bcc", + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=f485286cbc", + "bytes": 95477 + } + ] + }, + "warm": { + "requestCount": { + "median": 46, + "min": 46, + "max": 46, + "values": [ + 46 + ] + }, + "wireBytes": { + "median": 188906, + "min": 188906, + "max": 188906, + "values": [ + 188906 + ] + }, + "fcp": { + "median": 128, + "min": 128, + "max": 128, + "values": [ + 128 + ] + }, + "lcp": { + "median": 172, + "min": 172, + "max": 172, + "values": [ + 172 + ] + }, + "domContentLoaded": { + "median": 452, + "min": 452, + "max": 452, + "values": [ + 452 + ] + }, + "bootDone": { + "median": 467, + "min": 467, + "max": 467, + "values": [ + 467 + ] + }, + "longTaskTotal": { + "median": 56, + "min": 56, + "max": 56, + "values": [ + 56 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 60, + "min": 60, + "max": 60, + "values": [ + 60 + ] + }, + "lcp": { + "median": 60, + "min": 60, + "max": 60, + "values": [ + 60 + ] + }, + "domContentLoaded": { + "median": 179, + "min": 179, + "max": 179, + "values": [ + 179 + ] + }, + "bootDone": { + "median": 180, + "min": 180, + "max": 180, + "values": [ + 180 + ] + }, + "reloadDuration": { + "median": 200, + "min": 200, + "max": 200, + "values": [ + 200 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8 + ] + }, + "wireBytes": { + "median": 125795, + "min": 125795, + "max": 125795, + "values": [ + 125795 + ] + }, + "duration": { + "median": 771, + "min": 771, + "max": 771, + "values": [ + 771 + ] + }, + "wireBytesByType": { + "html": 11463, + "js": 111047, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3285, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3223 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=56a28ab207", + "status": 200, + "bytes": 95503 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 11463 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + }, + "updateCss": { + "requestCount": { + "median": 7, + "min": 7, + "max": 7, + "values": [ + 7 + ] + }, + "wireBytes": { + "median": 30263, + "min": 30263, + "max": 30263, + "values": [ + 30263 + ] + }, + "duration": { + "median": 220, + "min": 220, + "max": 220, + "values": [ + 220 + ] + }, + "wireBytesByType": { + "html": 11439, + "js": 15540, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3284, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3222 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=997252e5f7", + "status": 200, + "bytes": 11439 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8 + ] + }, + "wireBytes": { + "median": 33408, + "min": 33408, + "max": 33408, + "values": [ + 33408 + ] + }, + "duration": { + "median": 1376, + "min": 1376, + "max": 1376, + "values": [ + 1376 + ] + }, + "wireBytesByType": { + "html": 11456, + "js": 18662, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3290, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3228 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 11456 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:6189/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3118 + } + ] + } + } + }, + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159 + ] + }, + "wireBytes": { + "median": 1097048, + "min": 1097048, + "max": 1097048, + "values": [ + 1097048 + ] + }, + "fcp": { + "median": 2401, + "min": 2401, + "max": 2401, + "values": [ + 2401 + ] + }, + "lcp": { + "median": 2477, + "min": 2477, + "max": 2477, + "values": [ + 2477 + ] + }, + "domContentLoaded": { + "median": 2966, + "min": 2966, + "max": 2966, + "values": [ + 2966 + ] + }, + "bootDone": { + "median": 2977, + "min": 2977, + "max": 2977, + "values": [ + 2977 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "swInstallDuration": { + "median": 32605, + "min": 32605, + "max": 32605, + "values": [ + 32605 + ] + }, + "swInstallBytes": { + "median": 1097048, + "min": 1097048, + "max": 1097048, + "values": [ + 1097048 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28064, + "js": 556746, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5082, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/?v=benchmedia01", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:6189/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6189/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6189/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:6189/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6189/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6189/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6189/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6189/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6189/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6189/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6189/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6189/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6189/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6189/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6189/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6189/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6189/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6189/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6189/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6189/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6189/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6189/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6189/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6189/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6189/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6189/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6189/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6189/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6189/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6189/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6189/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6189/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6189/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6189/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6189/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6189/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6189/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:6189/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:6189/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:6189/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:6189/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:6189/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:6189/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220 + }, + { + "url": "http://127.0.0.1:6189/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6189/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6189/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6189/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6189/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6189/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6189/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6189/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6189/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6189/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6189/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6189/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6189/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:6189/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:6189/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:6189/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:6189/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:6189/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:6189/fonts/fonts.css", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6189/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:6189/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:6189/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6189/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:6189/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6189/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6189/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6189/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6189/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:6189/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6189/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042 + }, + { + "url": "http://127.0.0.1:6189/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6189/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6189/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6189/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6189/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6189/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6189/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915 + }, + { + "url": "http://127.0.0.1:6189/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6189/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6189/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:6189/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6189/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6189/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6189/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6189/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:6189/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6189/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6189/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:6189/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:6189/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:6189/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:6189/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080 + }, + { + "url": "http://127.0.0.1:6189/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:6189/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252 + }, + { + "url": "http://127.0.0.1:6189/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:6189/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216 + }, + { + "url": "http://127.0.0.1:6189/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:6189/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071 + }, + { + "url": "http://127.0.0.1:6189/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:6189/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763 + }, + { + "url": "http://127.0.0.1:6189/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:6189/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:6189/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:6189/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:6189/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624 + }, + { + "url": "http://127.0.0.1:6189/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:6189/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:6189/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474 + }, + { + "url": "http://127.0.0.1:6189/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:6189/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444 + }, + { + "url": "http://127.0.0.1:6189/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:6189/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475 + }, + { + "url": "http://127.0.0.1:6189/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773 + }, + { + "url": "http://127.0.0.1:6189/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:6189/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:6189/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:6189/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003 + }, + { + "url": "http://127.0.0.1:6189/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + }, + { + "url": "http://127.0.0.1:6189/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042 + }, + { + "url": "http://127.0.0.1:6189/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:6189/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222 + }, + { + "url": "http://127.0.0.1:6189/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:6189/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664 + }, + { + "url": "http://127.0.0.1:6189/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:6189/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:6189/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:6189/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:6189/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903 + }, + { + "url": "http://127.0.0.1:6189/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829 + }, + { + "url": "http://127.0.0.1:6189/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:6189/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:6189/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:6189/fonts/fonts.css?v=dda3dfb804", + "bytes": 457 + }, + { + "url": "http://127.0.0.1:6189/lazy.js?v=99caff8ebd", + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:6189/service-ui.css?v=b9bf96a3a8", + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:6189/layout-base.css?v=4f3307cd3b", + "bytes": 336 + }, + { + "url": "http://127.0.0.1:6189/recommendations.css?v=055101368d", + "bytes": 983 + }, + { + "url": "http://127.0.0.1:6189/refresh.css?v=62498384f1", + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:6189/styles.css?v=9f3a5dea41", + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.css?v=055507ab85", + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:6189/offline-pages.css?v=2889456261", + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:6189/saved-page.css?v=3ff576a784", + "bytes": 673 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:6189/related-videos.css?v=5a616b1be8", + "bytes": 517 + }, + { + "url": "http://127.0.0.1:6189/download-actions.css?v=12d3bcfe3e", + "bytes": 560 + }, + { + "url": "http://127.0.0.1:6189/fingerprint.js?v=a635143269", + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:6189/opfs.js?v=df7a8d0391", + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:6189/lyrics-display.js?v=48e8550175", + "bytes": 750 + }, + { + "url": "http://127.0.0.1:6189/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:6189/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:6189/sha256-wasm.js?v=393c50ba56", + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:6189/sha256.js?v=cd9b980e6f", + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:6189/loudness-wasm.js?v=c6102d7844", + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:6189/loudness.js?v=01b3da88dd", + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:6189/device-db.js?v=880c5cd70e", + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:6189/async-guard.js?v=e4afa1f2be", + "bytes": 887 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/sw-update.js?v=772c123c20", + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:6189/related-videos.js?v=3eec0ebd4c", + "bytes": 642 + }, + { + "url": "http://127.0.0.1:6189/audio-continuity.js?v=63b5464dd5", + "bytes": 677 + }, + { + "url": "http://127.0.0.1:6189/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:6189/settings-sections.js?v=1101425859", + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:6189/download-actions.js?v=388c7edecb", + "bytes": 669 + }, + { + "url": "http://127.0.0.1:6189/download-errors.js?v=bb6a4c887a", + "bytes": 959 + }, + { + "url": "http://127.0.0.1:6189/downloads.js?v=f2d3e7d212", + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:6189/saved-page.js?v=f1518c50fb", + "bytes": 820 + }, + { + "url": "http://127.0.0.1:6189/downloads-page.js?v=c1a3a218c0", + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:6189/server-backfill.js?v=294b103023", + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:6189/visible-timer.js?v=5322e86ef4", + "bytes": 474 + }, + { + "url": "http://127.0.0.1:6189/prewarm-next.js?v=ed16a51424", + "bytes": 665 + }, + { + "url": "http://127.0.0.1:6189/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832 + }, + { + "url": "http://127.0.0.1:6189/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:6189/shell-core.js?v=a04305c2ad", + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:6189/section-rail.js?v=07417c1bcc", + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:6189/views-core.js?v=49be16274c", + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=f485286cbc", + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:6189/theme-classic.css?v=d420fcfb12", + "bytes": 4079 + } + ] + }, + "warm": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 90, + "min": 90, + "max": 90, + "values": [ + 90 + ] + }, + "lcp": { + "median": 130, + "min": 130, + "max": 130, + "values": [ + 130 + ] + }, + "domContentLoaded": { + "median": 128, + "min": 128, + "max": 128, + "values": [ + 128 + ] + }, + "bootDone": { + "median": 132, + "min": 132, + "max": 132, + "values": [ + 132 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 55, + "min": 55, + "max": 55, + "values": [ + 55 + ] + }, + "lcp": { + "median": 86, + "min": 86, + "max": 86, + "values": [ + 86 + ] + }, + "domContentLoaded": { + "median": 85, + "min": 85, + "max": 85, + "values": [ + 85 + ] + }, + "bootDone": { + "median": 90, + "min": 90, + "max": 90, + "values": [ + 90 + ] + }, + "reloadDuration": { + "median": 105, + "min": 105, + "max": 105, + "values": [ + 105 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5 + ] + }, + "wireBytes": { + "median": 147259, + "min": 147259, + "max": 147259, + "values": [ + 147259 + ] + }, + "duration": { + "median": 1938, + "min": 1938, + "max": 1938, + "values": [ + 1938 + ] + }, + "wireBytesByType": { + "html": 14033, + "js": 129488, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3738, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8990 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:6189/app.js?v=56a28ab207", + "status": 200, + "bytes": 118544 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 14033 + } + ] + }, + "updateCss": { + "requestCount": { + "median": 4, + "min": 4, + "max": 4, + "values": [ + 4 + ] + }, + "wireBytes": { + "median": 28713, + "min": 28713, + "max": 28713, + "values": [ + 28713 + ] + }, + "duration": { + "median": 934, + "min": 934, + "max": 934, + "values": [ + 934 + ] + }, + "wireBytesByType": { + "html": 14030, + "js": 10945, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3738, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=997252e5f7", + "status": 200, + "bytes": 14030 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 7, + "min": 7, + "max": 7, + "values": [ + 7 + ] + }, + "wireBytes": { + "median": 41364, + "min": 41364, + "max": 41364, + "values": [ + 41364 + ] + }, + "duration": { + "median": 1358, + "min": 1358, + "max": 1358, + "values": [ + 1358 + ] + }, + "wireBytesByType": { + "html": 14032, + "js": 23529, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3803, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:6189/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:6189/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:6189/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:6189/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:6189/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:6189/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase4-hashing-rollback-2026-10-08.json b/perf/results/phase4-hashing-rollback-2026-10-08.json new file mode 100644 index 0000000..410fbf2 --- /dev/null +++ b/perf/results/phase4-hashing-rollback-2026-10-08.json @@ -0,0 +1,133 @@ +{ + "date": "2026-10-07T21:00:01.096Z", + "frontendCommit": null, + "frontendBuildTag": "1146a2a9ceca", + "commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 48, + "min": 48, + "max": 48, + "values": [ + 48 + ] + }, + "lcp": { + "median": 48, + "min": 48, + "max": 48, + "values": [ + 48 + ] + }, + "domContentLoaded": { + "median": 152, + "min": 152, + "max": 152, + "values": [ + 152 + ] + }, + "bootDone": { + "median": 156, + "min": 156, + "max": 156, + "values": [ + 156 + ] + }, + "reloadDuration": { + "median": 173, + "min": 173, + "max": 173, + "values": [ + 173 + ] + } + } + } + }, + "webkit": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 53, + "min": 53, + "max": 53, + "values": [ + 53 + ] + }, + "lcp": { + "median": 81, + "min": 81, + "max": 81, + "values": [ + 81 + ] + }, + "domContentLoaded": { + "median": 80, + "min": 80, + "max": 80, + "values": [ + 80 + ] + }, + "bootDone": { + "median": 83, + "min": 83, + "max": 83, + "values": [ + 83 + ] + }, + "reloadDuration": { + "median": 100, + "min": 100, + "max": 100, + "values": [ + 100 + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase4-lazy-2026-10-08.json b/perf/results/phase4-lazy-2026-10-08.json new file mode 100644 index 0000000..c0c9175 --- /dev/null +++ b/perf/results/phase4-lazy-2026-10-08.json @@ -0,0 +1,79 @@ +{ + "results": [ + { + "browser": "chromium", + "sourceBuildTag": "09d1ee0f9c80", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [] + }, + { + "browser": "webkit", + "sourceBuildTag": "09d1ee0f9c80", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [ + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38295/api/version.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38295/api/recommendations?fp=163577c02a53bc40.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:38295/api/version.", + "disconnected": true + } + ] + } + ] +} diff --git a/perf/results/phase4-migration-lossy-2026-10-08.json b/perf/results/phase4-migration-lossy-2026-10-08.json new file mode 100644 index 0000000..1630e62 --- /dev/null +++ b/perf/results/phase4-migration-lossy-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 25699, + "wireBytes": 628797, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 23376, + "wireBytes": 737972, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase4-migration-unthrottled-2026-10-08.json b/perf/results/phase4-migration-unthrottled-2026-10-08.json new file mode 100644 index 0000000..f2b254b --- /dev/null +++ b/perf/results/phase4-migration-unthrottled-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 9805, + "wireBytes": 646234, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 9554, + "wireBytes": 751943, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase4-seams-2026-10-08.json b/perf/results/phase4-seams-2026-10-08.json new file mode 100644 index 0000000..b0b5348 --- /dev/null +++ b/perf/results/phase4-seams-2026-10-08.json @@ -0,0 +1,28 @@ +[ + { + "browser": "chromium", + "checked": [ + "shell", + "presenter", + "remote", + "party", + "share", + "stats" + ], + "offlineNetworkRequests": 0, + "errors": [] + }, + { + "browser": "webkit", + "checked": [ + "shell", + "presenter", + "remote", + "party", + "share", + "stats" + ], + "offlineNetworkRequests": 0, + "errors": [] + } +] diff --git a/perf/results/phase4-sync-rollback-2026-10-08.json b/perf/results/phase4-sync-rollback-2026-10-08.json new file mode 100644 index 0000000..595ee65 --- /dev/null +++ b/perf/results/phase4-sync-rollback-2026-10-08.json @@ -0,0 +1,133 @@ +{ + "date": "2026-10-07T20:58:10.947Z", + "frontendCommit": null, + "frontendBuildTag": "9b741452f44e", + "commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 40, + "min": 40, + "max": 40, + "values": [ + 40 + ] + }, + "lcp": { + "median": 40, + "min": 40, + "max": 40, + "values": [ + 40 + ] + }, + "domContentLoaded": { + "median": 136, + "min": 136, + "max": 136, + "values": [ + 136 + ] + }, + "bootDone": { + "median": 137, + "min": 137, + "max": 137, + "values": [ + 137 + ] + }, + "reloadDuration": { + "median": 154, + "min": 154, + "max": 154, + "values": [ + 154 + ] + } + } + } + }, + "webkit": { + "lte": { + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 60, + "min": 60, + "max": 60, + "values": [ + 60 + ] + }, + "lcp": { + "median": 96, + "min": 96, + "max": 96, + "values": [ + 96 + ] + }, + "domContentLoaded": { + "median": 94, + "min": 94, + "max": 94, + "values": [ + 94 + ] + }, + "bootDone": { + "median": 98, + "min": 98, + "max": 98, + "values": [ + 98 + ] + }, + "reloadDuration": { + "median": 115, + "min": 115, + "max": 115, + "values": [ + 115 + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/perf/seams.mjs b/perf/seams.mjs index 39ff1e0..40c91be 100644 --- a/perf/seams.mjs +++ b/perf/seams.mjs @@ -23,7 +23,7 @@ async function run(name){ browser=await ({chromium,webkit}[name]).launch({headless:true});const context=await browser.newContext(); await context.route('**/*',r=>r.request().url().startsWith(origin)?r.continue():r.abort()); await context.addInitScript(()=>{Object.defineProperty(navigator,'onLine',{configurable:true,get:()=>!window.__offline});}); - const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message)); + const page=await context.newPage(),errors=[],failedRequests=[];page.on('pageerror',e=>errors.push(e.message));page.on('requestfailed',r=>failedRequests.push(r.url())); await page.goto(origin);await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn')); await wait(page,async()=>!!(await navigator.serviceWorker.getRegistration())?.active); await page.evaluate(()=>Lazy.warm()); @@ -39,14 +39,18 @@ async function run(name){ const checked=['shell']; if(groups.includes('feature:presenter')) { await page.evaluate(async()=>{history.replaceState(null,'','/?present=');await Presenter.boot();}); - await page.waitForSelector('#presenterView:not(.hidden)');await page.keyboard.press('b'); + await page.waitForSelector('#presenterView:not(.hidden)'); + await page.locator('#pvCode').fill('x');await page.locator('#pvPairBtn').click();assert.match(await page.locator('#pvMsg').textContent(),/6-digit/); + await page.evaluate(()=>document.activeElement?.blur());await page.keyboard.press('b'); assert.equal(await page.locator('#pvBlank').evaluate(n=>!n.classList.contains('hidden')),true); await page.evaluate(()=>{document.querySelector('#presenterView').classList.add('hidden');document.body.classList.remove('presenter-open');});checked.push('presenter'); } if(groups.includes('feature:remote-client')) { await page.evaluate(()=>document.querySelector('#navRemoteBtn').click()); await page.waitForSelector('#modal:not(.hidden)');assert.match(await page.locator('#modal').textContent(),/remote|screen|phone/i); - await page.evaluate(()=>closeModal());checked.push('remote'); + await page.getByRole('button',{name:'Use this phone as a remote',exact:true}).click(); + await page.waitForSelector('#remoteView:not(.hidden)');await page.locator('#rvCode').fill('x');await page.locator('#rvPairBtn').click(); + assert.match(await page.locator('#rvPairMsg').textContent(),/6-digit/);await page.locator('#rvClose').click();checked.push('remote'); } if(groups.includes('feature:watch-party')) { await page.evaluate(()=>document.querySelector('#navPartyBtn').click());await page.waitForSelector('#partyPanel:not(.hidden)'); @@ -58,10 +62,14 @@ async function run(name){ await page.locator('.sm-time').fill('0:30');await page.locator('.sm-time').dispatchEvent('input'); assert.match(await page.locator('.sm-app').textContent(),/t=30/); const m3u=await page.evaluate(async()=>{await Lazy.load('feature:share-external');return window.YT.External.m3u([{id:'benchmedia01',title:'Cached smoke'}]);});assert.match(m3u,/#EXTM3U/);assert.match(m3u,/benchmedia01/); + await page.evaluate(async()=>{closeModal();current={meta:{id:'upl_0123456789ab',title:'Cached upload'}};await External.open();}); + await page.waitForSelector('.ext-panel');assert.match(await page.locator('.ext-panel').textContent(),/api\/uploads\/upl_0123456789ab/); await page.evaluate(()=>closeModal());checked.push('share'); } if(groups.includes('feature:stats-view')) { - await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');checked.push('stats'); + await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty'); + await page.evaluate(async()=>{data.stats=StatsCore.record(null,{id:'benchmedia01',title:'Cached stats',channel:'Fixture'},600,true);await renderStats();}); + await page.waitForSelector('.stats .st-tiles');assert.match(await page.locator('.st-song-text').first().textContent(),/Cached stats/);checked.push('stats'); } if(groups.includes('feature:share-external')) { await page.evaluate(()=>{Share.open=()=>Promise.reject(new Error('Unavailable fixture chunk'));document.querySelector('#shareMomentBtn').click();}); @@ -70,6 +78,7 @@ async function run(name){ assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network'); // Ignore only verified disconnected version/recommendation API transports in WebKit. const scriptErrors=errors.filter(e=>!(name==='webkit'&&(e==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(e))));assert.deepEqual(scriptErrors,[]); + if(errors.length>scriptErrors.length)assert.ok(failedRequests.some(url=>/\/api\/(?:recommendations|version)/.test(url)),'ignored WebKit transport errors require a recorded disconnected API request'); results.push({browser:name,checked,offlineNetworkRequests:proxy.getStats().requestCount-before,errors:scriptErrors});console.log(name,JSON.stringify(results.at(-1))); }finally{await browser?.close();await stop();await proxy?.close();} } diff --git a/plans/phase4-seams.md b/plans/phase4-seams.md index a256383..7c12b99 100644 --- a/plans/phase4-seams.md +++ b/plans/phase4-seams.md @@ -2,7 +2,7 @@ Source: `cd4a25a`, 587,029 bytes. Acorn 8 parses classic scripts with source ranges; eslint-scope 8 resolves lexical references, including shadowing. Outside references are references outside the declaration’s owning top-level statement, plus unresolved references from other frontend classic scripts. Property names and strings are not lexical references. Browser globals and other scripts’ globals remain available. Positions below refer to this source, before extraction. -Reproduce: `npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`, then run `node perf/analyze-app.cjs`. Analysis tools are development-only; no frontend/server import is added. +Reproduce: `npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`, then run `node perf/analyze-app.cjs cd4a25a`. Analysis tools are development-only; no frontend/server import is added. ## Measured candidate ranking @@ -414,3 +414,34 @@ Outside references use app line numbers or `file:line`; imports name other app b | bootViewFromUrl | 12531 | 391 | view, render, URL_VIEWS | 12625 | | bootSearchFromUrl | 12545 | 414 | els | 12626 | | boot | 12563 | 11475 | WEB, APP_VERSION, perfMark, perfMeasure, webFetch, SaveQueue, API, DEFAULT_SETTINGS, data, view, current, abA, abB, cachedIds, downloading, $, els, persist, ProfileSecret, profileHeaders, syncOnLaunch, updateProfileStatus, adoptSharedPlaylistFromUrl, startPlaylistInboxWatch, adoptProfileFromUrl, syncMuteIcon, toast, uid, applyAppearance, refreshCachedIds, startCacheResyncWatch, warmOfflineThumbs, preload, preloadPlaylist, preloadPinnedPlaylists, Player, wirePlayerEvents, updatePlayBtn, Notes, Remote, Transition, CatalogSync, Recommendations, Presenter, Share, EqRender, PiP, EQ, SectionRail, Party, updateBottomChrome, updateQueueBadge, playNext, updateLoopRepeatButtons, playPrev, isServiceModeOpen, renderSidebar, exportToDevice, render, slim, wireShortcutHelp, showModal, closeModal, setupClassicLayout, setupPortraitPwaWatcher, setupViewportAnchorGuard, wireUI, setAbA, setAbB, clearAb, saveAbMarkers, updateAbUI, renderSmartSidebar, checkAutoBackup, checkBuildTag, pollBuildTag, checkUpdateOutcome, registerServiceWorker, bootShareFromUrl, bootViewFromUrl, bootSearchFromUrl | 12734 | + +## Final cuts and review + +Exactly six seams shipped: 3c9a24a (eager shell/shared renderers), 5fb9564 +(Presenter), 8e7fa19 (Remote), 94ea211 (Watch party), 0475a18 (Share/External), +b335f95 (Stats view). 2c50035 handles lazy-entry failures without rejected UI +navigation promises. Final app.js: 408,473 bytes; net removal 178,556 bytes +(30.4169%), including 2,976 bytes of facade/call-site overhead. + +Original bytes moved, independently counted from UTF-8 AST source slices: +98,378 eager renderer/shell/rail; 9,492 Presenter; 30,421 Remote; +22,833 Party; 13,334 Share/External; 7,074 Stats view. Published files include +headers/registry wrappers. Shared functions retain classic global lexical access; +new UI definitions evaluate safely before data/$/els/Player initialization. + +Self-review against master §6/6b: all new files belong to explicit manifest +groups and legacy SHELL; source JSON matches assets.json; core scripts load first; +required eager features stay parsed. Player, Transition, Wave, EQ/level rendering, +queue, persistence, tracking and sleep bodies have exact source fingerprint tests. +Transport internals move intact; entry button bindings move to core facades to +avoid duplicate listeners. Inbound APIs remain short; synchronous boolean/hooks +never become promises. Boot URL/session triggers remain; no banner/cache-header +rule is changed. Executing groups remain pinned; no disposal/handoff or live +replacement is introduced. Contract/N-1 safeguards remain tested by existing +unit/integration checks. + +Deliberately left: Notes/editor, service mode, playlist mutations, persistence, +player/queue/boot, audio watchdogs/EQ/sleep, Gestures, video editor/export glue and +other candidates beyond six seams. Settings paint moves to views-core but remains +eager. Now-playing metadata mutations inside Player stay there to honor the +untouched-playback constraint; their DOM, action paint and mini bar are eager. diff --git a/plans/phase4-verification.md b/plans/phase4-verification.md new file mode 100644 index 0000000..125a0bf --- /dev/null +++ b/plans/phase4-verification.md @@ -0,0 +1,119 @@ +# Phase 4 verification + +The served frontend is build `c3dbdd7039db`, source delivery commit `2c50035`. +`phase4-final-2026-10-08.json` records parent b335f95 because the review fix was +uncommitted when its scratch tree was copied; that tree includes exactly the +frontend subsequently committed as 2c50035. The isolated cold result records both +2c50035 and the build tag. Earlier phase result files were restored after harnesses +wrote their default paths; Phase 4 copies retain the actual new run evidence. + +## Six green seams + +| Commit | Seam | Original bytes moved | Frontend tests | Server tests | Both-engine cached smoke / hidden timers | +|---|---|---:|---:|---:|---| +| 3c9a24a | Eager shell/views/section rail | 98,378 | 192 | 183 | Pass | +| 5fb9564 | Presenter | 9,492 | 193 | 183 | Pass | +| 8e7fa19 | Remote client | 30,421 | 194 | 183 | Pass | +| 94ea211 | Watch party | 22,833 | 195 | 183 | Pass | +| 0475a18 | Share/External | 13,334 | 196 | 183 | Pass | +| b335f95 | Stats view | 7,074 | 197 | 183 | Pass | +| 2c50035 | Lazy-entry rejection handling | — | 198 | 183 | Pass | + +After every seam, `node --test frontend/*.test.js`, `bun install` then `bun run test` +in server, `node perf/hidden-timers.mjs`, and `node perf/seams.mjs --browser all` +ran. Server tests used PATH="$PWD/../perf/.tmp/test-venv/bin:$PATH" so yt-dlp +worker tests also ran, without skips. Logs are in gitignored perf/.tmp; representative +actual output: + +``` +ℹ tests 198 +ℹ pass 198 +ℹ fail 0 +ℹ skipped 0 +``` + +Server totals across its isolated test processes: 183 pass, 0 fail, 0 skip. + +``` +chromium {"browser":"chromium","checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]} +webkit {"browser":"webkit","checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]} +Result: ALL ASSERTIONS PASSED +``` + +The cache smoke stops Bun and blocks its proxy, then tests home playlists and eager +Settings, Presenter blank/pair validation, Remote pair form/close, Party local UI, +Share timestamp editing, External uploaded-media sheet/M3U, populated Stats view, +and a rejected entry action. Network relays are still required to connect parties +or remotes; offline verification proves cached code/UI, not offline relay service. +Existing lazy harness passes offline layouts, first-use, Settings extensions, +contract guards, pinned instances and update-during-playback on both engines. + +One review smoke WebKit process terminated during concurrent browser checks; an +isolated rerun and the final expanded both-engine smoke passed. Initial harness +fixture errors (incorrect Settings selector, absent VM helper, timestamp format, +hidden list pane) were corrected to exercise actual UI; no product tests were +removed or weakened. + +## Measurements + +Actual commands: + +``` +node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all --out perf/results/phase4-final-2026-10-08.json --compare perf/results/after-phase0-2026-10-07.json +node perf/baseline.mjs --runs 3 --browser chromium --profile lte --scenario cold --out perf/results/phase4-cold-isolated-2026-10-08.json --compare perf/results/after-phase0-2026-10-07.json +``` + +Full reduced run overlapped other checks; its Chromium long tasks were 495 ms. +Repeat cold-only runs with no concurrent tests produced 297/274/275 ms (median +275). Keep both results: neither is rewritten. WebKit lacks the long-task API. +Historical Phase 0 is five-run data; these reduced measurements are directional. + +| Metric | Phase 0 Chromium / WebKit | Phase 3 Chromium / WebKit | Phase 4 Chromium / WebKit | +|---|---:|---:|---:| +| Initial compressed JS/CSS | 276,414 / 338,940* | 221,307 / 274,813 | 210,419 / 255,200 | +| Cold boot ms | 10,480 / 3,290 | 7,193 / 3,293 | 7,010** / 2,977 | +| Cold FCP ms | 1,572 / 1,100 | 1,356 / 2,467 | 1,352** / 2,401 | +| Cold long-task ms | 454 / unavailable | 287 / unavailable | 275** / unavailable | +| Warm boot ms | 692 / 139 | 419 / 81 | 467 / 132 | +| Offline boot ms | 259 / 137 | 166 / 84 | 180 / 90 | +| Core app update wire bytes | 611,338 / 680,822 | 159,905 / 194,026 | 125,795 / 147,259 | +| Inactive CSS blocking-readiness bytes | 611,476 / 680,831 | 29,724 / 28,082 | 30,263 / 28,713 | +| Feature edit through actual idle cache fill | — | — | 33,408 / 41,364 | + +*Matched Phase 0 source reconstructed in Phase 3; historical JSON lacks initial +bytes. **Isolated three-run Chromium cold median. Other Phase 4 numbers are the +one-run both-browser suite. Warm counters include unfinished initial idle caching. +CSS readiness excludes its later background payload; it is not full update cost. +WebKit first paint still fails the master no-regression target. Full five-run +comparisons belong to Phase 5. Native iPhone timing/audio/quota is unverified. + +Actual feature-update output: + +``` +run 1/1: 33408 bytes, 8 reqs, dur=1376ms +run 1/1: 41364 bytes, 7 reqs, dur=1358ms +``` + +Only presenter.js application payload transfers (3,118 / 3,587 compressed bytes). +Totals include changed stamped index, manifest, version checks, sw.js checks and +WebKit's 1,954-byte sync-core worker import. No app.js, unchanged core views, +fonts, icons or CSS transfer. The benchmark asserts this rather than inferring it +from the lower total. Final app.js is 408,473 versus 587,029 bytes: −178,556, +−30.4169%; original code moved totals 181,532, facade overhead 2,976 bytes. + +## Migration, rollback and owner checks + +Both engines pass b77938a migration with lossy/stalling and unthrottled proxies: +122 cached SHELL entries, one banner and exactly one user-initiated reload, +21 legacy URL checks, N-1 open-tab continuity, offline boot, playback guard, +eviction repair and incremental refresh. Result JSON records the real runs. +No automatic activation/reload or live singleton replacement is added. + +Rollback ASSET_SYNC=0 and ASSET_HASHING=0 use the existing legacy path; commands +and results are in perf/README.md and perf/results. No new feature flag. +Revert an individual seam to restore its previous parsing behavior. + +Owner must verify a real iPhone PWA: warm feature first-use, selected/offline layout, +Presenter/Remote/Party sessions, update guard/override, locked audio 30 minutes, +interruption/resume, saved OPFS music surviving cache quota pressure. Nothing was +pushed, merged or deployed. From f133e1bb9f656f498ca01b83b6e8ab275958dac9 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 05:03:55 +0800 Subject: [PATCH 40/81] Document Phase 4 seams, measurements and remaining limitations --- plans/phase4-report.md | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 plans/phase4-report.md diff --git a/plans/phase4-report.md b/plans/phase4-report.md new file mode 100644 index 0000000..b624454 --- /dev/null +++ b/plans/phase4-report.md @@ -0,0 +1,48 @@ +# Phase 4 report + +Shipped on `codex/phase4`: plan cdd26b6; six seams 3c9a24a, 5fb9564, +8e7fa19, 94ea211, 0475a18, b335f95; failure handling 2c50035. +Scope-resolved dependency inventory and byte/coupling rankings are in +phase4-seams.md; commands, output excerpts and results in phase4-verification.md. + +Original source bytes moved: + +| Seam | Bytes | +|---|---:| +| Eager shell/shared views/Settings/rail | 98,378 | +| Presenter | 9,492 | +| Remote client | 30,421 | +| Watch party | 22,833 | +| Share/External | 13,334 | +| Stats view | 7,074 | + +`app.js`: **587,029 → 408,473 bytes, −30.42%** (178,556 net; 2,976 bytes +facade overhead). Shell definitions load before app; required eager features +stay in RAM. Lazy classic clients register on window.YT. Synchronous playback +hooks remain synchronous; configured/URL sessions resume. Stats tracking loads +without parsing its view. New chunks are manifested and retained in legacy SHELL. + +Player, queue, persistence, boot, Notes/editor, service mode, EQ/level, sleep/drift, +Gestures and remaining editor/export glue stay in app.js. Exact source fingerprints +protect playback/tracking bodies. Now-playing metadata mutations inside Player +remain there; markup, action paint and mini bar are eager. Stateful groups remain +pinned; live replacement stays disabled without disposal/state handoff. + +Actual LTE measurements, Chromium/WebKit: initial compressed JS/CSS +**210,419/255,200** versus Phase 3 221,307/274,813; matched Phase 0 +276,414/338,940. Isolated three-run Chromium median boot **7,010 ms**, long tasks +**275 ms** versus Phase 0 10,480/454 (Phase 3 7,193/287). +WebKit boot 2,977 ms; no long-task API. Presenter edit transfers only its chunk +(3,118/3,587 bytes), plus index/manifest/worker checks: total **33,408/41,364**. +Core updates: 125,795/147,259 bytes. Offline boot: 180/90 ms, zero network. + +Verification: **198 frontend/183 server tests**, no skips; both-engine cache smoke, +hidden timers, layouts/staged contracts/pinning/playback guard, b77938a migration +with/without stalls, and both rollback flags pass. Each seam had its own green +checks/commit. No deployment. + +Limits: WebKit FCP 2,401 versus Phase 0 1,100 ms still regresses. Concurrent-run +Chromium long tasks were 495 ms; isolated repeat is reported separately. Warm +counters include idle downloads; five-run comparisons await Phase 5. Owner must +check real-iPhone cached first-use/layouts, Remote/Party/Presenter, update guard, +30-minute locked audio/resume and OPFS quota coexistence. From ce5a159d4a960c76c1a8ead10500758c95442918 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 05:09:07 +0800 Subject: [PATCH 41/81] Plan phase 5: measure final performance and document rollout --- plans/phase5-plan.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 plans/phase5-plan.md diff --git a/plans/phase5-plan.md b/plans/phase5-plan.md new file mode 100644 index 0000000..6817c9b --- /dev/null +++ b/plans/phase5-plan.md @@ -0,0 +1,11 @@ +# Phase 5 plan + +Start at Phase 4 f133e1b on codex/phase5. No new product features. + +1. Audit perf/baseline.mjs against the original five-run configuration; retain all browser/profile combinations and cold/warm/offline/core-JS/CSS scenarios, plus the existing presenter-chunk update. Measure a genuinely warmed reload and complete CSS background download; preserve readiness measurements separately and document changed boundaries. Extend harness assertions before changing measurement behavior. +2. Run frontend and isolated server suites, hidden-timers, Chromium/WebKit lazy and seam smoke tests, and b77938a migration with unthrottled and lossy/stalling proxies. Preserve previous phase results. Fix only demonstrated product regressions, individually committed with tests. +3. Run the isolated full harness: --runs 5 --browser all --profile all --scenario all --out perf/results/final-2026-10-08.json. Compare actual requests, compressed wire bytes, FCP/LCP, boot and Chromium long tasks with baseline and after-phase0. Target CSS update <30 KB; only changed application payload for feature/core updates; report unmet targets plainly. +4. Write plans/perf-final.md with actual command excerpts, measurement limitations, phase contributions and remaining render/thumbnail/SPA hot spots. Write plans/rollout.md with separate Phase 1 then 2 then 3 then 4 deployment order, checks and rollback instructions. No deployment or production requests here. +5. Review the entire phase diff against master sections 5/6/6b, commit a <=350-word phase5-report.md, and overwrite the queue signal with DONE05 and the final commit. + +Risks: browser CPU noise, incomplete idle warm contaminating counters, historical readiness vs complete-download boundaries, Linux WebKit differing from iPhone, and missing real-device battery/audio evidence. Do not alter playback or the banner rule. Rollback product changes by reverting their individual commits; operational ASSET_HASHING=0 and ASSET_SYNC=0 require server restart and a user-initiated update. No generic lazy-feature flag exists; revert the applicable phase for loader rollback. From a08d363f2d98e7cdcff52b00f25bb009e0db5bd6 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 05:12:32 +0800 Subject: [PATCH 42/81] Measure complete CSS updates and fully cached warm reloads --- perf/README.md | 24 +++++++++++++++++++++ perf/baseline.mjs | 45 ++++++++++++++++----------------------- perf/lazy.mjs | 2 +- perf/measurement.mjs | 29 +++++++++++++++++++++++++ perf/measurement.test.mjs | 16 ++++++++++++++ 5 files changed, 88 insertions(+), 28 deletions(-) create mode 100644 perf/measurement.mjs create mode 100644 perf/measurement.test.mjs diff --git a/perf/README.md b/perf/README.md index 3fa5b38..0b64796 100644 --- a/perf/README.md +++ b/perf/README.md @@ -311,3 +311,27 @@ plus the source frontend build tag. WebKit does not expose the long-task API. Migration supports `--out` to preserve earlier phase evidence. Existing lazy harness results are copied to `phase4-lazy-2026-10-08.json` after each Phase 4 run and the Phase 3 result is restored. No production requests or deploys are needed. + +## Phase 5 complete measurements + +```bash +node --test perf/measurement.test.mjs +node perf/baseline.mjs --runs 5 --browser all --profile all --scenario all \ + --out perf/results/final-2026-10-08.json \ + --compare perf/results/baseline-2026-10-07.json +node perf/lazy.mjs --browser all --out perf/results/phase5-lazy-2026-10-08.json +``` + +Warm reloads now wait for verified idle asset caching before counters reset and +assert that no application asset body transfers. CSS update totals now include +activation and the changed inactive stylesheet's verified background cache fill, +matching the feature-update boundary. `readyWireBytes`/`readyDuration` retain the +blocking readiness snapshot separately. Core updates stop at blocking readiness +because app.js is blocking. Every update asserts that the only application asset +payload is the edited file; worker script checks/imports and index/manifest count +as overhead in the total. Historical Phase 3/4 CSS numbers were readiness only. +No product behavior changes are involved in these measurement corrections. + +Keep browser/build/test processes idle during full timing measurements. WebKit's +zero long-task field means unavailable, not zero work. Autoplay-blocked/media-ready +null results do not establish playback performance or iPhone audio continuity. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index 142febd..ffc7704 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -26,6 +26,7 @@ */ import assert from 'node:assert/strict'; +import { assertChangedAssets, assertWarmAssets, waitForIdleAssets } from './measurement.mjs'; import { createHash } from 'node:crypto'; import { spawn, spawnSync, execFileSync } from 'node:child_process'; import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs'; @@ -461,6 +462,8 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { }); }); + await waitForIdleAssets(page); + // Now measure warm re-navigation proxy.resetStats(); proxy.startTracking(); @@ -470,6 +473,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { proxy.stopTracking(); const stats = proxy.getStats(); + assertWarmAssets(stats.requests); const pageMetrics = await page.evaluate(() => { const nav = performance.getEntriesByType('navigation')[0]; @@ -622,24 +626,7 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi // Phase 3 activation precedes idle feature caching. Measure updates from a // genuinely warm build, rather than counting unfinished first-install bytes. - if (await page.evaluate(()=>!!window.Lazy && !!window.Lazy.warm)) { - await page.evaluate(()=>Lazy.warm()); - const end=Date.now()+90000; - while (true) { - const ready=await page.evaluate(async()=>{ - const c=await caches.open('ytplayer-assets'),r=await c.match('/__ytp_asset_state'); - if(!r)return false; - const m=(await r.json()).current; - return (await Promise.all(Object.values(m.groups).flatMap(g=>g.files).map(async p=>{ - const response=await c.match(p+'?v='+m.files[p].h); - return response?.headers.get('X-Asset-Hash')===m.files[p].h; - }))).every(Boolean); - }); - if(ready)break; - if(Date.now()>end)throw Error('Idle warm did not complete before update benchmark'); - await sleep(100); - } - } + await waitForIdleAssets(page); // Switch server to Tree N+1 (app.js or theme-glass.css modification) const targetTree = updateKind === 'feature' ? trees.treeUpdateFeature : updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss; @@ -662,20 +649,23 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi await sleep(50); } - if (updateKind === 'feature') { + const readyDuration = Date.now() - t0; + const readyWireBytes = proxy.getStats().totalWireBytes; + if (updateKind === 'feature' || updateKind === 'css') { + const changedPath=updateKind==='feature'?'/presenter.js':'/theme-glass.css'; // Readiness excludes background chunks. Include activation and the changed // feature's actual idle transfer rather than reporting readiness as its cost. - const expected = createHash('sha256').update(readFileSync(path.join(targetTree,'presenter.js'))).digest('hex').slice(0,10); + const expected = createHash('sha256').update(readFileSync(path.join(targetTree,changedPath.slice(1)))).digest('hex').slice(0,10); await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});}); const end=Date.now()+90000; while(true) { - const complete=await page.evaluate(async h=>{ + const complete=await page.evaluate(async ({h,p})=>{ const r=await navigator.serviceWorker.getRegistration(); if(r.waiting || r.installing)return false; r.active?.postMessage({type:'WARM_ASSETS',saveData:false}); - const c=await caches.open('ytplayer-assets'),entry=await c.match('/presenter.js?v='+h); + const c=await caches.open('ytplayer-assets'),entry=await c.match(p+'?v='+h); return entry?.headers.get('X-Asset-Hash')===h; - },expected); + },{h:expected,p:changedPath}); if(complete)break; if(Date.now()>end)throw Error('Changed feature was not cached after activation'); await sleep(100); @@ -684,14 +674,13 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi const duration = Date.now() - t0; proxy.stopTracking(); const stats = proxy.getStats(); - if(updateKind==='feature') { - const assetDownloads=stats.requests.filter(r=>r.bytes>0).map(r=>new URL(r.url,navUrl).pathname).filter(p=>/\.(?:js|css|woff2?|png|svg)$/.test(p)&&!['/sw.js','/asset-sync-core.js'].includes(p)); - assert.deepEqual([...new Set(assetDownloads)],['/presenter.js'],'feature edit transfers only its chunk; no app/core/font/icon payload'); - } + assertChangedAssets(stats.requests, updateKind==='feature'?'/presenter.js':updateKind==='css'?'/theme-glass.css':'/app.js'); await browser.close(); return { updateKind, + readyDuration, + readyWireBytes, requests: stats.requests, duration, requestCount: stats.requestCount, @@ -895,6 +884,8 @@ async function main() { } results.browsers[bName][prof].updateCss = { + readyDuration: summarizeList(updCssRuns.map(r=>r.readyDuration)), + readyWireBytes: summarizeList(updCssRuns.map(r=>r.readyWireBytes)), requestCount: summarizeList(updCssRuns.map((r) => r.requestCount)), wireBytes: summarizeList(updCssRuns.map((r) => r.wireBytes)), duration: summarizeList(updCssRuns.map((r) => r.duration)), diff --git a/perf/lazy.mjs b/perf/lazy.mjs index 6b6092a..b1afee7 100644 --- a/perf/lazy.mjs +++ b/perf/lazy.mjs @@ -132,4 +132,4 @@ async function run(name){ console.log(name,'PASS'); } finally {await browser?.close();await proxy?.close();await stop();} } -try{for(const name of requested==='all'?['chromium','webkit']:[requested])await run(name);writeFileSync(join(repo,'perf/results/phase3-lazy-2026-10-08.json'),JSON.stringify({results},null,2)+'\n');}finally{rmSync(scratch,{recursive:true,force:true});} +try{for(const name of requested==='all'?['chromium','webkit']:[requested])await run(name);writeFileSync(args.includes('--out')?resolve(args[args.indexOf('--out')+1]):join(repo,'perf/results/phase3-lazy-2026-10-08.json'),JSON.stringify({results},null,2)+'\n');}finally{rmSync(scratch,{recursive:true,force:true});} diff --git a/perf/measurement.mjs b/perf/measurement.mjs new file mode 100644 index 0000000..66035aa --- /dev/null +++ b/perf/measurement.mjs @@ -0,0 +1,29 @@ +import assert from 'node:assert/strict'; +export function assertChangedAssets(requests, expected) { + const paths=requests.filter(r=>r.bytes>0).map(r=>new URL(r.url,'http://localhost').pathname).filter(p=>/\.(?:js|css|woff2?|png|svg)$/.test(p)&&!['/sw.js','/asset-sync-core.js'].includes(p)); + assert.deepEqual([...new Set(paths)],[expected],'only the changed application asset transfers; worker checks and derived index/manifest are separate overhead'); +} +export async function waitForIdleAssets(page) { + if(!await page.evaluate(()=>!!window.Lazy?.warm))return; + await page.evaluate(()=>Lazy.warm()); + const end=Date.now()+120000; + while(true) { + const ready=await page.evaluate(async()=>{ + const c=await caches.open('ytplayer-assets'),r=await c.match('/__ytp_asset_state'); + // Legacy rollback has no manifest state and installs its complete shell instead. + if(!r)return (await caches.keys()).some(k=>/^ytplayer-(?!assets|thumbs|fonts)/.test(k)); + const m=(await r.json()).current; + return (await Promise.all(Object.values(m.groups).flatMap(g=>g.files).map(async p=>{ + const response=await c.match(p+'?v='+m.files[p].h); + return response?.headers.get('X-Asset-Hash')===m.files[p].h; + }))).every(Boolean); + }); + if(ready)return; + if(Date.now()>end)throw Error('Idle warm did not complete before benchmark'); + await new Promise(r=>setTimeout(r,100)); + } +} +export function assertWarmAssets(requests) { + const assets=requests.filter(r=>r.bytes>0&&/\.(?:js|css|woff2?|png|svg)(?:[?#]|$)/.test(r.url)&&!new URL(r.url,'http://localhost').pathname.endsWith('/sw.js')); + assert.deepEqual(assets,[],'warm reload does not transfer unfinished shell assets'); +} diff --git a/perf/measurement.test.mjs b/perf/measurement.test.mjs new file mode 100644 index 0000000..6fd0109 --- /dev/null +++ b/perf/measurement.test.mjs @@ -0,0 +1,16 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { assertChangedAssets, assertWarmAssets } from './measurement.mjs'; +test('changed CSS and feature measurements reject unrelated application transfers',()=>{ + const requests=[{url:'/sw.js',bytes:7000},{url:'/asset-sync-core.js',bytes:2000},{url:'/index.html',bytes:12000},{url:'/api/manifest',bytes:3000},{url:'/theme-glass.css?v=new',bytes:5000},{url:'/fonts/a.woff2',bytes:0}]; + assertChangedAssets(requests,'/theme-glass.css'); + assert.throws(()=>assertChangedAssets([...requests,{url:'/app.js?v=new',bytes:10000}],'/theme-glass.css')); + assert.throws(()=>assertChangedAssets(requests.filter(r=>!r.url.includes('theme-glass')),'/theme-glass.css')); + assertChangedAssets([{url:'/presenter.js?v=new',bytes:3200}],'/presenter.js'); + assert.throws(()=>assertChangedAssets([{url:'/presenter.js?v=new',bytes:3200},{url:'/icons/192.png',bytes:1000}],'/presenter.js')); +}); + +test('warm measurements reject unfinished shell downloads but allow API checks',()=>{ + assertWarmAssets([{url:'/api/version',bytes:62},{url:'/app.js?v=current',bytes:0}]); + assert.throws(()=>assertWarmAssets([{url:'/theme-glass.css?v=current',bytes:5000}])); +}); From 21c12733d326faba1a753ae8c19e9e93d848098f Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 05:47:31 +0800 Subject: [PATCH 43/81] Record final performance sweep and staged rollout instructions --- perf/results/final-2026-10-08.json | 6055 +++++++++++++++++ perf/results/phase5-css-check-2026-10-08.json | 205 + perf/results/phase5-lazy-2026-10-08.json | 79 + .../phase5-migration-lossy-2026-10-08.json | 41 + ...ase5-migration-unthrottled-2026-10-08.json | 41 + perf/results/phase5-seams-2026-10-08.json | 28 + .../results/phase5-warm-check-2026-10-08.json | 133 + plans/perf-final.md | 158 + plans/phase5-report.md | 13 + plans/rollout.md | 86 + 10 files changed, 6839 insertions(+) create mode 100644 perf/results/final-2026-10-08.json create mode 100644 perf/results/phase5-css-check-2026-10-08.json create mode 100644 perf/results/phase5-lazy-2026-10-08.json create mode 100644 perf/results/phase5-migration-lossy-2026-10-08.json create mode 100644 perf/results/phase5-migration-unthrottled-2026-10-08.json create mode 100644 perf/results/phase5-seams-2026-10-08.json create mode 100644 perf/results/phase5-warm-check-2026-10-08.json create mode 100644 plans/perf-final.md create mode 100644 plans/phase5-report.md create mode 100644 plans/rollout.md diff --git a/perf/results/final-2026-10-08.json b/perf/results/final-2026-10-08.json new file mode 100644 index 0000000..0583edd --- /dev/null +++ b/perf/results/final-2026-10-08.json @@ -0,0 +1,6055 @@ +{ + "date": "2026-10-07T21:13:22.712Z", + "frontendCommit": null, + "frontendBuildTag": "c3dbdd7039db", + "commit": "a08d363f2d98e7cdcff52b00f25bb009e0db5bd6", + "runsConfigured": 5, + "browsers": { + "chromium": { + "lte": { + "cold": { + "requestCount": { + "median": 115, + "min": 115, + "max": 115, + "values": [ + 115, + 115, + 115, + 115, + 115 + ] + }, + "wireBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012, + 651012, + 651012, + 651012, + 651012 + ] + }, + "fcp": { + "median": 1356, + "min": 1352, + "max": 1372, + "values": [ + 1360, + 1372, + 1352, + 1352, + 1356 + ] + }, + "lcp": { + "median": 1356, + "min": 1352, + "max": 1372, + "values": [ + 1360, + 1372, + 1352, + 1352, + 1356 + ] + }, + "domContentLoaded": { + "median": 7026, + "min": 7009, + "max": 7383, + "values": [ + 7383, + 7039, + 7026, + 7022, + 7009 + ] + }, + "bootDone": { + "median": 7043, + "min": 7031, + "max": 7405, + "values": [ + 7405, + 7055, + 7043, + 7039, + 7031 + ] + }, + "longTaskTotal": { + "median": 278, + "min": 271, + "max": 290, + "values": [ + 289, + 290, + 271, + 278, + 273 + ] + }, + "longTasks": [ + [ + { + "start": 1222, + "duration": 122 + }, + { + "start": 7227, + "duration": 167 + } + ], + [ + { + "start": 1232, + "duration": 126 + }, + { + "start": 6880, + "duration": 164 + } + ], + [ + { + "start": 1225, + "duration": 112 + }, + { + "start": 6873, + "duration": 159 + } + ], + [ + { + "start": 1223, + "duration": 114 + }, + { + "start": 6864, + "duration": 164 + } + ], + [ + { + "start": 1231, + "duration": 107 + }, + { + "start": 6850, + "duration": 166 + } + ] + ], + "swInstallDuration": { + "median": 36521, + "min": 35820, + "max": 36816, + "values": [ + 36816, + 36455, + 35820, + 36521, + 36573 + ] + }, + "swInstallBytes": { + "median": 651012, + "min": 651012, + "max": 651012, + "values": [ + 651012, + 651012, + 651012, + 651012, + 651012 + ] + }, + "storageEstimate": { + "usage": 2801669, + "quota": 4297768965 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 22882, + "js": 296653, + "css": 65916, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 4604, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/?v=benchmedia01", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 278 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 567 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 722 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 95477 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:5089/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3210 + }, + { + "url": "http://127.0.0.1:5089/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1058 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=b556b50667", + "status": 200, + "bytes": 11441 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:5089/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 3487 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7766 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:5089/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:5089/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 1727 + }, + { + "url": "http://127.0.0.1:5089/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:5089/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 3697 + }, + { + "url": "http://127.0.0.1:5089/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:5089/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 875 + }, + { + "url": "http://127.0.0.1:5089/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:5089/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4158 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5089/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:5089/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:5089/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:5089/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 542 + }, + { + "url": "http://127.0.0.1:5089/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:5089/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:5089/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2048 + }, + { + "url": "http://127.0.0.1:5089/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:5089/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:5089/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 3850 + }, + { + "url": "http://127.0.0.1:5089/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1267 + }, + { + "url": "http://127.0.0.1:5089/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2431 + }, + { + "url": "http://127.0.0.1:5089/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:5089/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:5089/piano.js?v=e82bc30884", + "status": 200, + "bytes": 3453 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3094 + }, + { + "url": "http://127.0.0.1:5089/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:5089/share-external.js?v=9de67de710", + "status": 200, + "bytes": 3653 + }, + { + "url": "http://127.0.0.1:5089/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:5089/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:5089/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 7926 + }, + { + "url": "http://127.0.0.1:5089/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:5089/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2294 + }, + { + "url": "http://127.0.0.1:5089/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:5089/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:5089/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:5089/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:5089/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 6513 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5068 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 210419, + "min": 210419, + "max": 210419, + "values": [ + 210419, + 210419, + 210419, + 210419, + 210419 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "bytes": 278 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "bytes": 567 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 722 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "bytes": 95477 + } + ] + }, + "warm": { + "requestCount": { + "median": 4, + "min": 3, + "max": 5, + "values": [ + 3, + 4, + 4, + 4, + 5 + ] + }, + "wireBytes": { + "median": 7863, + "min": 7852, + "max": 7863, + "values": [ + 7852, + 7863, + 7863, + 7863, + 7863 + ] + }, + "fcp": { + "median": 120, + "min": 104, + "max": 140, + "values": [ + 104, + 136, + 120, + 116, + 140 + ] + }, + "lcp": { + "median": 140, + "min": 136, + "max": 140, + "values": [ + 136, + 136, + 140, + 140, + 140 + ] + }, + "domContentLoaded": { + "median": 391, + "min": 376, + "max": 394, + "values": [ + 394, + 376, + 383, + 392, + 391 + ] + }, + "bootDone": { + "median": 410, + "min": 391, + "max": 411, + "values": [ + 410, + 391, + 400, + 411, + 411 + ] + }, + "longTaskTotal": { + "median": 58, + "min": 55, + "max": 61, + "values": [ + 61, + 56, + 58, + 55, + 61 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 52, + "min": 48, + "max": 60, + "values": [ + 56, + 48, + 60, + 52, + 48 + ] + }, + "lcp": { + "median": 52, + "min": 48, + "max": 60, + "values": [ + 56, + 48, + 60, + 52, + 48 + ] + }, + "domContentLoaded": { + "median": 180, + "min": 174, + "max": 198, + "values": [ + 198, + 180, + 178, + 174, + 186 + ] + }, + "bootDone": { + "median": 185, + "min": 177, + "max": 203, + "values": [ + 203, + 185, + 181, + 177, + 190 + ] + }, + "reloadDuration": { + "median": 202, + "min": 190, + "max": 222, + "values": [ + 222, + 202, + 197, + 190, + 206 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 8, + "min": 6, + "max": 8, + "values": [ + 8, + 8, + 6, + 8, + 8 + ] + }, + "wireBytes": { + "median": 125795, + "min": 118023, + "max": 125795, + "values": [ + 125795, + 125795, + 118023, + 125795, + 125795 + ] + }, + "duration": { + "median": 745, + "min": 45, + "max": 749, + "values": [ + 748, + 745, + 698, + 45, + 749 + ] + }, + "wireBytesByType": { + "html": 11463, + "js": 111047, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3285, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3223 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=56a28ab207", + "status": 200, + "bytes": 95503 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 11463 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + }, + "updateCss": { + "readyDuration": { + "median": 218, + "min": 213, + "max": 219, + "values": [ + 218, + 213, + 213, + 219, + 219 + ] + }, + "readyWireBytes": { + "median": 30263, + "min": 30263, + "max": 30263, + "values": [ + 30263, + 30263, + 30263, + 30263, + 30263 + ] + }, + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8, + 8, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 35363, + "min": 35363, + "max": 35363, + "values": [ + 35363, + 35363, + 35363, + 35363, + 35363 + ] + }, + "duration": { + "median": 1380, + "min": 1375, + "max": 1385, + "values": [ + 1383, + 1375, + 1379, + 1385, + 1380 + ] + }, + "wireBytesByType": { + "html": 11439, + "js": 15540, + "css": 5100, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3284, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3222 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=997252e5f7", + "status": 200, + "bytes": 11439 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5100 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8, + 8, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 33408, + "min": 33408, + "max": 33408, + "values": [ + 33408, + 33408, + 33408, + 33408, + 33408 + ] + }, + "duration": { + "median": 1378, + "min": 1376, + "max": 1385, + "values": [ + 1376, + 1385, + 1378, + 1380, + 1378 + ] + }, + "wireBytesByType": { + "html": 11456, + "js": 18662, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3290, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3228 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 11456 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3118 + } + ] + } + }, + "lossy": { + "cold": { + "requestCount": { + "median": 115, + "min": 115, + "max": 115, + "values": [ + 115, + 115, + 115, + 115, + 115 + ] + }, + "wireBytes": { + "median": 651096, + "min": 651096, + "max": 651096, + "values": [ + 651096, + 651096, + 651096, + 651096, + 651096 + ] + }, + "fcp": { + "median": 2052, + "min": 2048, + "max": 2072, + "values": [ + 2052, + 2048, + 2048, + 2056, + 2072 + ] + }, + "lcp": { + "median": 2052, + "min": 2048, + "max": 2072, + "values": [ + 2052, + 2048, + 2048, + 2056, + 2072 + ] + }, + "domContentLoaded": { + "median": 11314, + "min": 11306, + "max": 11574, + "values": [ + 11574, + 11328, + 11306, + 11314, + 11310 + ] + }, + "bootDone": { + "median": 11342, + "min": 11324, + "max": 11595, + "values": [ + 11595, + 11350, + 11324, + 11342, + 11327 + ] + }, + "longTaskTotal": { + "median": 295, + "min": 283, + "max": 302, + "values": [ + 302, + 290, + 283, + 295, + 302 + ] + }, + "longTasks": [ + [ + { + "start": 1908, + "duration": 129 + }, + { + "start": 11408, + "duration": 173 + } + ], + [ + { + "start": 1909, + "duration": 122 + }, + { + "start": 11169, + "duration": 168 + } + ], + [ + { + "start": 1909, + "duration": 118 + }, + { + "start": 11148, + "duration": 165 + } + ], + [ + { + "start": 1911, + "duration": 130 + }, + { + "start": 11158, + "duration": 165 + } + ], + [ + { + "start": 1907, + "duration": 140 + }, + { + "start": 11154, + "duration": 162 + } + ] + ], + "swInstallDuration": { + "median": 40770, + "min": 40138, + "max": 41052, + "values": [ + 41052, + 40773, + 40770, + 40138, + 40721 + ] + }, + "swInstallBytes": { + "median": 651096, + "min": 651096, + "max": 651096, + "values": [ + 651096, + 651096, + 651096, + 651096, + 651096 + ] + }, + "storageEstimate": { + "usage": 2801720, + "quota": 4297769016 + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 22912, + "js": 296689, + "css": 65916, + "fonts": 254048, + "images": 6278, + "media": 0, + "api": 4622, + "other": 631 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/?v=benchmedia01", + "status": 200, + "bytes": 11456 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 278 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 567 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 722 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 95477 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3228 + }, + { + "url": "http://127.0.0.1:5089/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1058 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css", + "status": 200, + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 11456 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 631 + }, + { + "url": "http://127.0.0.1:5089/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 3487 + }, + { + "url": "http://127.0.0.1:5089/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 762 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1294 + }, + { + "url": "http://127.0.0.1:5089/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 385 + }, + { + "url": "http://127.0.0.1:5089/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 1727 + }, + { + "url": "http://127.0.0.1:5089/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 291 + }, + { + "url": "http://127.0.0.1:5089/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 3697 + }, + { + "url": "http://127.0.0.1:5089/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 875 + }, + { + "url": "http://127.0.0.1:5089/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1079 + }, + { + "url": "http://127.0.0.1:5089/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1249 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=c83c12c79b483c87", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5089/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1305 + }, + { + "url": "http://127.0.0.1:5089/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4158 + }, + { + "url": "http://127.0.0.1:5089/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 927 + }, + { + "url": "http://127.0.0.1:5089/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 375 + }, + { + "url": "http://127.0.0.1:5089/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 965 + }, + { + "url": "http://127.0.0.1:5089/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 542 + }, + { + "url": "http://127.0.0.1:5089/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 2763 + }, + { + "url": "http://127.0.0.1:5089/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 1713 + }, + { + "url": "http://127.0.0.1:5089/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2048 + }, + { + "url": "http://127.0.0.1:5089/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 989 + }, + { + "url": "http://127.0.0.1:5089/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 3850 + }, + { + "url": "http://127.0.0.1:5089/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1267 + }, + { + "url": "http://127.0.0.1:5089/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1184 + }, + { + "url": "http://127.0.0.1:5089/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:5089/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 756 + }, + { + "url": "http://127.0.0.1:5089/piano.js?v=e82bc30884", + "status": 200, + "bytes": 3453 + }, + { + "url": "http://127.0.0.1:5089/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2431 + }, + { + "url": "http://127.0.0.1:5089/share-external.js?v=9de67de710", + "status": 200, + "bytes": 3653 + }, + { + "url": "http://127.0.0.1:5089/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2462 + }, + { + "url": "http://127.0.0.1:5089/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 7926 + }, + { + "url": "http://127.0.0.1:5089/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2336 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3118 + }, + { + "url": "http://127.0.0.1:5089/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 6718 + }, + { + "url": "http://127.0.0.1:5089/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 4727 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1480 + }, + { + "url": "http://127.0.0.1:5089/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2294 + }, + { + "url": "http://127.0.0.1:5089/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 38592 + }, + { + "url": "http://127.0.0.1:5089/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2168 + }, + { + "url": "http://127.0.0.1:5089/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1146 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 848 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5068 + }, + { + "url": "http://127.0.0.1:5089/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 6513 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/config", + "status": 200, + "bytes": 40 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/device", + "status": 200, + "bytes": 121 + }, + { + "url": "http://127.0.0.1:5089/api/p2p/holdings", + "status": 200, + "bytes": 54 + } + ], + "initialJsCss": { + "median": 210419, + "min": 210419, + "max": 210419, + "values": [ + 210419, + 210419, + 210419, + 210419, + 210419 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "bytes": 2543 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "bytes": 3529 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "bytes": 391 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "bytes": 27364 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "bytes": 3736 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "bytes": 5027 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "bytes": 278 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "bytes": 790 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "bytes": 873 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "bytes": 859 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "bytes": 537 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1415 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "bytes": 404 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "bytes": 430 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "bytes": 1034 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "bytes": 3920 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "bytes": 2632 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "bytes": 571 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "bytes": 2036 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "bytes": 1521 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "bytes": 2733 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "bytes": 1130 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "bytes": 1818 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "bytes": 1050 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "bytes": 725 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "bytes": 1690 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "bytes": 4411 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "bytes": 545 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "bytes": 583 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2494 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "bytes": 2690 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "bytes": 550 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "bytes": 727 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "bytes": 1764 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "bytes": 3103 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "bytes": 652 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "bytes": 918 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "bytes": 380 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "bytes": 567 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 722 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "bytes": 2056 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "bytes": 3882 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "bytes": 16310 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "bytes": 3552 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "bytes": 95477 + } + ] + }, + "warm": { + "requestCount": { + "median": 3, + "min": 3, + "max": 5, + "values": [ + 3, + 3, + 3, + 5, + 4 + ] + }, + "wireBytes": { + "median": 7858, + "min": 97, + "max": 7869, + "values": [ + 7858, + 7858, + 97, + 7869, + 7869 + ] + }, + "fcp": { + "median": 136, + "min": 116, + "max": 136, + "values": [ + 136, + 136, + 132, + 136, + 116 + ] + }, + "lcp": { + "median": 136, + "min": 132, + "max": 140, + "values": [ + 136, + 136, + 132, + 136, + 140 + ] + }, + "domContentLoaded": { + "median": 387, + "min": 376, + "max": 444, + "values": [ + 376, + 396, + 444, + 387, + 378 + ] + }, + "bootDone": { + "median": 403, + "min": 391, + "max": 468, + "values": [ + 391, + 412, + 468, + 403, + 392 + ] + }, + "longTaskTotal": { + "median": 59, + "min": 52, + "max": 76, + "values": [ + 52, + 66, + 76, + 55, + 59 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 60, + "min": 48, + "max": 60, + "values": [ + 60, + 60, + 52, + 60, + 48 + ] + }, + "lcp": { + "median": 60, + "min": 48, + "max": 60, + "values": [ + 60, + 60, + 52, + 60, + 48 + ] + }, + "domContentLoaded": { + "median": 186, + "min": 170, + "max": 195, + "values": [ + 186, + 187, + 178, + 195, + 170 + ] + }, + "bootDone": { + "median": 189, + "min": 172, + "max": 199, + "values": [ + 189, + 190, + 182, + 199, + 172 + ] + }, + "reloadDuration": { + "median": 204, + "min": 187, + "max": 212, + "values": [ + 204, + 207, + 197, + 212, + 187 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 8, + "min": 6, + "max": 8, + "values": [ + 8, + 8, + 7, + 8, + 6 + ] + }, + "wireBytes": { + "median": 125795, + "min": 118023, + "max": 125795, + "values": [ + 125795, + 125795, + 125795, + 125795, + 118023 + ] + }, + "duration": { + "median": 747, + "min": 695, + "max": 760, + "values": [ + 747, + 748, + 707, + 760, + 695 + ] + }, + "wireBytesByType": { + "html": 11463, + "js": 111047, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3285, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3223 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=56a28ab207", + "status": 200, + "bytes": 95503 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 11463 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + } + ] + }, + "updateCss": { + "readyDuration": { + "median": 218, + "min": 214, + "max": 222, + "values": [ + 214, + 222, + 218, + 216, + 220 + ] + }, + "readyWireBytes": { + "median": 30263, + "min": 30263, + "max": 30263, + "values": [ + 30263, + 30263, + 30263, + 30263, + 30263 + ] + }, + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8, + 8, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 35363, + "min": 35363, + "max": 35363, + "values": [ + 35363, + 35363, + 35363, + 35363, + 35363 + ] + }, + "duration": { + "median": 1377, + "min": 1368, + "max": 1389, + "values": [ + 1368, + 1377, + 1374, + 1389, + 1378 + ] + }, + "wireBytesByType": { + "html": 11439, + "js": 15540, + "css": 5100, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3284, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3222 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=997252e5f7", + "status": 200, + "bytes": 11439 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5100 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8, + 8, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 33408, + "min": 33408, + "max": 33408, + "values": [ + 33408, + 33408, + 33408, + 33408, + 33408 + ] + }, + "duration": { + "median": 1375, + "min": 1372, + "max": 1376, + "values": [ + 1372, + 1375, + 1372, + 1375, + 1376 + ] + }, + "wireBytesByType": { + "html": 11456, + "js": 18662, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3290, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3228 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 11456 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 7772 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3118 + } + ] + } + } + }, + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159, + 159, + 159, + 159, + 159 + ] + }, + "wireBytes": { + "median": 1097048, + "min": 1097048, + "max": 1097048, + "values": [ + 1097048, + 1097048, + 1097048, + 1097048, + 1097048 + ] + }, + "fcp": { + "median": 1739, + "min": 1727, + "max": 2378, + "values": [ + 2378, + 1733, + 1742, + 1727, + 1739 + ] + }, + "lcp": { + "median": 1810, + "min": 1794, + "max": 2454, + "values": [ + 2454, + 1802, + 1810, + 1794, + 1822 + ] + }, + "domContentLoaded": { + "median": 2310, + "min": 2300, + "max": 2951, + "values": [ + 2951, + 2310, + 2312, + 2300, + 2300 + ] + }, + "bootDone": { + "median": 2315, + "min": 2304, + "max": 2956, + "values": [ + 2956, + 2315, + 2316, + 2305, + 2304 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [], + [], + [] + ], + "swInstallDuration": { + "median": 31691, + "min": 31690, + "max": 32316, + "values": [ + 32316, + 31690, + 31690, + 31704, + 31691 + ] + }, + "swInstallBytes": { + "median": 1097048, + "min": 1097048, + "max": 1097048, + "values": [ + 1097048, + 1097048, + 1097048, + 1097048, + 1097048 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28064, + "js": 556746, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5082, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/?v=benchmedia01", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:5089/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:5089/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080 + }, + { + "url": "http://127.0.0.1:5089/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:5089/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252 + }, + { + "url": "http://127.0.0.1:5089/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5089/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216 + }, + { + "url": "http://127.0.0.1:5089/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:5089/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071 + }, + { + "url": "http://127.0.0.1:5089/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:5089/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5089/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:5089/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:5089/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624 + }, + { + "url": "http://127.0.0.1:5089/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:5089/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:5089/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474 + }, + { + "url": "http://127.0.0.1:5089/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:5089/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444 + }, + { + "url": "http://127.0.0.1:5089/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5089/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475 + }, + { + "url": "http://127.0.0.1:5089/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773 + }, + { + "url": "http://127.0.0.1:5089/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:5089/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:5089/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:5089/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + }, + { + "url": "http://127.0.0.1:5089/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042 + }, + { + "url": "http://127.0.0.1:5089/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:5089/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222 + }, + { + "url": "http://127.0.0.1:5089/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:5089/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664 + }, + { + "url": "http://127.0.0.1:5089/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:5089/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903 + }, + { + "url": "http://127.0.0.1:5089/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829 + }, + { + "url": "http://127.0.0.1:5089/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506 + }, + { + "url": "http://127.0.0.1:5089/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:5089/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "bytes": 4079 + } + ] + }, + "warm": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 78, + "min": 76, + "max": 85, + "values": [ + 78, + 79, + 85, + 77, + 76 + ] + }, + "lcp": { + "median": 78, + "min": 76, + "max": 85, + "values": [ + 78, + 79, + 85, + 77, + 76 + ] + }, + "domContentLoaded": { + "median": 77, + "min": 75, + "max": 84, + "values": [ + 77, + 78, + 84, + 76, + 75 + ] + }, + "bootDone": { + "median": 83, + "min": 80, + "max": 89, + "values": [ + 84, + 83, + 89, + 80, + 80 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 56, + "min": 54, + "max": 58, + "values": [ + 54, + 56, + 56, + 54, + 58 + ] + }, + "lcp": { + "median": 84, + "min": 83, + "max": 86, + "values": [ + 83, + 84, + 84, + 85, + 86 + ] + }, + "domContentLoaded": { + "median": 83, + "min": 82, + "max": 85, + "values": [ + 82, + 82, + 83, + 84, + 85 + ] + }, + "bootDone": { + "median": 86, + "min": 84, + "max": 88, + "values": [ + 84, + 86, + 86, + 87, + 88 + ] + }, + "reloadDuration": { + "median": 100, + "min": 99, + "max": 102, + "values": [ + 99, + 100, + 100, + 102, + 102 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + "wireBytes": { + "median": 147259, + "min": 147259, + "max": 147259, + "values": [ + 147259, + 147259, + 147259, + 147259, + 147259 + ] + }, + "duration": { + "median": 1890, + "min": 1271, + "max": 1936, + "values": [ + 1886, + 1271, + 1893, + 1936, + 1890 + ] + }, + "wireBytesByType": { + "html": 14033, + "js": 129488, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3738, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8990 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=56a28ab207", + "status": 200, + "bytes": 118544 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 14033 + } + ] + }, + "updateCss": { + "readyDuration": { + "median": 935, + "min": 930, + "max": 938, + "values": [ + 930, + 936, + 932, + 935, + 938 + ] + }, + "readyWireBytes": { + "median": 28713, + "min": 28713, + "max": 28713, + "values": [ + 28713, + 28713, + 28713, + 28713, + 28713 + ] + }, + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8, + 8, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 45659, + "min": 45659, + "max": 45659, + "values": [ + 45659, + 45659, + 45659, + 45659, + 45659 + ] + }, + "duration": { + "median": 1455, + "min": 1452, + "max": 1460, + "values": [ + 1452, + 1455, + 1453, + 1458, + 1460 + ] + }, + "wireBytesByType": { + "html": 14030, + "js": 21890, + "css": 5939, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3800, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=997252e5f7", + "status": 200, + "bytes": 14030 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5939 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 8, + "min": 7, + "max": 8, + "values": [ + 8, + 7, + 8, + 8, + 8 + ] + }, + "wireBytes": { + "median": 43318, + "min": 41364, + "max": 43318, + "values": [ + 43318, + 41364, + 43318, + 43318, + 43318 + ] + }, + "duration": { + "median": 1455, + "min": 1361, + "max": 1456, + "values": [ + 1456, + 1361, + 1455, + 1456, + 1455 + ] + }, + "wireBytesByType": { + "html": 14032, + "js": 25483, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3803, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + } + ] + } + }, + "lossy": { + "cold": { + "requestCount": { + "median": 162, + "min": 161, + "max": 163, + "values": [ + 163, + 162, + 163, + 161, + 161 + ] + }, + "wireBytes": { + "median": 1105402, + "min": 1104265, + "max": 1109654, + "values": [ + 1106647, + 1105402, + 1109654, + 1104265, + 1104265 + ] + }, + "fcp": { + "median": 4303, + "min": 4067, + "max": 5712, + "values": [ + 5712, + 4084, + 4067, + 4309, + 4303 + ] + }, + "lcp": { + "median": 4371, + "min": 4139, + "max": 5787, + "values": [ + 5787, + 4157, + 4139, + 4379, + 4371 + ] + }, + "domContentLoaded": { + "median": 5568, + "min": 5342, + "max": 6505, + "values": [ + 5711, + 6505, + 5568, + 5351, + 5342 + ] + }, + "bootDone": { + "median": 5573, + "min": 5347, + "max": 6512, + "values": [ + 5717, + 6512, + 5573, + 5356, + 5347 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [], + [], + [] + ], + "swInstallDuration": { + "median": 34915, + "min": 34029, + "max": 36003, + "values": [ + 34943, + 36003, + 34915, + 34736, + 34029 + ] + }, + "swInstallBytes": { + "median": 1105402, + "min": 1104265, + "max": 1109654, + "values": [ + 1106647, + 1105402, + 1109654, + 1104265, + 1104265 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28064, + "js": 566345, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5082, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/?v=benchmedia01", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/api/user/sync", + "status": 200, + "bytes": 11 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736 + }, + { + "url": "http://127.0.0.1:5089/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588 + }, + { + "url": "http://127.0.0.1:5089/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624 + }, + { + "url": "http://127.0.0.1:5089/fonts/fonts.css", + "status": 200, + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-192.png", + "status": 200, + "bytes": 1669 + }, + { + "url": "http://127.0.0.1:5089/icons/icon-512.png", + "status": 200, + "bytes": 4609 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/manifest.webmanifest", + "status": 200, + "bytes": 783 + }, + { + "url": "http://127.0.0.1:5089/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079 + }, + { + "url": "http://127.0.0.1:5089/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523 + }, + { + "url": "http://127.0.0.1:5089/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504 + }, + { + "url": "http://127.0.0.1:5089/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080 + }, + { + "url": "http://127.0.0.1:5089/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370 + }, + { + "url": "http://127.0.0.1:5089/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252 + }, + { + "url": "http://127.0.0.1:5089/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216 + }, + { + "url": "http://127.0.0.1:5089/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457 + }, + { + "url": "http://127.0.0.1:5089/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071 + }, + { + "url": "http://127.0.0.1:5089/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536 + }, + { + "url": "http://127.0.0.1:5089/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728 + }, + { + "url": "http://127.0.0.1:5089/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227 + }, + { + "url": "http://127.0.0.1:5089/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5089/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173 + }, + { + "url": "http://127.0.0.1:5089/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624 + }, + { + "url": "http://127.0.0.1:5089/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502 + }, + { + "url": "http://127.0.0.1:5089/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153 + }, + { + "url": "http://127.0.0.1:5089/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474 + }, + { + "url": "http://127.0.0.1:5089/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444 + }, + { + "url": "http://127.0.0.1:5089/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137 + }, + { + "url": "http://127.0.0.1:5089/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475 + }, + { + "url": "http://127.0.0.1:5089/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773 + }, + { + "url": "http://127.0.0.1:5089/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444 + }, + { + "url": "http://127.0.0.1:5089/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867 + }, + { + "url": "http://127.0.0.1:5089/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245 + }, + { + "url": "http://127.0.0.1:5089/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + }, + { + "url": "http://127.0.0.1:5089/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042 + }, + { + "url": "http://127.0.0.1:5089/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348 + }, + { + "url": "http://127.0.0.1:5089/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879 + }, + { + "url": "http://127.0.0.1:5089/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222 + }, + { + "url": "http://127.0.0.1:5089/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619 + }, + { + "url": "http://127.0.0.1:5089/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731 + }, + { + "url": "http://127.0.0.1:5089/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579 + }, + { + "url": "http://127.0.0.1:5089/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782 + }, + { + "url": "http://127.0.0.1:5089/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903 + }, + { + "url": "http://127.0.0.1:5089/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829 + }, + { + "url": "http://127.0.0.1:5089/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397 + }, + { + "url": "http://127.0.0.1:5089/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473 + }, + { + "url": "http://127.0.0.1:5089/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580 + }, + { + "url": "http://127.0.0.1:5089/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664 + }, + { + "url": "http://127.0.0.1:5089/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5089/fonts/fonts.css?v=dda3dfb804", + "bytes": 457 + }, + { + "url": "http://127.0.0.1:5089/lazy.js?v=99caff8ebd", + "bytes": 3021 + }, + { + "url": "http://127.0.0.1:5089/service-ui.css?v=b9bf96a3a8", + "bytes": 4417 + }, + { + "url": "http://127.0.0.1:5089/styles.css?v=9f3a5dea41", + "bytes": 33412 + }, + { + "url": "http://127.0.0.1:5089/layout-base.css?v=4f3307cd3b", + "bytes": 336 + }, + { + "url": "http://127.0.0.1:5089/refresh.css?v=62498384f1", + "bytes": 5828 + }, + { + "url": "http://127.0.0.1:5089/recommendations.css?v=055101368d", + "bytes": 983 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.css?v=055507ab85", + "bytes": 1076 + }, + { + "url": "http://127.0.0.1:5089/offline-pages.css?v=2889456261", + "bytes": 1069 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721 + }, + { + "url": "http://127.0.0.1:5089/related-videos.css?v=5a616b1be8", + "bytes": 517 + }, + { + "url": "http://127.0.0.1:5089/download-actions.css?v=12d3bcfe3e", + "bytes": 560 + }, + { + "url": "http://127.0.0.1:5089/saved-page.css?v=3ff576a784", + "bytes": 673 + }, + { + "url": "http://127.0.0.1:5089/fingerprint.js?v=a635143269", + "bytes": 1269 + }, + { + "url": "http://127.0.0.1:5089/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038 + }, + { + "url": "http://127.0.0.1:5089/opfs.js?v=df7a8d0391", + "bytes": 4571 + }, + { + "url": "http://127.0.0.1:5089/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469 + }, + { + "url": "http://127.0.0.1:5089/lyrics-display.js?v=48e8550175", + "bytes": 750 + }, + { + "url": "http://127.0.0.1:5089/sha256-wasm.js?v=393c50ba56", + "bytes": 1748 + }, + { + "url": "http://127.0.0.1:5089/sha256.js?v=cd9b980e6f", + "bytes": 3209 + }, + { + "url": "http://127.0.0.1:5089/loudness-wasm.js?v=c6102d7844", + "bytes": 1279 + }, + { + "url": "http://127.0.0.1:5089/device-db.js?v=880c5cd70e", + "bytes": 1230 + }, + { + "url": "http://127.0.0.1:5089/loudness.js?v=01b3da88dd", + "bytes": 2068 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/sw-update.js?v=772c123c20", + "bytes": 5195 + }, + { + "url": "http://127.0.0.1:5089/async-guard.js?v=e4afa1f2be", + "bytes": 887 + }, + { + "url": "http://127.0.0.1:5089/related-videos.js?v=3eec0ebd4c", + "bytes": 642 + }, + { + "url": "http://127.0.0.1:5089/audio-continuity.js?v=63b5464dd5", + "bytes": 677 + }, + { + "url": "http://127.0.0.1:5089/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916 + }, + { + "url": "http://127.0.0.1:5089/settings-sections.js?v=1101425859", + "bytes": 3174 + }, + { + "url": "http://127.0.0.1:5089/download-errors.js?v=bb6a4c887a", + "bytes": 959 + }, + { + "url": "http://127.0.0.1:5089/downloads.js?v=f2d3e7d212", + "bytes": 2088 + }, + { + "url": "http://127.0.0.1:5089/downloads-page.js?v=c1a3a218c0", + "bytes": 3642 + }, + { + "url": "http://127.0.0.1:5089/saved-page.js?v=f1518c50fb", + "bytes": 820 + }, + { + "url": "http://127.0.0.1:5089/server-backfill.js?v=294b103023", + "bytes": 1105 + }, + { + "url": "http://127.0.0.1:5089/visible-timer.js?v=5322e86ef4", + "bytes": 474 + }, + { + "url": "http://127.0.0.1:5089/download-actions.js?v=388c7edecb", + "bytes": 669 + }, + { + "url": "http://127.0.0.1:5089/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832 + }, + { + "url": "http://127.0.0.1:5089/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430 + }, + { + "url": "http://127.0.0.1:5089/shell-core.js?v=a04305c2ad", + "bytes": 4548 + }, + { + "url": "http://127.0.0.1:5089/section-rail.js?v=07417c1bcc", + "bytes": 4206 + }, + { + "url": "http://127.0.0.1:5089/views-core.js?v=49be16274c", + "bytes": 19016 + }, + { + "url": "http://127.0.0.1:5089/prewarm-next.js?v=ed16a51424", + "bytes": 665 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=f485286cbc", + "bytes": 118521 + }, + { + "url": "http://127.0.0.1:5089/theme-classic.css?v=d420fcfb12", + "bytes": 4079 + } + ] + }, + "warm": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 54, + "min": 51, + "max": 76, + "values": [ + 54, + 76, + 52, + 57, + 51 + ] + }, + "lcp": { + "median": 83, + "min": 76, + "max": 88, + "values": [ + 83, + 76, + 79, + 88, + 85 + ] + }, + "domContentLoaded": { + "median": 82, + "min": 75, + "max": 87, + "values": [ + 82, + 75, + 78, + 87, + 83 + ] + }, + "bootDone": { + "median": 85, + "min": 79, + "max": 90, + "values": [ + 85, + 79, + 81, + 90, + 86 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + } + }, + "offline": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0, + 0, + 0 + ] + }, + "fcp": { + "median": 75, + "min": 61, + "max": 78, + "values": [ + 78, + 61, + 78, + 72, + 75 + ] + }, + "lcp": { + "median": 78, + "min": 72, + "max": 105, + "values": [ + 78, + 94, + 105, + 72, + 75 + ] + }, + "domContentLoaded": { + "median": 76, + "min": 70, + "max": 104, + "values": [ + 76, + 92, + 104, + 70, + 74 + ] + }, + "bootDone": { + "median": 81, + "min": 77, + "max": 107, + "values": [ + 81, + 96, + 107, + 77, + 79 + ] + }, + "reloadDuration": { + "median": 95, + "min": 90, + "max": 122, + "values": [ + 95, + 112, + 122, + 90, + 92 + ] + } + }, + "updateJs": { + "requestCount": { + "median": 5, + "min": 5, + "max": 5, + "values": [ + 5, + 5, + 5, + 5, + 5 + ] + }, + "wireBytes": { + "median": 147259, + "min": 147259, + "max": 147259, + "values": [ + 147259, + 147259, + 147259, + 147259, + 147259 + ] + }, + "duration": { + "median": 4192, + "min": 3506, + "max": 4215, + "values": [ + 3506, + 4189, + 4215, + 4195, + 4192 + ] + }, + "wireBytesByType": { + "html": 14033, + "js": 129488, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3738, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8990 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=7c1d7ef6fc", + "status": 200, + "bytes": 14033 + }, + { + "url": "http://127.0.0.1:5089/app.js?v=56a28ab207", + "status": 200, + "bytes": 118544 + } + ] + }, + "updateCss": { + "readyDuration": { + "median": 2918, + "min": 1430, + "max": 2929, + "values": [ + 2918, + 2929, + 1430, + 2927, + 1436 + ] + }, + "readyWireBytes": { + "median": 28713, + "min": 28713, + "max": 28713, + "values": [ + 28713, + 28713, + 28713, + 28713, + 28713 + ] + }, + "requestCount": { + "median": 7, + "min": 7, + "max": 8, + "values": [ + 7, + 7, + 7, + 7, + 8 + ] + }, + "wireBytes": { + "median": 43705, + "min": 43705, + "max": 45659, + "values": [ + 43705, + 43705, + 43705, + 43705, + 45659 + ] + }, + "duration": { + "median": 3647, + "min": 3608, + "max": 3667, + "values": [ + 3647, + 3667, + 3608, + 3655, + 3638 + ] + }, + "wireBytesByType": { + "html": 14030, + "js": 19936, + "css": 5939, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3800, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=997252e5f7", + "status": 200, + "bytes": 14030 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:5089/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5939 + } + ] + }, + "updateFeature": { + "requestCount": { + "median": 7, + "min": 7, + "max": 8, + "values": [ + 7, + 7, + 7, + 7, + 8 + ] + }, + "wireBytes": { + "median": 41364, + "min": 41364, + "max": 43318, + "values": [ + 41364, + 41364, + 41364, + 41364, + 43318 + ] + }, + "duration": { + "median": 3644, + "min": 2983, + "max": 3667, + "values": [ + 3644, + 3667, + 3626, + 3664, + 2983 + ] + }, + "wireBytesByType": { + "html": 14032, + "js": 23529, + "css": 0, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3803, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:5089/api/manifest", + "status": 200, + "bytes": 3741 + }, + { + "url": "http://127.0.0.1:5089/index.html?v=c0c5f60ca6", + "status": 200, + "bytes": 14032 + }, + { + "url": "http://127.0.0.1:5089/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:5089/sw.js", + "status": 200, + "bytes": 8994 + }, + { + "url": "http://127.0.0.1:5089/presenter.js?v=45776e7cc4", + "status": 200, + "bytes": 3587 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase5-css-check-2026-10-08.json b/perf/results/phase5-css-check-2026-10-08.json new file mode 100644 index 0000000..dbee210 --- /dev/null +++ b/perf/results/phase5-css-check-2026-10-08.json @@ -0,0 +1,205 @@ +{ + "date": "2026-10-07T21:09:51.732Z", + "frontendCommit": null, + "frontendBuildTag": "c3dbdd7039db", + "commit": "ce5a159d4a960c76c1a8ead10500758c95442918", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "updateCss": { + "readyDuration": { + "median": 224, + "min": 224, + "max": 224, + "values": [ + 224 + ] + }, + "readyWireBytes": { + "median": 30263, + "min": 30263, + "max": 30263, + "values": [ + 30263 + ] + }, + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8 + ] + }, + "wireBytes": { + "median": 35363, + "min": 35363, + "max": 35363, + "values": [ + 35363 + ] + }, + "duration": { + "median": 1387, + "min": 1387, + "max": 1387, + "values": [ + 1387 + ] + }, + "wireBytesByType": { + "html": 11439, + "js": 15540, + "css": 5100, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3284, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:4435/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:4435/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:4435/api/manifest", + "status": 200, + "bytes": 3222 + }, + { + "url": "http://127.0.0.1:4435/index.html?v=997252e5f7", + "status": 200, + "bytes": 11439 + }, + { + "url": "http://127.0.0.1:4435/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:4435/sw.js", + "status": 200, + "bytes": 7770 + }, + { + "url": "http://127.0.0.1:4435/asset-sync-core.js?v=155be9339b", + "status": 304, + "bytes": 0 + }, + { + "url": "http://127.0.0.1:4435/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5100 + } + ] + } + } + }, + "webkit": { + "lte": { + "updateCss": { + "readyDuration": { + "median": 1002, + "min": 1002, + "max": 1002, + "values": [ + 1002 + ] + }, + "readyWireBytes": { + "median": 28713, + "min": 28713, + "max": 28713, + "values": [ + 28713 + ] + }, + "requestCount": { + "median": 8, + "min": 8, + "max": 8, + "values": [ + 8 + ] + }, + "wireBytes": { + "median": 45659, + "min": 45659, + "max": 45659, + "values": [ + 45659 + ] + }, + "duration": { + "median": 1537, + "min": 1537, + "max": 1537, + "values": [ + 1537 + ] + }, + "wireBytesByType": { + "html": 14030, + "js": 21890, + "css": 5939, + "fonts": 0, + "images": 0, + "media": 0, + "api": 3800, + "other": 0 + }, + "requests": [ + { + "url": "http://127.0.0.1:4435/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:4435/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + }, + { + "url": "http://127.0.0.1:4435/api/manifest", + "status": 200, + "bytes": 3738 + }, + { + "url": "http://127.0.0.1:4435/index.html?v=997252e5f7", + "status": 200, + "bytes": 14030 + }, + { + "url": "http://127.0.0.1:4435/api/version", + "status": 200, + "bytes": 62 + }, + { + "url": "http://127.0.0.1:4435/sw.js", + "status": 200, + "bytes": 8991 + }, + { + "url": "http://127.0.0.1:4435/theme-glass.css?v=253e56cfb3", + "status": 200, + "bytes": 5939 + }, + { + "url": "http://127.0.0.1:4435/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954 + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase5-lazy-2026-10-08.json b/perf/results/phase5-lazy-2026-10-08.json new file mode 100644 index 0000000..96b5058 --- /dev/null +++ b/perf/results/phase5-lazy-2026-10-08.json @@ -0,0 +1,79 @@ +{ + "results": [ + { + "browser": "chromium", + "sourceBuildTag": "c3dbdd7039db", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [] + }, + { + "browser": "webkit", + "sourceBuildTag": "c3dbdd7039db", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [ + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:44473/api/version.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:44473/api/recommendations?fp=163577c02a53bc40.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:44473/api/version.", + "disconnected": true + } + ] + } + ] +} diff --git a/perf/results/phase5-migration-lossy-2026-10-08.json b/perf/results/phase5-migration-lossy-2026-10-08.json new file mode 100644 index 0000000..2af6bc4 --- /dev/null +++ b/perf/results/phase5-migration-lossy-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 25453, + "wireBytes": 628797, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 23132, + "wireBytes": 737972, + "offline": true, + "legacyURLs": 21, + "profile": "lossy", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase5-migration-unthrottled-2026-10-08.json b/perf/results/phase5-migration-unthrottled-2026-10-08.json new file mode 100644 index 0000000..c7377b5 --- /dev/null +++ b/perf/results/phase5-migration-unthrottled-2026-10-08.json @@ -0,0 +1,41 @@ +{ + "commit": "b77938a", + "results": [ + { + "browser": "chromium", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 10954, + "wireBytes": 646234, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 0 + }, + { + "browser": "webkit", + "oldTag": "1175f1a1d2c1", + "newTag": "c3dbdd7039db", + "banners": 1, + "updateReloads": 1, + "cachedFiles": 122, + "durationMs": 10056, + "wireBytes": 751943, + "offline": true, + "legacyURLs": 21, + "profile": "unthrottled", + "userInitiatedOnly": true, + "playbackGuard": true, + "evictionRepair": true, + "incrementalRefresh": true, + "offlineTransportErrors": 4 + } + ] +} diff --git a/perf/results/phase5-seams-2026-10-08.json b/perf/results/phase5-seams-2026-10-08.json new file mode 100644 index 0000000..b0b5348 --- /dev/null +++ b/perf/results/phase5-seams-2026-10-08.json @@ -0,0 +1,28 @@ +[ + { + "browser": "chromium", + "checked": [ + "shell", + "presenter", + "remote", + "party", + "share", + "stats" + ], + "offlineNetworkRequests": 0, + "errors": [] + }, + { + "browser": "webkit", + "checked": [ + "shell", + "presenter", + "remote", + "party", + "share", + "stats" + ], + "offlineNetworkRequests": 0, + "errors": [] + } +] diff --git a/perf/results/phase5-warm-check-2026-10-08.json b/perf/results/phase5-warm-check-2026-10-08.json new file mode 100644 index 0000000..16f198d --- /dev/null +++ b/perf/results/phase5-warm-check-2026-10-08.json @@ -0,0 +1,133 @@ +{ + "date": "2026-10-07T21:11:58.283Z", + "frontendCommit": null, + "frontendBuildTag": "c3dbdd7039db", + "commit": "ce5a159d4a960c76c1a8ead10500758c95442918", + "runsConfigured": 1, + "browsers": { + "chromium": { + "lte": { + "warm": { + "requestCount": { + "median": 4, + "min": 4, + "max": 4, + "values": [ + 4 + ] + }, + "wireBytes": { + "median": 7863, + "min": 7863, + "max": 7863, + "values": [ + 7863 + ] + }, + "fcp": { + "median": 152, + "min": 152, + "max": 152, + "values": [ + 152 + ] + }, + "lcp": { + "median": 152, + "min": 152, + "max": 152, + "values": [ + 152 + ] + }, + "domContentLoaded": { + "median": 542, + "min": 542, + "max": 542, + "values": [ + 542 + ] + }, + "bootDone": { + "median": 567, + "min": 567, + "max": 567, + "values": [ + 567 + ] + }, + "longTaskTotal": { + "median": 128, + "min": 128, + "max": 128, + "values": [ + 128 + ] + } + } + } + }, + "webkit": { + "lte": { + "warm": { + "requestCount": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "wireBytes": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "fcp": { + "median": 87, + "min": 87, + "max": 87, + "values": [ + 87 + ] + }, + "lcp": { + "median": 130, + "min": 130, + "max": 130, + "values": [ + 130 + ] + }, + "domContentLoaded": { + "median": 128, + "min": 128, + "max": 128, + "values": [ + 128 + ] + }, + "bootDone": { + "median": 132, + "min": 132, + "max": 132, + "values": [ + 132 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/plans/perf-final.md b/plans/perf-final.md new file mode 100644 index 0000000..84d844b --- /dev/null +++ b/plans/perf-final.md @@ -0,0 +1,158 @@ +# Final performance and regression sweep + +Phase 5 starts from Phase 4 f133e1b. The full run uses measurement commit a08d363 and served base build c3dbdd7039db. Product frontend/server bytes are unchanged in this phase. The final JSON records its actual source commit and UTC start time; the filename uses the local 2026-10-08 date. + +Sources: perf/results/baseline-2026-10-07.json, after-phase0-2026-10-07.json and final-2026-10-08.json. The first two contain five runs for Chromium/WebKit × LTE/lossy. Their recorded commits are 64f8eae and 7bc5b4f, respectively (the older prose baseline labels b77938a; this report uses the JSON metadata). Numbers below are medians of actual runs, compressed HTTP response-body bytes, not raw source sizes or header-inclusive packet captures. WebKit generally receives gzip; Chromium receives Brotli. Do not compare their absolute byte totals as equivalent compression. + +## Commands and measurement boundaries + +```bash +node --test frontend/*.test.js +(cd server && bun install && PATH="$PWD/../perf/.tmp/test-venv/bin:$PATH" bun run test) +node --test perf/measurement.test.mjs +node perf/hidden-timers.mjs +node perf/lazy.mjs --browser all --out perf/results/phase5-lazy-2026-10-08.json +node perf/seams.mjs --browser all +node perf/migration.mjs --browser all --profile unthrottled \ + --out perf/results/phase5-migration-unthrottled-2026-10-08.json +node perf/migration.mjs --browser all --profile lossy \ + --out perf/results/phase5-migration-lossy-2026-10-08.json +node perf/baseline.mjs --runs 5 --browser all --profile all --scenario all \ + --out perf/results/final-2026-10-08.json \ + --compare perf/results/baseline-2026-10-07.json +``` + +The full measurement runs alone, after other browser/build/test processes finish. Chromium uses 4× CPU slowdown for launch scenarios and CDP network shaping; WebKit uses a paced proxy and stalls every seventh lossy request. Update scenarios do not use the launch CPU throttle. Chromium CDP shaping targets the page; the harness does not separately attach CDP to the service worker, so its update durations must not be treated as a calibrated mobile-worker throughput measurement. WebKit proxy shaping covers worker responses as well. Initial navigation is `/?v=benchmedia01`. Static inspection and a Node regex check confirm this ID has 12 characters and fails the existing 11-character media-ID guard in both b77938a and the final build. The query is ignored; these are home-launch measurements and Share/External is not loaded by this invalid deep link. `bootDone` is the first cards view, not a validated playing-ready milestone. + +Two measurement corrections are deliberately included. Warm reloads wait for all verified idle assets before resetting counters; Phase 3/4 warm runs counted unfinished first-install downloads. CSS updates now include activation and the inactive Glass stylesheet's verified idle download; historical Phase 3/4 CSS totals stopped at blocking readiness. Final `readyWireBytes` and `readyDuration` preserve the separate readiness snapshot. Feature updates use the same complete-cache boundary. Core app.js is blocking, so its waiting-readiness boundary already includes the changed payload. Auto-update checks can begin during the server restart before the explicit registration.update timestamp; very short duration outliers (including a 45 ms Chromium LTE core run) are retained, and medians should not be interpreted as complete deploy-to-user latency. Each update asserts that only the edited application file transfers; worker checks/imports and derived index/manifest remain counted overhead. No fonts/icons may be re-downloaded. + +The harness creates synthetic N+1 comment/rule trees. Later profile cold scenarios inherit the last synthetic update tree, as in the original harness; executable behavior is identical, but its derived tag and a comment in presenter.js differ from the reported base tag. The run records one response log per scenario alongside all five aggregate samples. Long-task totals cover the entire cold observation window, not only boot. The media timeout options are historically passed as the predicate argument, so the nominal eight-second check uses Playwright's default timeout; this boundary was retained for historical comparison. Media-ready null/autoplayBlocked does not establish playback performance: the invalid fixture ID prevents the intended playback attempt, and the flag cannot distinguish that from an autoplay rejection. This pre-existing harness flaw was retained for an honest comparison with the stored baseline; a separate valid-ID playback experiment is still required. + +## Five-run medians: baseline → after Phase 0 → final + +All byte columns are bytes; all timings are ms. WebKit long-task timing is unavailable. + +| Browser/profile | Scenario | Requests | Wire bytes | FCP | LCP | Boot-done | Long tasks | +|---|---|---:|---:|---:|---:|---:|---:| +| chromium/lte | cold | 164 → 166 → 115 | 1,039,315 → 1,040,158 → 651,012 | 1,540 → 1,572 → 1,356 | 1,896 → 1,916 → 1,356 | 10,163 → 10,480 → 7,043 | 397 → 454 → 278 | +| chromium/lte | warm | 4 → 4 → 4 | 5,321 → 5,331 → 7,863 | 180 → 192 → 120 | 684 → 704 → 140 | 675 → 692 → 410 | 156 → 169 → 58 | +| chromium/lte | offline | 0 → 0 → 0 | 0 → 0 → 0 | 72 → 80 → 52 | 108 → 80 → 52 | 219 → 259 → 185 | — → — → — | +| chromium/lossy | cold | 164 → 166 → 115 | 1,039,309 → 1,040,225 → 651,096 | 2,344 → 2,372 → 2,052 | 2,912 → 2,940 → 2,052 | 16,015 → 16,408 → 11,342 | 432 → 480 → 295 | +| chromium/lossy | warm | 4 → 4 → 3 | 5,326 → 5,332 → 7,858 | 184 → 192 → 136 | 644 → 780 → 136 | 651 → 768 → 403 | 155 → 195 → 59 | +| chromium/lossy | offline | 0 → 0 → 0 | 0 → 0 → 0 | 80 → 76 → 60 | 92 → 76 → 60 | 237 → 241 → 189 | — → — → — | +| webkit/lte | cold | 162 → 164 → 159 | 1,179,624 → 1,180,749 → 1,097,048 | 1,088 → 1,100 → 1,739 | 1,287 → 1,303 → 1,810 | 3,201 → 3,290 → 2,315 | unavailable | +| webkit/lte | warm | 0 → 0 → 0 | 0 → 0 → 0 | 110 → 117 → 78 | 110 → 146 → 78 | 131 → 139 → 83 | unavailable | +| webkit/lte | offline | 0 → 0 → 0 | 0 → 0 → 0 | 107 → 113 → 56 | 107 → 144 → 84 | 128 → 137 → 86 | unavailable | +| webkit/lossy | cold | 162 → 164 → 162 | 1,179,624 → 1,180,749 → 1,105,402 | 3,557 → 3,738 → 4,303 | 3,735 → 3,905 → 4,371 | 7,303 → 7,305 → 5,573 | unavailable | +| webkit/lossy | warm | 0 → 0 → 0 | 0 → 0 → 0 | 111 → 110 → 54 | 112 → 110 → 83 | 131 → 128 → 85 | unavailable | +| webkit/lossy | offline | 0 → 0 → 0 | 0 → 0 → 0 | 109 → 113 → 75 | 119 → 113 → 78 | 129 → 132 → 81 | unavailable | + +## Update medians: baseline → after Phase 0 → final + +Feature/CSS final totals include the changed background file after explicit activation. Historical full-shell updates included every file before waiting readiness. + +| Browser/profile | Edited file | Requests | Complete wire bytes | Duration | Final CSS blocking-ready bytes | +|---|---|---:|---:|---:|---:| +| chromium/lte | app.js | 88 → 89 → 8 | 610,965 → 611,338 → 125,795 | 2,013 → 2,155 → 745 | — | +| chromium/lte | theme-glass.css | 88 → 89 → 8 | 611,005 → 611,476 → 35,363 | 1,970 → 2,107 → 1,380 | 30,263 | +| chromium/lte | presenter.js | — → — → 8 | — → — → 33,408 | — → — → 1,378 | — | +| chromium/lossy | app.js | 88 → 89 → 8 | 610,965 → 611,338 → 125,795 | 2,031 → 2,115 → 747 | — | +| chromium/lossy | theme-glass.css | 88 → 89 → 8 | 611,005 → 611,476 → 35,363 | 2,004 → 2,116 → 1,377 | 30,263 | +| chromium/lossy | presenter.js | — → — → 8 | — → — → 33,408 | — → — → 1,375 | — | +| webkit/lte | app.js | 86 → 87 → 5 | 680,250 → 680,822 → 147,259 | 4,457 → 4,584 → 1,890 | — | +| webkit/lte | theme-glass.css | 86 → 87 → 8 | 680,265 → 680,831 → 45,659 | 4,510 → 4,550 → 1,455 | 28,713 | +| webkit/lte | presenter.js | — → — → 8 | — → — → 43,318 | — → — → 1,455 | — | +| webkit/lossy | app.js | 86 → 87 → 5 | 680,250 → 680,822 → 147,259 | 8,135 → 10,017 → 4,192 | — | +| webkit/lossy | theme-glass.css | 87 → 87 → 7 | 680,327 → 680,831 → 43,705 | 8,269 → 10,013 → 3,647 | 28,713 | +| webkit/lossy | presenter.js | — → — → 7 | — → — → 41,364 | — → — → 3,644 | — | + +## Targets and response evidence + +| Browser/profile | Cold initial JS+CSS | Cold app.js positive-byte responses | Core-edit app.js payload | CSS-edit stylesheet payload | Feature-edit presenter payload | +|---|---:|---:|---:|---:|---:| +| chromium/lte | 210,419 | 1 | 95,503 | 5,100 | 3,118 | +| chromium/lossy | 210,419 | 1 | 95,503 | 5,100 | 3,118 | +| webkit/lte | 255,200 | 2 | 118,544 | 5,939 | 3,587 | +| webkit/lossy | 255,200 | 2 | 118,544 | 5,939 | 3,587 | + +Actual full-harness output excerpt: + +```text +=== YTPlayer Performance Baseline Harness === +Runs per scenario: 5 +Browser target: all +Network profile: all +Scenario target: all +Bun server running on ephemeral port 5089 + +>>> Running Benchmark: Browser=[chromium] Profile=[lte] +>>> Running Benchmark: Browser=[chromium] Profile=[lossy] +>>> Running Benchmark: Browser=[webkit] Profile=[lte] +>>> Running Benchmark: Browser=[webkit] Profile=[lossy] +Baseline results saved to: perf/results/final-2026-10-08.json +| Update N->N+1 (1-line JS) | 8 | 122.8 KB | - | 745ms | +| Update N->N+1 (1-line CSS)| 8 | 34.5 KB | - | 1380ms | +| Update N->N+1 (1-line JS) | 8 | 122.8 KB | - | 747ms | +| Update N->N+1 (1-line CSS)| 8 | 34.5 KB | - | 1377ms | +| Update N->N+1 (1-line JS) | 5 | 143.8 KB | - | 1890ms | +| Update N->N+1 (1-line CSS)| 8 | 44.6 KB | - | 1455ms | +| Update N->N+1 (1-line JS) | 5 | 143.8 KB | - | 4192ms | +| Update N->N+1 (1-line CSS)| 7 | 42.7 KB | - | 3647ms | +``` + +chromium/lte: cold wire bytes -37.4% vs after Phase 0; boot -32.8%; FCP -13.7%. Complete CSS update 35,363 bytes: FAIL against <30,000-byte target. + +chromium/lossy: cold wire bytes -37.4% vs after Phase 0; boot -30.9%; FCP -13.5%. Complete CSS update 35,363 bytes: FAIL against <30,000-byte target. + +webkit/lte: cold wire bytes -7.1% vs after Phase 0; boot -29.6%; FCP +58.1%. Complete CSS update 45,659 bytes: FAIL against <30,000-byte target. + +webkit/lossy: cold wire bytes -6.4% vs after Phase 0; boot -23.7%; FCP +15.1%. Complete CSS update 43,705 bytes: FAIL against <30,000-byte target. + + +The earlier matched-delivery Phase 0 frontend reconstruction (perf/results/phase3-phase0-initial-2026-10-08.json, one run per browser) measured 276,414 Chromium / 338,940 WebKit initial JS+CSS bytes. Final five-run medians are 210,419 / 255,200: reductions of 23.9% / 24.7%. The historical five-run Phase 0 JSON did not collect this initial-only metric, so this comparison is explicitly a single-run reconstruction against repeated final measurements. + +## What the phases contributed + +- Phase 0 added characterization tests and suspended five hidden UI timers. It did not change shell/update behavior; its small launch timing changes are measurement noise rather than a claimed speed gain. +- Phase 1 supplied file hashes, a deterministic manifest, per-file stamps, hash headers and current/stale cache rules while retaining the old client update path. Its compatibility checks are prerequisites for Phase 2; alone it does not stop the legacy worker's complete shell download. +- Phase 2 made downloads resumable and incremental with hash validation, N-1 retention, atomic blocking commit and playback-guarded application. Fonts/icons no longer transfer on a code-only update. Legacy pages still reload only after their own user-initiated Refresh UI and retain that timer limitation. +- Phase 3 deferred inactive layouts and uncommon feature parsing, reads persisted layout before body paint, warms all groups at idle unless Save-Data, and permits same-contract N-1 fallback. Eager playlist/settings/service/editor stay in RAM. Executing groups remain pinned; incompatible new groups stay on N-1 and require a guarded reload. +- Phase 4 reduced app.js from 587,029 to 408,473 raw bytes: 178,556 bytes (30.4169%). Shell/shared views/Settings/rail remain eager; Presenter, Remote, Watch party, Share/External and Stats view are lazy chunks. The protected player, queue, persistence, boot, sleep/drift/transition bodies stayed intact. A presenter edit now transfers its chunk plus update overhead, rather than app.js or the shell. +- Phase 5 corrected misleading measurement boundaries, re-ran regression verification and supplied rollout instructions. It introduces no product features or changes to playback/banner behavior. + +## Regression sweep evidence + +Actual command-output excerpts: + +```text +node --test frontend/*.test.js: + pass 198; fail 0; skipped 0 +isolated Bun server suites: + 183 pass; 0 fail; 0 skip +node --test perf/measurement.test.mjs: + pass 2; fail 0 +node perf/hidden-timers.mjs: + Hidden intervals (2): anon120000, maybeCheck + Restored visible intervals (7): anon120000, checkBuildTag, chips, flush, maybeCheck, reanchor, rotateChips + Page errors: none + Result: ALL ASSERTIONS PASSED +node perf/seams.mjs --browser all: + chromium {"checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]} + webkit {"checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]} +``` + +Both lazy-browser results verify pre-body layout selection; immediate offline reload; warmed feature use without network; Glass/Bento/F7/classic offline switching; eager Settings and optional search panels; stale fallback; pinned executing groups; compatible unexecuted new URL; incompatible N-1 with reload-required; and update-during-playback guard. Seam tests stop the server and block the proxy. They test cached feature UI/local actions, not successful offline network relay/remote-party transport. + +Both migration profiles use actual b77938a frontend/server at origin N, then the current server at the same origin. Each browser reports one banner, one user-initiated reload, 122 cached legacy-shell entries, 21 correct-body old plain/stale/fresh URL checks, open-old-tab compatibility, repair after eviction and offline launch. Unthrottled durations were Chromium 10,954 ms/WebKit 10,056 ms; stalling durations 25,453/23,132 ms. WebKit recorded four disconnected API transport errors per migration and no script errors; matching failed version/recommendation requests are required before these errors are classified as expected. No automatic install/activate reload is allowed. See the tracked phase5-migration JSON files for full output. + +The hashing/sync rollback paths were verified in Phase 4 on both browsers with zero-request offline reloads; Phase 5 documents their exact use and preserves the corresponding server tests. No additional product regression was fixed during this sweep. CSS/FCP/double-download gaps below are not represented as passing acceptance targets. + +## Remaining gaps and hot spots + +The final tables above show that Chromium launch/long-task and incremental-payload goals passed, but every CSS total exceeds the budget, WebKit first paint regresses, and WebKit still double-downloads app.js at first install. These numerical acceptance requirements are not all met; do not promote the rollout as fully validated. The CSS <30 KB budget includes worker/index/manifest overhead; counting only the changed stylesheet or only blocking readiness would conceal the actual update total. Linux WebKit still does not share page/SW first-install bytes as effectively as Chromium; check the duplicate app.js bodies in its cold response log. The earlier Phase 3 WebKit first-paint regression remains an explicit release concern rather than a claimed fix. + +Navigation still rebuilds sidebar/list DOM; splitting its definitions does not make rendering incremental. Measure large libraries before changing it. The thumbnail cap is still 25,000 entries, trimmed with cache.keys every 100 puts; CacheStorage shares quota with OPFS saved audio, and opaque fallback entries can have large quota padding. No cap change was authorized in these phases. Manifest/version/SW checks remain update overhead, and inactive layouts/features still download at idle on mobile data unless Save-Data. + +SPA `/`, `/index.html`, `/search`, `/playlist/x` return the same stamped index (server tests pass). Static inspection confirms that its relative app.js resolves to /playlist/app.js on /playlist/x (Node URL-resolution output: `app.js on /playlist/x resolves to /playlist/app.js`). That unmatched URL follows the HTML fallback, so direct nested navigation has an asset-resolution defect even though stamped-body tests pass; a browser route audit is still required. This is a pre-existing hotspot; it was not silently changed during the regression-only phase. + +No real iPhone was available. Linux WebKit cannot verify installed-PWA process eviction, iOS HTTP-cache sharing, layout flash on actual hardware, Safari storage/quota eviction with a large saved-music library, 30-minute locked audio/battery drain, interruption/resume and lock-screen controls, cellular behavior, safe-area rendering, PiP, native sharing or relay/WebRTC functionality. The deterministic fixture reports autoplay/media-ready limitations rather than proving audio playback. Production was down; live origin/proxy headers, deployment and on-device old-to-new migration remain unverified. Follow plans/rollout.md and record failures before promoting the next phase. diff --git a/plans/phase5-report.md b/plans/phase5-report.md new file mode 100644 index 0000000..8b48b5b --- /dev/null +++ b/plans/phase5-report.md @@ -0,0 +1,13 @@ +# Phase 5 report + +Measured Phase 4 f133e1b on codex/phase5. Plan ce5a159; measurement correction a08d363. Product frontend/server bytes are unchanged (served base build c3dbdd7039db). + +The full harness completed 120 runs: five samples × six scenarios × Chromium/WebKit × LTE/lossy. Evidence: perf/results/final-2026-10-08.json; full before/after tables and command excerpts in plans/perf-final.md. Warm counters now start after verified idle caching; CSS totals include the changed background stylesheet, with blocking readiness retained separately. Assertions reject unrelated application/font/icon downloads. + +Chromium LTE vs after-phase0: cold 1,040,158→651,012 bytes, 166→115 requests; boot 10,480→7,043 ms; long tasks 454→278 ms. WebKit LTE boot 3,290→2,315 ms, but FCP regressed 1,100→1,739 ms. Core edits transfer 125,795/147,259 bytes (Chromium/WebKit); presenter edits 33,408/43,318 bytes on LTE, including overhead. Complete CSS updates cost 35,363/45,659 bytes: <30 KB fails. WebKit still downloads app.js twice on first install. These targets remain unmet. + +Verification: 198 frontend, 183 server and two measurement tests pass; hidden timers, both-engine lazy/seam offline smoke, playback guard and b77938a migration with/without stalling pass. Migration: one user-initiated reload/banner, 122 shell entries, 21 legacy URL checks, open-old-tab and offline compatibility. No product regression fix was committed. + +Self-review against master §6/6b preserved banner/hash rules, migration, pinned contracts, caches and playback. No push/deploy/production request. Rollout order and rollback commands are in plans/rollout.md; generic lazy feature flags do not exist. + +Limitations: the historical 12-character benchmedia01 fixture is rejected as a media ID, so these runs prove home launch, not playing-ready. Nested SPA relative assets remain a pre-existing defect. Large-list rendering and the 25,000-thumbnail quota risk remain. Real-iPhone installed/offline/update behavior, 30-minute locked audio, battery, interruptions and OPFS quota checks are still required. Numerical acceptance is not fully met; report failures before rollout. diff --git a/plans/rollout.md b/plans/rollout.md new file mode 100644 index 0000000..eaec5e9 --- /dev/null +++ b/plans/rollout.md @@ -0,0 +1,86 @@ +# Incremental-assets rollout + +This is a deployment runbook, not a record of a deployment. Production was unavailable during this work; no production request, push or deploy was performed. The owner must review the reports and complete the iPhone gate before rollout. Deploy matching server/frontend artifacts: Docker serves frontend from server/public, and the server snapshots assets at boot. + +## Exact order + +1. **Phase 1 alone: codex/phase1.** Ship the per-file-hash server and descriptive groups while retaining the legacy worker/page update path. Verify the old production fixture migration locally, then live headers and version stamping below. Let existing clients complete their user-initiated Refresh UI. Do not combine this deployment with Phase 2. +2. **Phase 2 alone: codex/phase2.** Ship incremental worker/cache migration. Run both migration profiles and live version/cache checks, then confirm old pages reach the ready fast path and an already-open old tab still works. Confirm no install/activate causes a reload without a user action. +3. **Phase 3: codex/phase3.** Ship the loader, selected-layout boot, idle warm and contract safeguards. Verify offline layouts/features, Save-Data and playback guard on a real installed iPhone. Confirm the selected layout survives a force-close and offline launch. +4. **Phase 4: codex/phase4 (then the Phase 5 validation/docs tip codex/phase5).** Ship the six app seams after the previous gates pass. Verify each cached feature and synchronous player facade. Phase 5 adds measurement/runbook files; any future regression fix must be reviewed independently. + +Use the actual branch tips, not the Phase 1–4 intermediate seam commits. Do not deploy phases concurrently. After each stage, retain the previous image and its environment configuration until the next stage passes. Preserve the data volume and all OPFS/client caches; rollback must not ask users to clear storage. + +## Local verification commands at each branch + +Run in the existing isolated worktree, or a separate review checkout; do not switch a dirty deployment checkout. Install server dependencies first. Python yt-dlp-worker tests need an importable yt_dlp in PATH; report skips explicitly. + +```bash +node --test frontend/*.test.js +(cd server && bun install && bun run test) +perf/make-shell-fixture.sh b77938a 1175f1a1d2c1 +``` + +Phase 1: `node perf/migration.mjs --browser all` (its default profile is the stalling proxy). Phase 2 onward: + +```bash +node perf/migration.mjs --browser all --profile unthrottled +node perf/migration.mjs --browser all --profile lossy +node perf/hidden-timers.mjs +``` + +Phase 3 onward: `node perf/lazy.mjs --browser all` (offline launch/layout switching, warmed feature first use, contract guards, pinned groups and playback guard). Phase 4 onward: `node perf/seams.mjs --browser all` (Presenter, Remote, Watch party, Share/External, Stats and shell with the server stopped). On Phase 5 use `--out perf/results/.json` for migration/lazy to preserve historical results; seams retains its historical default, so copy the new result then restore the older tracked result if running in a review worktree. + +Final reproduction: + +```bash +node --test perf/measurement.test.mjs +node perf/baseline.mjs --runs 5 --browser all --profile all --scenario all \ + --out perf/results/final-2026-10-08.json \ + --compare perf/results/baseline-2026-10-07.json +``` + +The full harness includes cold/warm/offline and app.js, theme-glass.css and presenter.js edits. Run it without competing browsers/builds/tests. Re-running an old phase's own harness measures its own readiness boundary; use the Phase 5 harness for complete background-update comparisons. + +## Live checks after production is restored (owner executes) + +Set `origin` to the deployed URL; use curl only for public endpoints. Do not copy credentials into these commands. + +```bash +origin=https://worship.hesed.sbs +curl -fsS "$origin/api/version" +curl -fsS "$origin/" > /tmp/ytp-index.html +curl -fsS "$origin/index.html" > /tmp/ytp-index-route.html +curl -fsS "$origin/search" > /tmp/ytp-search.html +curl -fsS "$origin/playlist/x" > /tmp/ytp-playlist.html +cmp /tmp/ytp-index.html /tmp/ytp-index-route.html +cmp /tmp/ytp-index.html /tmp/ytp-search.html +cmp /tmp/ytp-index.html /tmp/ytp-playlist.html +curl -fsS "$origin/api/manifest" > /tmp/ytp-manifest.json +curl -fsS "$origin/sw.js" > /tmp/ytp-sw.js +``` + +Read the manifest's buildTag and /app.js h. Confirm buildTag equals /api/version, the index meta and injected worker BUILD_TAG; each index asset uses its own h. Request `/api/manifest` with `If-None-Match: ""`: expect 304 and no body; ordinary response must be no-store. Request `/app.js?v=`: expect 200, X-Asset-Hash equal h and `public, max-age=31536000, immutable`; request stale `?v=`: expect 200 with current body, correct X-Asset-Hash and no-store. Plain `/app.js` and `?__ytpfresh=probe` must still be 200. `/sw.js` must be no-store. Run these checks against the origin and public proxy to catch intermediary caching errors. + +Matching stamped SPA bodies alone does not prove nested-route asset resolution: open /playlist/x in a browser and inspect relative URLs/MIME types. This remains a documented hotspot, not a release success inferred from cmp. + +In a browser inspect CacheStorage: Phase 2+ uses ytplayer-assets with exact `/path?v=` entries and /__ytp_asset_state. Wait for verified blocking readiness before applying; background groups finish later. Keep a second old tab open, apply from the first while paused and confirm the second still opens its cached features. After one further update confirm only changed N-1 versions remain; do not manually delete caches to simulate success. + +## Rollback levers + +- `ASSET_HASHING=0`: set in the server/container environment and restart/recreate the service using the normal owner-approved deployment process. Restores legacy single-tag stamping/cache headers and automatically selects legacy sync. Verify index URLs use the single buildTag; per-file immutable/header expectations above no longer apply. This is available from Phase 1. +- `ASSET_SYNC=0`: available from Phase 2. Set and restart the server; hashing can stay on, but the served worker uses its legacy install/update path. Existing ytplayer-assets is a preserved utility cache. Legacy SHELL does not include piano-engine.mjs, so this emergency path does not promise every optional feature offline; verify the feature you need before disconnecting. With hashing enabled the changed sync setting changes buildTag; verify the new worker bytes and /api/version before applying the update from a paused page. +- Restore defaults by removing either variable or setting it to `1`, restart, verify the new build and apply through Refresh UI. Test either lever locally with `ASSET_SYNC=0 node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario offline --out perf/results/rollback-sync.json` (substitute ASSET_HASHING=0 for the other lever). +- **No generic lazy/chunk feature flag was implemented.** Roll back a Phase 3/4 regression by reverting the specific commit or restoring the last validated phase image with its matching frontend/server. Existing user feature settings are not loader rollback switches. A hashing/sync flag cannot undo a lazy-load interface change. + +Server flags do not mutate already-running JavaScript. They take effect on a newly installed worker/page through the normal user-initiated, playback-guarded update. No cache wipe, forced reload, auto-skipWaiting or stateful chunk re-evaluation is allowed. Executing feature instances stay pinned until session end or a guarded reload; live replacement requires disposal/state handoff before it can be enabled. + +## Manual iPhone gate (record model/iOS/network, build tags and observations) + +- Install from Safari; open the Home Screen app, verify the current meta/version and selected classic/nonclassic layout without a flash. +- Update from b77938a via its own Refresh UI; assert one banner and one reload after the tap, no automatic install/activate reload. Legacy pages do not report PLAYING and retain their existing post-tap timer limitation. Pause playback first on those pages. +- On a new page press Refresh UI during playback: see the explicit playing guard, no reload. Pause then apply; separately exercise the explicit override only when intentionally accepting playback interruption. Test the worker defers a reported-playing page's SKIP_WAITING. +- Allow idle warm on Wi-Fi and cellular (Save-Data off); open each uncommon feature the first time offline. Repeat with Save-Data on and confirm automatic warming is skipped; unprimed optional features are not promised offline. +- Pick Glass, Bento or F7, finish idle warm, enable Airplane Mode, force-close/reopen and reload; selected layout and saved audio/lyrics remain. Switch layouts offline, including classic. +- Play a saved playlist, record battery %, lock 30 minutes and listen for dropouts. Record drain, track transitions, lock-screen controls, sleep timer, interruption/Siri/call recovery and resume position. Verify audio-only and video playback. Linux WebKit cannot certify this. +- Check real-device storage estimate alongside existing OPFS music before/after updates; verify N-1 retention and quota pressure do not evict saved music. Repeat background audio with cellular/lossy transport and a pending update. Record failures rather than clearing storage to hide them. From af6aabc3b7fcc9e43ac8378dce55a0fdb3250506 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 08:27:08 +0800 Subject: [PATCH 44/81] Plan phase 6: diagnose and fix WebKit cold delivery --- plans/phase6-plan.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 plans/phase6-plan.md diff --git a/plans/phase6-plan.md b/plans/phase6-plan.md new file mode 100644 index 0000000..0a3b934 --- /dev/null +++ b/plans/phase6-plan.md @@ -0,0 +1,11 @@ +# Phase 6 plan + +Start from Phase 5 21c1273. Fix cold first-visit delivery only; preserve playback, banner, migration, exact hashes, contracts/pinning, offline and both rollback flags. + +1. Extend perf/baseline.mjs/proxy.mjs with page Resource Timing and complete request waterfalls, and a source-worktree option. Create detached historical worktrees beneath perf/.tmp for Phase 2, 3 and 5 tips. Run isolated WebKit/LTE cold measurements, >=3 runs each. Bisect Phase 3 commits with the same instrumented harness. Test head-loader/CSS discovery, fonts, worker start relative to FCP and immutable HTTP-cache behavior with controlled scratch variants. Record actual evidence in plans/phase6-investigation.md. +2. Add failing tests before each root fix. Likely files: frontend/index.html, lazy.js or a tiny layout bootstrap; frontend/sw.js and asset-sync-core.js only as evidence warrants. Keep the legacy install path and update all-or-nothing behavior intact; cache completed immutable responses safely without any unverifiable body. Preserve selected layout before paint and existing CSS cascade order. +3. Commit each fix separately with frontend and isolated Bun server suites green. Revert individual fixes for rollback; ASSET_HASHING=0/ASSET_SYNC=0 stay supported. Do not deploy or contact production. +4. Run final five-run WebKit cold LTE and lossy medians: FCP <= measured Phase 2 (targets ~1,300/3,800 ms); app.js positive-body responses exactly one; cold wire clearly below baseline. Measure Chromium and warm/offline/core-JS/CSS/feature updates against Phase 5, with repeated medians where regression risk exists. Rerun migration both engines with and without stalls, hidden timers, lazy/seam offline checks, rollback paths and all tests. +5. Self-review master sections 3.2/3.3/6/6b and full diff. Commit <=350-word plans/phase6-report.md with actual before/after table and explicit unmet targets; overwrite DONE06 signal and end. + +Risks: CSS cascade/no-flash preservation, duplicate requests crossing browser/worker HTTP-cache partitions, race between page handoff and install, timeout fallbacks delaying cache readiness, CPU contention invalidating timing. Historical worktrees/scratch data stay inside wt-assets; run benchmarks sequentially and preserve the invalid historical media fixture only for comparable home-launch metrics, not playback claims. From 799b1e7ed68fd5e55eb7faa9ed58ad633efbbbd2 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 08:45:00 +0800 Subject: [PATCH 45/81] Trace cold request waterfalls and isolate the layout discovery regression --- perf/README.md | 11 + perf/baseline.mjs | 20 +- perf/proxy.mjs | 6 +- perf/results/phase6-before-phase2.json | 8538 +++++++++++++++++ perf/results/phase6-before-phase3.json | 6846 +++++++++++++ perf/results/phase6-before-phase5.json | 7338 ++++++++++++++ perf/results/phase6-bisect-before-loader.json | 8538 +++++++++++++++++ perf/results/phase6-bisect-first-loader.json | 6742 +++++++++++++ perf/results/phase6-force-cache.json | 7338 ++++++++++++++ perf/results/phase6-preload-css.json | 7338 ++++++++++++++ perf/results/phase6-static-css.json | 7338 ++++++++++++++ plans/phase6-investigation.md | 53 + 12 files changed, 60098 insertions(+), 8 deletions(-) create mode 100644 perf/results/phase6-before-phase2.json create mode 100644 perf/results/phase6-before-phase3.json create mode 100644 perf/results/phase6-before-phase5.json create mode 100644 perf/results/phase6-bisect-before-loader.json create mode 100644 perf/results/phase6-bisect-first-loader.json create mode 100644 perf/results/phase6-force-cache.json create mode 100644 perf/results/phase6-preload-css.json create mode 100644 perf/results/phase6-static-css.json create mode 100644 plans/phase6-investigation.md diff --git a/perf/README.md b/perf/README.md index 0b64796..ee46ade 100644 --- a/perf/README.md +++ b/perf/README.md @@ -335,3 +335,14 @@ No product behavior changes are involved in these measurement corrections. Keep browser/build/test processes idle during full timing measurements. WebKit's zero long-task field means unavailable, not zero work. Autoplay-blocked/media-ready null results do not establish playback performance or iPhone audio continuity. + +### Cold waterfall diagnosis + +`--source-root perf/.tmp/` runs that worktree's matching +frontend **and server**; `--frontend-commit` instead combines archived frontend +with the current backend. Run historical comparisons sequentially to avoid CPU +contention. The result records `sourceCommit`, `sourceRoot` and the served build. +Every cold sample has `waterfalls`: proxy request order/start/headers/end times +and page Resource Timing discovery/start/end times. Proxy times start when +tracking begins; page times start at navigation. Compare within each clock, +then use the page FCP to locate the rendering dependency. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index ffc7704..3f64556 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -62,6 +62,7 @@ function parseArgs() { out: null, compare: null, frontendCommit: null, + sourceRoot: null, }; for (let i = 0; i < args.length; i++) { @@ -71,6 +72,7 @@ function parseArgs() { else if (a === '--profile' && i + 1 < args.length) options.profile = args[++i]; else if (a === '--scenario' && i + 1 < args.length) options.scenario = args[++i]; else if (a === '--out' && i + 1 < args.length) options.out = args[++i]; + else if (a === '--source-root' && i + 1 < args.length) options.sourceRoot = path.resolve(args[++i]); else if (a === '--frontend-commit' && i + 1 < args.length) options.frontendCommit = args[++i]; else if (a === '--compare' && i + 1 < args.length) options.compare = args[++i]; } @@ -151,7 +153,8 @@ async function seedDatabase(dbPath, mediaFiles) { * Bun Server Manager */ class ServerManager { - constructor(scratchDir, publicDir) { + constructor(scratchDir, publicDir, sourceRoot = REPO_ROOT) { + this.sourceRoot = sourceRoot; this.scratchDir = scratchDir; this.publicDir = publicDir; this.dataDir = path.join(scratchDir, 'data'); @@ -184,7 +187,7 @@ class ServerManager { DB_PATH: this.dbPath, }; - const serverScript = path.join(REPO_ROOT, 'server', 'server.js'); + const serverScript = path.join(this.sourceRoot, 'server', 'server.js'); this.serverProcess = spawn('bun', [serverScript], { cwd: srvCwd, env, @@ -373,7 +376,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) { return { initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -482,7 +485,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { return { initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -563,7 +566,7 @@ async function runOfflineScenario({ browserType, server, proxy, profile }) { return { initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize})), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -717,7 +720,7 @@ async function main() { const treeUpdateCss = path.join(tmpRoot, 'tree-update-css'); const treeUpdateFeature = path.join(tmpRoot, 'tree-update-feature'); - let frontendSource=path.join(REPO_ROOT,'frontend'); + let frontendSource=path.join(options.sourceRoot || REPO_ROOT,'frontend'); if(options.frontendCommit) { const archive=path.join(tmpRoot,'frontend.tar'); writeFileSync(archive,execFileSync('git',['archive',options.frontendCommit,'frontend'],{cwd:REPO_ROOT,maxBuffer:20*1024*1024})); @@ -735,13 +738,15 @@ async function main() { const trees = { treeBase, treeUpdateJs, treeUpdateCss, treeUpdateFeature }; const serverScratch = path.join(tmpRoot, 'server-run'); - const server = new ServerManager(serverScratch, treeBase); + const server = new ServerManager(serverScratch, treeBase, options.sourceRoot || REPO_ROOT); await server.start(); console.log(`Bun server running on ephemeral port ${server.port}`); const results = { date: new Date().toISOString(), frontendCommit: options.frontendCommit, + sourceRoot: options.sourceRoot, + sourceCommit: spawnSync('git', ['rev-parse','HEAD'], { cwd: options.sourceRoot || REPO_ROOT }).stdout.toString().trim(), frontendBuildTag: (await (await fetch('http://127.0.0.1:'+server.port+'/api/version')).json()).buildTag, commit: spawnSync('git', ['rev-parse', 'HEAD'], { cwd: REPO_ROOT }).stdout.toString().trim(), runsConfigured: options.runs, @@ -791,6 +796,7 @@ async function main() { requests: coldRuns[0]?.requests || [], initialJsCss: summarizeList(coldRuns.map(r=>r.initialJsCss)), initialAssetRequests: coldRuns[0]?.initialAssetRequests || [], + waterfalls: coldRuns.map(r=>({fcp:r.fcp,requests:r.requests,page:r.initialAssetRequests})), }; } diff --git a/perf/proxy.mjs b/perf/proxy.mjs index c185fe1..72a0714 100644 --- a/perf/proxy.mjs +++ b/perf/proxy.mjs @@ -47,6 +47,7 @@ export function categorizeContentType(contentType, urlPath) { */ export function createThrottleProxy({ targetPort, profile = 'lte' }) { let activeTracking = false; + let trackingStart = 0; let requestCount = 0; let requests = []; let totalWireBytes = 0; @@ -79,6 +80,7 @@ export function createThrottleProxy({ targetPort, profile = 'lte' }) { return; } + const requestStart = Date.now(); reqIndex++; const currentReqIndex = reqIndex; @@ -114,7 +116,8 @@ export function createThrottleProxy({ targetPort, profile = 'lte' }) { let recorded; if (activeTracking) { requestCount++; - recorded={url:clientReq.url,status:upRes.statusCode,bytes:0}; + recorded={url:clientReq.url,status:upRes.statusCode,bytes:0,index:currentReqIndex,startMs:requestStart-trackingStart,headersMs:Date.now()-trackingStart}; + clientRes.once('finish',()=>{recorded.endMs=Date.now()-trackingStart;}); requests.push(recorded); } @@ -176,6 +179,7 @@ export function createThrottleProxy({ targetPort, profile = 'lte' }) { server.close(resolve); }), startTracking: () => { + trackingStart = Date.now(); activeTracking = true; }, stopTracking: () => { diff --git a/perf/results/phase6-before-phase2.json b/perf/results/phase6-before-phase2.json new file mode 100644 index 0000000..000ff68 --- /dev/null +++ b/perf/results/phase6-before-phase2.json @@ -0,0 +1,8538 @@ +{ + "date": "2026-10-08T00:28:12.646Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-phase2", + "sourceCommit": "4950d3e41713c675290fd4b2bdf52580bcfdcc67", + "frontendBuildTag": "4f7090fff60c", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 171, + "min": 171, + "max": 171, + "values": [ + 171, + 171, + 171 + ] + }, + "wireBytes": { + "median": 1191063, + "min": 1191063, + "max": 1191063, + "values": [ + 1191063, + 1191063, + 1191063 + ] + }, + "fcp": { + "median": 1044, + "min": 1029, + "max": 1284, + "values": [ + 1284, + 1044, + 1029 + ] + }, + "lcp": { + "median": 1232, + "min": 1219, + "max": 1492, + "values": [ + 1492, + 1232, + 1219 + ] + }, + "domContentLoaded": { + "median": 3240, + "min": 3234, + "max": 4496, + "values": [ + 4496, + 3240, + 3234 + ] + }, + "bootDone": { + "median": 3263, + "min": 3262, + "max": 4508, + "values": [ + 4508, + 3263, + 3262 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 32432, + "min": 32432, + "max": 32884, + "values": [ + 32884, + 32432, + 32432 + ] + }, + "swInstallBytes": { + "median": 1191063, + "min": 1191063, + "max": 1191063, + "values": [ + 1191063, + 1191063, + 1191063 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 23000, + "js": 603160, + "css": 156688, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 3299, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5591/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 1, + "startMs": 17, + "headersMs": 225, + "endMs": 285 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 292, + "headersMs": 448, + "endMs": 26 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 293, + "headersMs": 449, + "endMs": -182 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 4, + "startMs": 293, + "headersMs": 452, + "endMs": 455 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 5, + "startMs": 294, + "headersMs": -177, + "endMs": -8 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 6, + "startMs": 294, + "headersMs": -160, + "endMs": -136 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 7, + "startMs": 295, + "headersMs": -134, + "endMs": -103 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 8, + "startMs": 456, + "headersMs": -102, + "endMs": -71 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 9, + "startMs": -181, + "headersMs": -8, + "endMs": 13 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": -135, + "headersMs": 20, + "endMs": 25 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": -102, + "headersMs": 55, + "endMs": 61 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 12, + "startMs": -69, + "headersMs": 86, + "endMs": 87 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 13, + "startMs": -5, + "headersMs": 149, + "endMs": 151 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 14, + "startMs": 14, + "headersMs": 167, + "endMs": 170 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 15, + "startMs": 26, + "headersMs": 180, + "endMs": 186 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 16, + "startMs": 27, + "headersMs": 182, + "endMs": 186 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 17, + "startMs": 62, + "headersMs": 222, + "endMs": 231 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 18, + "startMs": 88, + "headersMs": 244, + "endMs": 250 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 19, + "startMs": 152, + "headersMs": 312, + "endMs": 321 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 20, + "startMs": 170, + "headersMs": 324, + "endMs": 327 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 21, + "startMs": 186, + "headersMs": 340, + "endMs": 343 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 22, + "startMs": 187, + "headersMs": 379, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 23, + "startMs": 233, + "headersMs": 411, + "endMs": 439 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 24, + "startMs": 251, + "headersMs": 414, + "endMs": 421 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 25, + "startMs": 322, + "headersMs": 490, + "endMs": 513 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 26, + "startMs": 328, + "headersMs": 499, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 27, + "startMs": 343, + "headersMs": 509, + "endMs": 526 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 28, + "startMs": 418, + "headersMs": 573, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 29, + "startMs": 422, + "headersMs": 582, + "endMs": 595 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 30, + "startMs": 439, + "headersMs": 598, + "endMs": 606 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 31, + "startMs": 513, + "headersMs": 673, + "endMs": 687 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 32, + "startMs": 513, + "headersMs": 678, + "endMs": 687 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 33, + "startMs": 527, + "headersMs": 688, + "endMs": 703 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 34, + "startMs": 579, + "headersMs": 734, + "endMs": 742 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 35, + "startMs": 596, + "headersMs": 754, + "endMs": 765 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 36, + "startMs": 607, + "headersMs": 765, + "endMs": 772 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 37, + "startMs": 687, + "headersMs": 855, + "endMs": 878 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 38, + "startMs": 688, + "headersMs": 864, + "endMs": 870 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 39, + "startMs": 704, + "headersMs": 871, + "endMs": 884 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 40, + "startMs": 743, + "headersMs": 899, + "endMs": 904 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 41, + "startMs": 766, + "headersMs": 924, + "endMs": 933 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 42, + "startMs": 773, + "headersMs": 942, + "endMs": 968 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 43, + "startMs": 871, + "headersMs": 1025, + "endMs": 1028 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 44, + "startMs": 879, + "headersMs": 1033, + "endMs": 1037 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 45, + "startMs": 885, + "headersMs": 1051, + "endMs": 1066 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 46, + "startMs": 905, + "headersMs": 1069, + "endMs": 1084 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 47, + "startMs": 934, + "headersMs": 1090, + "endMs": 1097 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 48, + "startMs": 969, + "headersMs": 1125, + "endMs": 1134 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 49, + "startMs": 1029, + "headersMs": 1197, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 50, + "startMs": 1038, + "headersMs": 1199, + "endMs": 1204 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 51, + "startMs": 1067, + "headersMs": 1223, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 52, + "startMs": 1085, + "headersMs": 1245, + "endMs": 1255 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 53, + "startMs": 1098, + "headersMs": 1265, + "endMs": 1285 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 54, + "startMs": 1135, + "headersMs": 1288, + "endMs": 1293 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 55, + "startMs": 1204, + "headersMs": 1360, + "endMs": 1367 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 56, + "startMs": 1219, + "headersMs": 1382, + "endMs": 1399 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 57, + "startMs": 1229, + "headersMs": 1388, + "endMs": 1396 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 58, + "startMs": 1256, + "headersMs": 1423, + "endMs": 1447 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 59, + "startMs": 1286, + "headersMs": 1445, + "endMs": 1451 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 60, + "startMs": 1294, + "headersMs": 1450, + "endMs": 1457 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 61, + "startMs": 1367, + "headersMs": 1527, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 62, + "startMs": 1397, + "headersMs": 1556, + "endMs": 1566 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 63, + "startMs": 1400, + "headersMs": 1560, + "endMs": 1566 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 64, + "startMs": 1448, + "headersMs": 1605, + "endMs": 1612 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 65, + "startMs": 1451, + "headersMs": 1611, + "endMs": 1619 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 66, + "startMs": 1458, + "headersMs": 1617, + "endMs": 1622 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 67, + "startMs": 1541, + "headersMs": 1711, + "endMs": 1731 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 68, + "startMs": 1567, + "headersMs": 1729, + "endMs": 1744 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 69, + "startMs": 1567, + "headersMs": 1737, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 70, + "startMs": 1613, + "headersMs": 1766, + "endMs": 1768 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 71, + "startMs": 1620, + "headersMs": 1777, + "endMs": 1781 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 72, + "startMs": 1622, + "headersMs": 2759, + "endMs": 3583 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 1732, + "headersMs": 2759, + "endMs": 2917 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 74, + "startMs": 1745, + "headersMs": 2766, + "endMs": 2772 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 75, + "startMs": 3630, + "headersMs": 3783, + "endMs": 3785 + }, + { + "url": "http://127.0.0.1:5591/api/version", + "status": 200, + "bytes": 62, + "index": 76, + "startMs": 3694, + "headersMs": 3847, + "endMs": 3848 + }, + { + "url": "http://127.0.0.1:5591/api/user/sync", + "status": 200, + "bytes": 11, + "index": 77, + "startMs": 3696, + "headersMs": 3852, + "endMs": 3853 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 78, + "startMs": 3707, + "headersMs": 3884, + "endMs": 3925 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 79, + "startMs": 3855, + "headersMs": 4008, + "endMs": 4009 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 80, + "startMs": 3932, + "headersMs": 4084, + "endMs": 4092 + }, + { + "url": "http://127.0.0.1:5591/api/manifest", + "status": 200, + "bytes": 3178, + "index": 81, + "startMs": 4096, + "headersMs": 4260, + "endMs": 4277 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 82, + "startMs": 4310, + "headersMs": 4464, + "endMs": 5287 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 83, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4472 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 84, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4468 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 85, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4467 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 86, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4471 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 87, + "startMs": 4311, + "headersMs": 4464, + "endMs": 4467 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 88, + "startMs": 4469, + "headersMs": 4620, + "endMs": 4632 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 89, + "startMs": 4469, + "headersMs": 4621, + "endMs": 4627 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 90, + "startMs": 4470, + "headersMs": 4621, + "endMs": 4623 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 91, + "startMs": 4473, + "headersMs": 4623, + "endMs": 4645 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 92, + "startMs": 4476, + "headersMs": 4627, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:5591/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 93, + "startMs": 4625, + "headersMs": 4782, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 94, + "startMs": 4629, + "headersMs": 4782, + "endMs": 4789 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 95, + "startMs": 4633, + "headersMs": 4785, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 96, + "startMs": 4634, + "headersMs": 4785, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 97, + "startMs": 4647, + "headersMs": 4798, + "endMs": 4802 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 98, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4961 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 99, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4953 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 100, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 101, + "startMs": 4792, + "headersMs": 4942, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 102, + "startMs": 4804, + "headersMs": 4955, + "endMs": 4979 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 103, + "startMs": 4953, + "headersMs": 5104, + "endMs": 5110 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 104, + "startMs": 4954, + "headersMs": 5105, + "endMs": 5117 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 105, + "startMs": 4955, + "headersMs": 5105, + "endMs": 5261 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 106, + "startMs": 4962, + "headersMs": 5112, + "endMs": 5495 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 107, + "startMs": 4982, + "headersMs": 5133, + "endMs": 5232 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 108, + "startMs": 5113, + "headersMs": 5264, + "endMs": 5438 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 109, + "startMs": 5120, + "headersMs": 5271, + "endMs": 5330 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 110, + "startMs": 5234, + "headersMs": 5387, + "endMs": 5545 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 111, + "startMs": 5263, + "headersMs": 5415, + "endMs": 5524 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 112, + "startMs": 5293, + "headersMs": 5444, + "endMs": 5581 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 113, + "startMs": 5333, + "headersMs": 5485, + "endMs": 5487 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 114, + "startMs": 5441, + "headersMs": 5593, + "endMs": 5601 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 115, + "startMs": 5489, + "headersMs": 5640, + "endMs": 5655 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 116, + "startMs": 5498, + "headersMs": 5648, + "endMs": 5666 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 117, + "startMs": 5526, + "headersMs": 5677, + "endMs": 5682 + }, + { + "url": "http://127.0.0.1:5591/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 118, + "startMs": 5547, + "headersMs": 5700, + "endMs": 5703 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 119, + "startMs": 5583, + "headersMs": 5734, + "endMs": 5743 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 120, + "startMs": 5604, + "headersMs": 5755, + "endMs": 5779 + }, + { + "url": "http://127.0.0.1:5591/index.html?v=33e10c4b2d", + "status": 200, + "bytes": 11500, + "index": 121, + "startMs": 5657, + "headersMs": 5808, + "endMs": 5866 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 122, + "startMs": 5668, + "headersMs": 5819, + "endMs": 5826 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 123, + "startMs": 5684, + "headersMs": 5835, + "endMs": 5846 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 124, + "startMs": 5704, + "headersMs": 5856, + "endMs": 5859 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 125, + "startMs": 5745, + "headersMs": 5897, + "endMs": 5902 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 126, + "startMs": 5782, + "headersMs": 5935, + "endMs": 5951 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 127, + "startMs": 5828, + "headersMs": 5980, + "endMs": 5983 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 128, + "startMs": 5849, + "headersMs": 6001, + "endMs": 6013 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 129, + "startMs": 5861, + "headersMs": 6012, + "endMs": 6015 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 5868, + "headersMs": 6019, + "endMs": 6029 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 131, + "startMs": 5904, + "headersMs": 6056, + "endMs": 6062 + }, + { + "url": "http://127.0.0.1:5591/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 132, + "startMs": 5954, + "headersMs": 6118, + "endMs": 6138 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 133, + "startMs": 5985, + "headersMs": 6138, + "endMs": 6160 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 134, + "startMs": 6015, + "headersMs": 6167, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 135, + "startMs": 6017, + "headersMs": 6169, + "endMs": 6175 + }, + { + "url": "http://127.0.0.1:5591/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 136, + "startMs": 6031, + "headersMs": 6186, + "endMs": 6194 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 137, + "startMs": 6064, + "headersMs": 6215, + "endMs": 6229 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 138, + "startMs": 6141, + "headersMs": 6293, + "endMs": 6301 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 139, + "startMs": 6163, + "headersMs": 6314, + "endMs": 6319 + }, + { + "url": "http://127.0.0.1:5591/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 140, + "startMs": 6177, + "headersMs": 6329, + "endMs": 6342 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 141, + "startMs": 6191, + "headersMs": 6345, + "endMs": 6365 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 142, + "startMs": 6196, + "headersMs": 6346, + "endMs": 6350 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 143, + "startMs": 6231, + "headersMs": 6382, + "endMs": 6387 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 144, + "startMs": 6303, + "headersMs": 6455, + "endMs": 6485 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 145, + "startMs": 6321, + "headersMs": 6472, + "endMs": 6474 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 146, + "startMs": 6344, + "headersMs": 6496, + "endMs": 6500 + }, + { + "url": "http://127.0.0.1:5591/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 147, + "startMs": 6351, + "headersMs": 6504, + "endMs": 6508 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 148, + "startMs": 6367, + "headersMs": 6518, + "endMs": 6521 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 149, + "startMs": 6390, + "headersMs": 6541, + "endMs": 6545 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 150, + "startMs": 6476, + "headersMs": 6629, + "endMs": 6635 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 151, + "startMs": 6488, + "headersMs": 6638, + "endMs": 6661 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 152, + "startMs": 6502, + "headersMs": 6653, + "endMs": 6668 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 153, + "startMs": 6510, + "headersMs": 6661, + "endMs": 6666 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 154, + "startMs": 6523, + "headersMs": 6674, + "endMs": 6689 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 155, + "startMs": 6547, + "headersMs": 6698, + "endMs": 6706 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 156, + "startMs": 6637, + "headersMs": 6789, + "endMs": 6805 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 157, + "startMs": 6663, + "headersMs": 6815, + "endMs": 6829 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 158, + "startMs": 6668, + "headersMs": 6819, + "endMs": 6987 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 159, + "startMs": 6669, + "headersMs": 6820, + "endMs": 6845 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 160, + "startMs": 6691, + "headersMs": 6842, + "endMs": 6881 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 161, + "startMs": 6708, + "headersMs": 6860, + "endMs": 6881 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 162, + "startMs": 6807, + "headersMs": 6958, + "endMs": 6985 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 163, + "startMs": 6832, + "headersMs": 6985, + "endMs": 6993 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 164, + "startMs": 6847, + "headersMs": 6998, + "endMs": 7003 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 165, + "startMs": 6884, + "headersMs": 7037, + "endMs": 7068 + }, + { + "url": "http://127.0.0.1:5591/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 166, + "startMs": 6885, + "headersMs": 7236, + "endMs": 7461 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 167, + "startMs": 6987, + "headersMs": 7236, + "endMs": 7248 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 168, + "startMs": 6991, + "headersMs": 7239, + "endMs": 7241 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 169, + "startMs": 6995, + "headersMs": 7239, + "endMs": 7246 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 170, + "startMs": 7473, + "headersMs": 7627, + "endMs": 7668 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 171, + "startMs": 7671, + "headersMs": 7823, + "endMs": 7833 + } + ], + "initialJsCss": { + "median": 342400, + "min": 342400, + "max": 342400, + "values": [ + 342400, + 342400, + 342400 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 289, + "responseStart": 452, + "end": 453, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 290, + "responseStart": 667, + "end": 667, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 290, + "responseStart": 699, + "end": 700, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 290, + "responseStart": 732, + "end": 733, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 290, + "responseStart": 795, + "end": 796, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 290, + "responseStart": 816, + "end": 816, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "bytes": 983, + "start": 290, + "responseStart": 828, + "end": 828, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 290, + "responseStart": 864, + "end": 864, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 290, + "responseStart": 890, + "end": 891, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 291, + "responseStart": 954, + "end": 954, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 291, + "responseStart": 973, + "end": 973, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 291, + "responseStart": 988, + "end": 989, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 291, + "responseStart": 989, + "end": 989, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 291, + "responseStart": 1034, + "end": 1035, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 291, + "responseStart": 1053, + "end": 1053, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 291, + "responseStart": 1124, + "end": 1125, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 291, + "responseStart": 1130, + "end": 1130, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 291, + "responseStart": 1145, + "end": 1146, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 291, + "responseStart": 1220, + "end": 1220, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 292, + "responseStart": 1241, + "end": 1242, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 295, + "responseStart": 1224, + "end": 1224, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 295, + "responseStart": 1315, + "end": 1315, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 295, + "responseStart": 1316, + "end": 1316, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 295, + "responseStart": 1329, + "end": 1329, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 295, + "responseStart": 1380, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 295, + "responseStart": 1398, + "end": 1398, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 296, + "responseStart": 1409, + "end": 1409, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 296, + "responseStart": 1489, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 296, + "responseStart": 1490, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 296, + "responseStart": 1506, + "end": 1507, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 296, + "responseStart": 1544, + "end": 1545, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 296, + "responseStart": 1568, + "end": 1568, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 296, + "responseStart": 1575, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 296, + "responseStart": 1673, + "end": 1673, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 296, + "responseStart": 1680, + "end": 1681, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 296, + "responseStart": 1687, + "end": 1687, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 297, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "bytes": 1742, + "start": 297, + "responseStart": 1736, + "end": 1736, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 297, + "responseStart": 1771, + "end": 1772, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 297, + "responseStart": 1831, + "end": 1832, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 297, + "responseStart": 1840, + "end": 1841, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 297, + "responseStart": 1869, + "end": 1869, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 297, + "responseStart": 1887, + "end": 1887, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 297, + "responseStart": 1900, + "end": 1900, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 297, + "responseStart": 1936, + "end": 1937, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 297, + "responseStart": 2021, + "end": 2021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 298, + "responseStart": 2006, + "end": 2007, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 298, + "responseStart": 2031, + "end": 2031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 298, + "responseStart": 2058, + "end": 2058, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 298, + "responseStart": 2087, + "end": 2088, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 298, + "responseStart": 2096, + "end": 2097, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 298, + "responseStart": 2169, + "end": 2170, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 298, + "responseStart": 2199, + "end": 2199, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 298, + "responseStart": 2202, + "end": 2202, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 298, + "responseStart": 2249, + "end": 2250, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 298, + "responseStart": 2253, + "end": 2254, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 298, + "responseStart": 2260, + "end": 2261, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 299, + "responseStart": 2342, + "end": 2343, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 299, + "responseStart": 2369, + "end": 2369, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 299, + "responseStart": 2369, + "end": 2370, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 299, + "responseStart": 2415, + "end": 2415, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 299, + "responseStart": 2422, + "end": 2422, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 299, + "responseStart": 2425, + "end": 2425, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 299, + "responseStart": 2534, + "end": 2534, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 299, + "responseStart": 2547, + "end": 2548, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 300, + "responseStart": 2550, + "end": 2550, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 300, + "responseStart": 2571, + "end": 2571, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 300, + "responseStart": 2584, + "end": 2584, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "bytes": 164863, + "start": 300, + "responseStart": 3889, + "end": 4387, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1284, + "requests": [ + { + "url": "http://127.0.0.1:5591/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 1, + "startMs": 17, + "headersMs": 225, + "endMs": 285 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 292, + "headersMs": 448, + "endMs": 26 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 293, + "headersMs": 449, + "endMs": -182 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 4, + "startMs": 293, + "headersMs": 452, + "endMs": 455 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 5, + "startMs": 294, + "headersMs": -177, + "endMs": -8 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 6, + "startMs": 294, + "headersMs": -160, + "endMs": -136 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 7, + "startMs": 295, + "headersMs": -134, + "endMs": -103 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 8, + "startMs": 456, + "headersMs": -102, + "endMs": -71 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 9, + "startMs": -181, + "headersMs": -8, + "endMs": 13 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": -135, + "headersMs": 20, + "endMs": 25 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": -102, + "headersMs": 55, + "endMs": 61 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 12, + "startMs": -69, + "headersMs": 86, + "endMs": 87 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 13, + "startMs": -5, + "headersMs": 149, + "endMs": 151 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 14, + "startMs": 14, + "headersMs": 167, + "endMs": 170 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 15, + "startMs": 26, + "headersMs": 180, + "endMs": 186 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 16, + "startMs": 27, + "headersMs": 182, + "endMs": 186 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 17, + "startMs": 62, + "headersMs": 222, + "endMs": 231 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 18, + "startMs": 88, + "headersMs": 244, + "endMs": 250 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 19, + "startMs": 152, + "headersMs": 312, + "endMs": 321 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 20, + "startMs": 170, + "headersMs": 324, + "endMs": 327 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 21, + "startMs": 186, + "headersMs": 340, + "endMs": 343 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 22, + "startMs": 187, + "headersMs": 379, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 23, + "startMs": 233, + "headersMs": 411, + "endMs": 439 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 24, + "startMs": 251, + "headersMs": 414, + "endMs": 421 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 25, + "startMs": 322, + "headersMs": 490, + "endMs": 513 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 26, + "startMs": 328, + "headersMs": 499, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 27, + "startMs": 343, + "headersMs": 509, + "endMs": 526 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 28, + "startMs": 418, + "headersMs": 573, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 29, + "startMs": 422, + "headersMs": 582, + "endMs": 595 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 30, + "startMs": 439, + "headersMs": 598, + "endMs": 606 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 31, + "startMs": 513, + "headersMs": 673, + "endMs": 687 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 32, + "startMs": 513, + "headersMs": 678, + "endMs": 687 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 33, + "startMs": 527, + "headersMs": 688, + "endMs": 703 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 34, + "startMs": 579, + "headersMs": 734, + "endMs": 742 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 35, + "startMs": 596, + "headersMs": 754, + "endMs": 765 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 36, + "startMs": 607, + "headersMs": 765, + "endMs": 772 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 37, + "startMs": 687, + "headersMs": 855, + "endMs": 878 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 38, + "startMs": 688, + "headersMs": 864, + "endMs": 870 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 39, + "startMs": 704, + "headersMs": 871, + "endMs": 884 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 40, + "startMs": 743, + "headersMs": 899, + "endMs": 904 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 41, + "startMs": 766, + "headersMs": 924, + "endMs": 933 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 42, + "startMs": 773, + "headersMs": 942, + "endMs": 968 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 43, + "startMs": 871, + "headersMs": 1025, + "endMs": 1028 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 44, + "startMs": 879, + "headersMs": 1033, + "endMs": 1037 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 45, + "startMs": 885, + "headersMs": 1051, + "endMs": 1066 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 46, + "startMs": 905, + "headersMs": 1069, + "endMs": 1084 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 47, + "startMs": 934, + "headersMs": 1090, + "endMs": 1097 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 48, + "startMs": 969, + "headersMs": 1125, + "endMs": 1134 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 49, + "startMs": 1029, + "headersMs": 1197, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 50, + "startMs": 1038, + "headersMs": 1199, + "endMs": 1204 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 51, + "startMs": 1067, + "headersMs": 1223, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 52, + "startMs": 1085, + "headersMs": 1245, + "endMs": 1255 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 53, + "startMs": 1098, + "headersMs": 1265, + "endMs": 1285 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 54, + "startMs": 1135, + "headersMs": 1288, + "endMs": 1293 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 55, + "startMs": 1204, + "headersMs": 1360, + "endMs": 1367 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 56, + "startMs": 1219, + "headersMs": 1382, + "endMs": 1399 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 57, + "startMs": 1229, + "headersMs": 1388, + "endMs": 1396 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 58, + "startMs": 1256, + "headersMs": 1423, + "endMs": 1447 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 59, + "startMs": 1286, + "headersMs": 1445, + "endMs": 1451 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 60, + "startMs": 1294, + "headersMs": 1450, + "endMs": 1457 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 61, + "startMs": 1367, + "headersMs": 1527, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 62, + "startMs": 1397, + "headersMs": 1556, + "endMs": 1566 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 63, + "startMs": 1400, + "headersMs": 1560, + "endMs": 1566 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 64, + "startMs": 1448, + "headersMs": 1605, + "endMs": 1612 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 65, + "startMs": 1451, + "headersMs": 1611, + "endMs": 1619 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 66, + "startMs": 1458, + "headersMs": 1617, + "endMs": 1622 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 67, + "startMs": 1541, + "headersMs": 1711, + "endMs": 1731 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 68, + "startMs": 1567, + "headersMs": 1729, + "endMs": 1744 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 69, + "startMs": 1567, + "headersMs": 1737, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 70, + "startMs": 1613, + "headersMs": 1766, + "endMs": 1768 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 71, + "startMs": 1620, + "headersMs": 1777, + "endMs": 1781 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 72, + "startMs": 1622, + "headersMs": 2759, + "endMs": 3583 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 1732, + "headersMs": 2759, + "endMs": 2917 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 74, + "startMs": 1745, + "headersMs": 2766, + "endMs": 2772 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 75, + "startMs": 3630, + "headersMs": 3783, + "endMs": 3785 + }, + { + "url": "http://127.0.0.1:5591/api/version", + "status": 200, + "bytes": 62, + "index": 76, + "startMs": 3694, + "headersMs": 3847, + "endMs": 3848 + }, + { + "url": "http://127.0.0.1:5591/api/user/sync", + "status": 200, + "bytes": 11, + "index": 77, + "startMs": 3696, + "headersMs": 3852, + "endMs": 3853 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 78, + "startMs": 3707, + "headersMs": 3884, + "endMs": 3925 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 79, + "startMs": 3855, + "headersMs": 4008, + "endMs": 4009 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 80, + "startMs": 3932, + "headersMs": 4084, + "endMs": 4092 + }, + { + "url": "http://127.0.0.1:5591/api/manifest", + "status": 200, + "bytes": 3178, + "index": 81, + "startMs": 4096, + "headersMs": 4260, + "endMs": 4277 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 82, + "startMs": 4310, + "headersMs": 4464, + "endMs": 5287 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 83, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4472 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 84, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4468 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 85, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4467 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 86, + "startMs": 4310, + "headersMs": 4464, + "endMs": 4471 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 87, + "startMs": 4311, + "headersMs": 4464, + "endMs": 4467 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 88, + "startMs": 4469, + "headersMs": 4620, + "endMs": 4632 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 89, + "startMs": 4469, + "headersMs": 4621, + "endMs": 4627 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 90, + "startMs": 4470, + "headersMs": 4621, + "endMs": 4623 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 91, + "startMs": 4473, + "headersMs": 4623, + "endMs": 4645 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 92, + "startMs": 4476, + "headersMs": 4627, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:5591/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 93, + "startMs": 4625, + "headersMs": 4782, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 94, + "startMs": 4629, + "headersMs": 4782, + "endMs": 4789 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 95, + "startMs": 4633, + "headersMs": 4785, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 96, + "startMs": 4634, + "headersMs": 4785, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 97, + "startMs": 4647, + "headersMs": 4798, + "endMs": 4802 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 98, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4961 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 99, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4953 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 100, + "startMs": 4790, + "headersMs": 4942, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 101, + "startMs": 4792, + "headersMs": 4942, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 102, + "startMs": 4804, + "headersMs": 4955, + "endMs": 4979 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 103, + "startMs": 4953, + "headersMs": 5104, + "endMs": 5110 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 104, + "startMs": 4954, + "headersMs": 5105, + "endMs": 5117 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 105, + "startMs": 4955, + "headersMs": 5105, + "endMs": 5261 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 106, + "startMs": 4962, + "headersMs": 5112, + "endMs": 5495 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 107, + "startMs": 4982, + "headersMs": 5133, + "endMs": 5232 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 108, + "startMs": 5113, + "headersMs": 5264, + "endMs": 5438 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 109, + "startMs": 5120, + "headersMs": 5271, + "endMs": 5330 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 110, + "startMs": 5234, + "headersMs": 5387, + "endMs": 5545 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 111, + "startMs": 5263, + "headersMs": 5415, + "endMs": 5524 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 112, + "startMs": 5293, + "headersMs": 5444, + "endMs": 5581 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 113, + "startMs": 5333, + "headersMs": 5485, + "endMs": 5487 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 114, + "startMs": 5441, + "headersMs": 5593, + "endMs": 5601 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 115, + "startMs": 5489, + "headersMs": 5640, + "endMs": 5655 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 116, + "startMs": 5498, + "headersMs": 5648, + "endMs": 5666 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 117, + "startMs": 5526, + "headersMs": 5677, + "endMs": 5682 + }, + { + "url": "http://127.0.0.1:5591/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 118, + "startMs": 5547, + "headersMs": 5700, + "endMs": 5703 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 119, + "startMs": 5583, + "headersMs": 5734, + "endMs": 5743 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 120, + "startMs": 5604, + "headersMs": 5755, + "endMs": 5779 + }, + { + "url": "http://127.0.0.1:5591/index.html?v=33e10c4b2d", + "status": 200, + "bytes": 11500, + "index": 121, + "startMs": 5657, + "headersMs": 5808, + "endMs": 5866 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 122, + "startMs": 5668, + "headersMs": 5819, + "endMs": 5826 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 123, + "startMs": 5684, + "headersMs": 5835, + "endMs": 5846 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 124, + "startMs": 5704, + "headersMs": 5856, + "endMs": 5859 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 125, + "startMs": 5745, + "headersMs": 5897, + "endMs": 5902 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 126, + "startMs": 5782, + "headersMs": 5935, + "endMs": 5951 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 127, + "startMs": 5828, + "headersMs": 5980, + "endMs": 5983 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 128, + "startMs": 5849, + "headersMs": 6001, + "endMs": 6013 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 129, + "startMs": 5861, + "headersMs": 6012, + "endMs": 6015 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 5868, + "headersMs": 6019, + "endMs": 6029 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 131, + "startMs": 5904, + "headersMs": 6056, + "endMs": 6062 + }, + { + "url": "http://127.0.0.1:5591/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 132, + "startMs": 5954, + "headersMs": 6118, + "endMs": 6138 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 133, + "startMs": 5985, + "headersMs": 6138, + "endMs": 6160 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 134, + "startMs": 6015, + "headersMs": 6167, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 135, + "startMs": 6017, + "headersMs": 6169, + "endMs": 6175 + }, + { + "url": "http://127.0.0.1:5591/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 136, + "startMs": 6031, + "headersMs": 6186, + "endMs": 6194 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 137, + "startMs": 6064, + "headersMs": 6215, + "endMs": 6229 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 138, + "startMs": 6141, + "headersMs": 6293, + "endMs": 6301 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 139, + "startMs": 6163, + "headersMs": 6314, + "endMs": 6319 + }, + { + "url": "http://127.0.0.1:5591/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 140, + "startMs": 6177, + "headersMs": 6329, + "endMs": 6342 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 141, + "startMs": 6191, + "headersMs": 6345, + "endMs": 6365 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 142, + "startMs": 6196, + "headersMs": 6346, + "endMs": 6350 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 143, + "startMs": 6231, + "headersMs": 6382, + "endMs": 6387 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 144, + "startMs": 6303, + "headersMs": 6455, + "endMs": 6485 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 145, + "startMs": 6321, + "headersMs": 6472, + "endMs": 6474 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 146, + "startMs": 6344, + "headersMs": 6496, + "endMs": 6500 + }, + { + "url": "http://127.0.0.1:5591/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 147, + "startMs": 6351, + "headersMs": 6504, + "endMs": 6508 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 148, + "startMs": 6367, + "headersMs": 6518, + "endMs": 6521 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 149, + "startMs": 6390, + "headersMs": 6541, + "endMs": 6545 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 150, + "startMs": 6476, + "headersMs": 6629, + "endMs": 6635 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 151, + "startMs": 6488, + "headersMs": 6638, + "endMs": 6661 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 152, + "startMs": 6502, + "headersMs": 6653, + "endMs": 6668 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 153, + "startMs": 6510, + "headersMs": 6661, + "endMs": 6666 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 154, + "startMs": 6523, + "headersMs": 6674, + "endMs": 6689 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 155, + "startMs": 6547, + "headersMs": 6698, + "endMs": 6706 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 156, + "startMs": 6637, + "headersMs": 6789, + "endMs": 6805 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 157, + "startMs": 6663, + "headersMs": 6815, + "endMs": 6829 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 158, + "startMs": 6668, + "headersMs": 6819, + "endMs": 6987 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 159, + "startMs": 6669, + "headersMs": 6820, + "endMs": 6845 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 160, + "startMs": 6691, + "headersMs": 6842, + "endMs": 6881 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 161, + "startMs": 6708, + "headersMs": 6860, + "endMs": 6881 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 162, + "startMs": 6807, + "headersMs": 6958, + "endMs": 6985 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 163, + "startMs": 6832, + "headersMs": 6985, + "endMs": 6993 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 164, + "startMs": 6847, + "headersMs": 6998, + "endMs": 7003 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 165, + "startMs": 6884, + "headersMs": 7037, + "endMs": 7068 + }, + { + "url": "http://127.0.0.1:5591/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 166, + "startMs": 6885, + "headersMs": 7236, + "endMs": 7461 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 167, + "startMs": 6987, + "headersMs": 7236, + "endMs": 7248 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 168, + "startMs": 6991, + "headersMs": 7239, + "endMs": 7241 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 169, + "startMs": 6995, + "headersMs": 7239, + "endMs": 7246 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 170, + "startMs": 7473, + "headersMs": 7627, + "endMs": 7668 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 171, + "startMs": 7671, + "headersMs": 7823, + "endMs": 7833 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 289, + "responseStart": 452, + "end": 453, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 290, + "responseStart": 667, + "end": 667, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 290, + "responseStart": 699, + "end": 700, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 290, + "responseStart": 732, + "end": 733, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 290, + "responseStart": 795, + "end": 796, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 290, + "responseStart": 816, + "end": 816, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "bytes": 983, + "start": 290, + "responseStart": 828, + "end": 828, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 290, + "responseStart": 864, + "end": 864, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 290, + "responseStart": 890, + "end": 891, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 291, + "responseStart": 954, + "end": 954, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 291, + "responseStart": 973, + "end": 973, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 291, + "responseStart": 988, + "end": 989, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 291, + "responseStart": 989, + "end": 989, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 291, + "responseStart": 1034, + "end": 1035, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 291, + "responseStart": 1053, + "end": 1053, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 291, + "responseStart": 1124, + "end": 1125, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 291, + "responseStart": 1130, + "end": 1130, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 291, + "responseStart": 1145, + "end": 1146, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 291, + "responseStart": 1220, + "end": 1220, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 292, + "responseStart": 1241, + "end": 1242, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 295, + "responseStart": 1224, + "end": 1224, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 295, + "responseStart": 1315, + "end": 1315, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 295, + "responseStart": 1316, + "end": 1316, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 295, + "responseStart": 1329, + "end": 1329, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 295, + "responseStart": 1380, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 295, + "responseStart": 1398, + "end": 1398, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 296, + "responseStart": 1409, + "end": 1409, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 296, + "responseStart": 1489, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 296, + "responseStart": 1490, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 296, + "responseStart": 1506, + "end": 1507, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 296, + "responseStart": 1544, + "end": 1545, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 296, + "responseStart": 1568, + "end": 1568, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 296, + "responseStart": 1575, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 296, + "responseStart": 1673, + "end": 1673, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 296, + "responseStart": 1680, + "end": 1681, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 296, + "responseStart": 1687, + "end": 1687, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 297, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "bytes": 1742, + "start": 297, + "responseStart": 1736, + "end": 1736, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 297, + "responseStart": 1771, + "end": 1772, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 297, + "responseStart": 1831, + "end": 1832, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 297, + "responseStart": 1840, + "end": 1841, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 297, + "responseStart": 1869, + "end": 1869, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 297, + "responseStart": 1887, + "end": 1887, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 297, + "responseStart": 1900, + "end": 1900, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 297, + "responseStart": 1936, + "end": 1937, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 297, + "responseStart": 2021, + "end": 2021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 298, + "responseStart": 2006, + "end": 2007, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 298, + "responseStart": 2031, + "end": 2031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 298, + "responseStart": 2058, + "end": 2058, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 298, + "responseStart": 2087, + "end": 2088, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 298, + "responseStart": 2096, + "end": 2097, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 298, + "responseStart": 2169, + "end": 2170, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 298, + "responseStart": 2199, + "end": 2199, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 298, + "responseStart": 2202, + "end": 2202, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 298, + "responseStart": 2249, + "end": 2250, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 298, + "responseStart": 2253, + "end": 2254, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 298, + "responseStart": 2260, + "end": 2261, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 299, + "responseStart": 2342, + "end": 2343, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 299, + "responseStart": 2369, + "end": 2369, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 299, + "responseStart": 2369, + "end": 2370, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 299, + "responseStart": 2415, + "end": 2415, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 299, + "responseStart": 2422, + "end": 2422, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 299, + "responseStart": 2425, + "end": 2425, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 299, + "responseStart": 2534, + "end": 2534, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 299, + "responseStart": 2547, + "end": 2548, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 300, + "responseStart": 2550, + "end": 2550, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 300, + "responseStart": 2571, + "end": 2571, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 300, + "responseStart": 2584, + "end": 2584, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "bytes": 164863, + "start": 300, + "responseStart": 3889, + "end": 4387, + "initiator": "script" + } + ] + }, + { + "fcp": 1044, + "requests": [ + { + "url": "http://127.0.0.1:5591/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 172, + "startMs": 17, + "headersMs": 169, + "endMs": 227 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 173, + "startMs": 234, + "headersMs": 386, + "endMs": 388 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 174, + "startMs": 235, + "headersMs": 386, + "endMs": 771 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 175, + "startMs": 236, + "headersMs": 387, + "endMs": 556 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 176, + "startMs": 237, + "headersMs": 388, + "endMs": 411 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 177, + "startMs": 237, + "headersMs": 388, + "endMs": 418 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 178, + "startMs": 237, + "headersMs": 388, + "endMs": 420 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 179, + "startMs": 389, + "headersMs": 541, + "endMs": 561 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 180, + "startMs": 411, + "headersMs": 563, + "endMs": 567 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 181, + "startMs": 418, + "headersMs": 570, + "endMs": 575 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 182, + "startMs": 420, + "headersMs": 573, + "endMs": 575 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 183, + "startMs": 559, + "headersMs": 711, + "endMs": 713 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 184, + "startMs": 562, + "headersMs": 713, + "endMs": 715 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 185, + "startMs": 568, + "headersMs": 719, + "endMs": 724 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 186, + "startMs": 576, + "headersMs": 727, + "endMs": 730 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 187, + "startMs": 576, + "headersMs": 727, + "endMs": 735 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 188, + "startMs": 714, + "headersMs": 868, + "endMs": 874 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 189, + "startMs": 715, + "headersMs": 868, + "endMs": 876 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 190, + "startMs": 725, + "headersMs": 875, + "endMs": 877 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 191, + "startMs": 731, + "headersMs": 882, + "endMs": 884 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 192, + "startMs": 736, + "headersMs": 887, + "endMs": 925 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 193, + "startMs": 771, + "headersMs": 923, + "endMs": 952 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 194, + "startMs": 875, + "headersMs": 1027, + "endMs": 1034 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 195, + "startMs": 877, + "headersMs": 1027, + "endMs": 1050 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 196, + "startMs": 877, + "headersMs": 1031, + "endMs": 1043 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 197, + "startMs": 885, + "headersMs": 1036, + "endMs": 1051 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 198, + "startMs": 926, + "headersMs": 1078, + "endMs": 1081 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 199, + "startMs": 952, + "headersMs": 1105, + "endMs": 1118 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 200, + "startMs": 1035, + "headersMs": 1186, + "endMs": 1194 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 201, + "startMs": 1044, + "headersMs": 1195, + "endMs": 1209 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 202, + "startMs": 1051, + "headersMs": 1202, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 203, + "startMs": 1052, + "headersMs": 1205, + "endMs": 1220 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 204, + "startMs": 1082, + "headersMs": 1234, + "endMs": 1241 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 205, + "startMs": 1119, + "headersMs": 1270, + "endMs": 1281 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 206, + "startMs": 1195, + "headersMs": 1347, + "endMs": 1354 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 207, + "startMs": 1210, + "headersMs": 1361, + "endMs": 1384 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 208, + "startMs": 1210, + "headersMs": 1362, + "endMs": 1367 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 209, + "startMs": 1221, + "headersMs": 1373, + "endMs": 1386 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 210, + "startMs": 1242, + "headersMs": 1393, + "endMs": 1398 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 211, + "startMs": 1281, + "headersMs": 1432, + "endMs": 1444 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 212, + "startMs": 1355, + "headersMs": 1507, + "endMs": 1533 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 213, + "startMs": 1368, + "headersMs": 1519, + "endMs": 1523 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 214, + "startMs": 1385, + "headersMs": 1536, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 215, + "startMs": 1387, + "headersMs": 1538, + "endMs": 1552 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 216, + "startMs": 1399, + "headersMs": 1551, + "endMs": 1567 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 217, + "startMs": 1445, + "headersMs": 1596, + "endMs": 1603 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 218, + "startMs": 1523, + "headersMs": 1674, + "endMs": 1681 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 219, + "startMs": 1534, + "headersMs": 1684, + "endMs": 1706 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 220, + "startMs": 1540, + "headersMs": 1694, + "endMs": 1697 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 221, + "startMs": 1553, + "headersMs": 1704, + "endMs": 1709 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 222, + "startMs": 1568, + "headersMs": 1720, + "endMs": 1731 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 223, + "startMs": 1603, + "headersMs": 1755, + "endMs": 1774 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 224, + "startMs": 1682, + "headersMs": 1834, + "endMs": 1839 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 225, + "startMs": 1698, + "headersMs": 1849, + "endMs": 1855 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 226, + "startMs": 1707, + "headersMs": 1858, + "endMs": 1874 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 227, + "startMs": 1709, + "headersMs": 1860, + "endMs": 1868 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 228, + "startMs": 1731, + "headersMs": 1885, + "endMs": 1908 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 229, + "startMs": 1775, + "headersMs": 1926, + "endMs": 1931 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 230, + "startMs": 1840, + "headersMs": 1991, + "endMs": 1998 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 231, + "startMs": 1855, + "headersMs": 2009, + "endMs": 2023 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 232, + "startMs": 1869, + "headersMs": 2020, + "endMs": 2030 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 233, + "startMs": 1875, + "headersMs": 2027, + "endMs": 2033 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 234, + "startMs": 1909, + "headersMs": 2061, + "endMs": 2068 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 235, + "startMs": 1932, + "headersMs": 2085, + "endMs": 2093 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 236, + "startMs": 1999, + "headersMs": 2150, + "endMs": 2156 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 237, + "startMs": 2023, + "headersMs": 2175, + "endMs": 2195 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 238, + "startMs": 2031, + "headersMs": 2182, + "endMs": 2197 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 239, + "startMs": 2034, + "headersMs": 2185, + "endMs": 2195 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 240, + "startMs": 2068, + "headersMs": 2221, + "endMs": 2223 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 241, + "startMs": 2094, + "headersMs": 2245, + "endMs": 2249 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 242, + "startMs": 2157, + "headersMs": 2308, + "endMs": 3132 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 243, + "startMs": 2197, + "headersMs": 2348, + "endMs": 2523 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 244, + "startMs": 2197, + "headersMs": 2349, + "endMs": 2507 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 245, + "startMs": 2198, + "headersMs": 2349, + "endMs": 2352 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 246, + "startMs": 3177, + "headersMs": 3329, + "endMs": 3330 + }, + { + "url": "http://127.0.0.1:5591/api/version", + "status": 200, + "bytes": 62, + "index": 247, + "startMs": 3243, + "headersMs": 3394, + "endMs": 3395 + }, + { + "url": "http://127.0.0.1:5591/api/user/sync", + "status": 200, + "bytes": 11, + "index": 248, + "startMs": 3244, + "headersMs": 3396, + "endMs": 3398 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 249, + "startMs": 3268, + "headersMs": 3420, + "endMs": 3460 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 250, + "startMs": 3400, + "headersMs": 3553, + "endMs": 3555 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 251, + "startMs": 3470, + "headersMs": 3622, + "endMs": 3630 + }, + { + "url": "http://127.0.0.1:5591/api/manifest", + "status": 200, + "bytes": 3178, + "index": 252, + "startMs": 3634, + "headersMs": 3787, + "endMs": 3802 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 253, + "startMs": 3834, + "headersMs": 3986, + "endMs": 4811 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 254, + "startMs": 3834, + "headersMs": 3987, + "endMs": 3995 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 255, + "startMs": 3834, + "headersMs": 3987, + "endMs": 3991 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 256, + "startMs": 3834, + "headersMs": 3987, + "endMs": 3990 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 257, + "startMs": 3834, + "headersMs": 3987, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 258, + "startMs": 3834, + "headersMs": 3988, + "endMs": 3990 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 259, + "startMs": 3993, + "headersMs": 4145, + "endMs": 4155 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 260, + "startMs": 3993, + "headersMs": 4145, + "endMs": 4152 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 261, + "startMs": 3994, + "headersMs": 4146, + "endMs": 4148 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 262, + "startMs": 3996, + "headersMs": 4146, + "endMs": 4168 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 263, + "startMs": 3996, + "headersMs": 4146, + "endMs": 4152 + }, + { + "url": "http://127.0.0.1:5591/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 264, + "startMs": 4150, + "headersMs": 4301, + "endMs": 4306 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 265, + "startMs": 4154, + "headersMs": 4306, + "endMs": 4313 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 266, + "startMs": 4154, + "headersMs": 4306, + "endMs": 4308 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 267, + "startMs": 4157, + "headersMs": 4308, + "endMs": 4312 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 268, + "startMs": 4170, + "headersMs": 4322, + "endMs": 4326 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 269, + "startMs": 4308, + "headersMs": 4460, + "endMs": 4478 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 270, + "startMs": 4309, + "headersMs": 4460, + "endMs": 4470 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 271, + "startMs": 4314, + "headersMs": 4466, + "endMs": 4473 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 272, + "startMs": 4315, + "headersMs": 4466, + "endMs": 4473 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 273, + "startMs": 4328, + "headersMs": 4479, + "endMs": 4503 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 274, + "startMs": 4473, + "headersMs": 4625, + "endMs": 4632 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 275, + "startMs": 4474, + "headersMs": 4626, + "endMs": 4638 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 276, + "startMs": 4475, + "headersMs": 4626, + "endMs": 4780 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 277, + "startMs": 4480, + "headersMs": 4631, + "endMs": 5016 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 278, + "startMs": 4506, + "headersMs": 4657, + "endMs": 4756 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 279, + "startMs": 4637, + "headersMs": 4789, + "endMs": 4962 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 280, + "startMs": 4640, + "headersMs": 4792, + "endMs": 4851 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 281, + "startMs": 4758, + "headersMs": 4910, + "endMs": 5067 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 282, + "startMs": 4782, + "headersMs": 4933, + "endMs": 5043 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 283, + "startMs": 4817, + "headersMs": 4968, + "endMs": 5105 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 284, + "startMs": 4853, + "headersMs": 5005, + "endMs": 5007 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 285, + "startMs": 4964, + "headersMs": 5115, + "endMs": 5124 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 286, + "startMs": 5009, + "headersMs": 5160, + "endMs": 5175 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 287, + "startMs": 5019, + "headersMs": 5170, + "endMs": 5186 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 288, + "startMs": 5046, + "headersMs": 5198, + "endMs": 5203 + }, + { + "url": "http://127.0.0.1:5591/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 289, + "startMs": 5069, + "headersMs": 5221, + "endMs": 5223 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 290, + "startMs": 5108, + "headersMs": 5260, + "endMs": 5269 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 291, + "startMs": 5126, + "headersMs": 5276, + "endMs": 5300 + }, + { + "url": "http://127.0.0.1:5591/index.html?v=33e10c4b2d", + "status": 200, + "bytes": 11500, + "index": 292, + "startMs": 5177, + "headersMs": 5328, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 293, + "startMs": 5189, + "headersMs": 5340, + "endMs": 5347 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 294, + "startMs": 5205, + "headersMs": 5356, + "endMs": 5366 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 295, + "startMs": 5225, + "headersMs": 5377, + "endMs": 5379 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 296, + "startMs": 5271, + "headersMs": 5422, + "endMs": 5428 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 297, + "startMs": 5302, + "headersMs": 5454, + "endMs": 5470 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 298, + "startMs": 5349, + "headersMs": 5502, + "endMs": 5506 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 299, + "startMs": 5369, + "headersMs": 5521, + "endMs": 5533 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 300, + "startMs": 5381, + "headersMs": 5532, + "endMs": 5536 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 301, + "startMs": 5389, + "headersMs": 5540, + "endMs": 5551 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 302, + "startMs": 5430, + "headersMs": 5580, + "endMs": 5586 + }, + { + "url": "http://127.0.0.1:5591/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 303, + "startMs": 5472, + "headersMs": 5623, + "endMs": 5643 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 304, + "startMs": 5508, + "headersMs": 5659, + "endMs": 5682 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 305, + "startMs": 5535, + "headersMs": 5687, + "endMs": 5710 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 306, + "startMs": 5537, + "headersMs": 5688, + "endMs": 5693 + }, + { + "url": "http://127.0.0.1:5591/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 307, + "startMs": 5552, + "headersMs": 5704, + "endMs": 5712 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 308, + "startMs": 5588, + "headersMs": 5739, + "endMs": 5753 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 309, + "startMs": 5646, + "headersMs": 5798, + "endMs": 5806 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 310, + "startMs": 5686, + "headersMs": 5838, + "endMs": 5843 + }, + { + "url": "http://127.0.0.1:5591/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 311, + "startMs": 5695, + "headersMs": 5846, + "endMs": 5859 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 312, + "startMs": 5712, + "headersMs": 5866, + "endMs": 5886 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 313, + "startMs": 5714, + "headersMs": 5866, + "endMs": 5869 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 314, + "startMs": 5755, + "headersMs": 5906, + "endMs": 5911 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 315, + "startMs": 5808, + "headersMs": 5960, + "endMs": 5990 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 316, + "startMs": 5846, + "headersMs": 5996, + "endMs": 5999 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 317, + "startMs": 5861, + "headersMs": 6012, + "endMs": 6016 + }, + { + "url": "http://127.0.0.1:5591/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 318, + "startMs": 5871, + "headersMs": 6022, + "endMs": 6027 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 319, + "startMs": 5888, + "headersMs": 6039, + "endMs": 6042 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 320, + "startMs": 5913, + "headersMs": 6064, + "endMs": 6069 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 321, + "startMs": 5992, + "headersMs": 6146, + "endMs": 6152 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 322, + "startMs": 6000, + "headersMs": 6152, + "endMs": 6175 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 323, + "startMs": 6017, + "headersMs": 6169, + "endMs": 6183 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 324, + "startMs": 6029, + "headersMs": 6181, + "endMs": 6186 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 325, + "startMs": 6044, + "headersMs": 6197, + "endMs": 6212 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 326, + "startMs": 6071, + "headersMs": 6222, + "endMs": 6230 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 327, + "startMs": 6154, + "headersMs": 6305, + "endMs": 6321 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 328, + "startMs": 6177, + "headersMs": 6329, + "endMs": 6343 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 329, + "startMs": 6185, + "headersMs": 6337, + "endMs": 6504 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 330, + "startMs": 6187, + "headersMs": 6337, + "endMs": 6362 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 331, + "startMs": 6215, + "headersMs": 6366, + "endMs": 6404 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 332, + "startMs": 6231, + "headersMs": 6383, + "endMs": 6404 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 333, + "startMs": 6324, + "headersMs": 6476, + "endMs": 6503 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 334, + "startMs": 6345, + "headersMs": 6496, + "endMs": 6505 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 335, + "startMs": 6365, + "headersMs": 6516, + "endMs": 6522 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 336, + "startMs": 6407, + "headersMs": 6560, + "endMs": 6591 + }, + { + "url": "http://127.0.0.1:5591/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 337, + "startMs": 6407, + "headersMs": 6560, + "endMs": 6784 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 338, + "startMs": 6506, + "headersMs": 6657, + "endMs": 6669 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 339, + "startMs": 6507, + "headersMs": 6657, + "endMs": 6659 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 340, + "startMs": 6508, + "headersMs": 6659, + "endMs": 6665 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 341, + "startMs": 6795, + "headersMs": 6947, + "endMs": 6988 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 342, + "startMs": 6990, + "headersMs": 7142, + "endMs": 7150 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 231, + "responseStart": 385, + "end": 386, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 232, + "responseStart": 408, + "end": 408, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 232, + "responseStart": 415, + "end": 415, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 232, + "responseStart": 417, + "end": 417, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 232, + "responseStart": 554, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 232, + "responseStart": 558, + "end": 559, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "bytes": 983, + "start": 232, + "responseStart": 565, + "end": 565, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 232, + "responseStart": 572, + "end": 572, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 232, + "responseStart": 572, + "end": 573, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 233, + "responseStart": 710, + "end": 711, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 233, + "responseStart": 712, + "end": 712, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 233, + "responseStart": 722, + "end": 722, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 233, + "responseStart": 728, + "end": 728, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 233, + "responseStart": 732, + "end": 733, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 233, + "responseStart": 871, + "end": 871, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 233, + "responseStart": 873, + "end": 873, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 233, + "responseStart": 874, + "end": 874, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 234, + "responseStart": 882, + "end": 882, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 234, + "responseStart": 922, + "end": 923, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 234, + "responseStart": 949, + "end": 949, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 238, + "responseStart": 1031, + "end": 1031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 238, + "responseStart": 1040, + "end": 1040, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 238, + "responseStart": 1047, + "end": 1048, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 239, + "responseStart": 1048, + "end": 1049, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 239, + "responseStart": 1079, + "end": 1079, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 239, + "responseStart": 1115, + "end": 1116, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 239, + "responseStart": 1191, + "end": 1192, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 239, + "responseStart": 1206, + "end": 1206, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 239, + "responseStart": 1207, + "end": 1207, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 239, + "responseStart": 1218, + "end": 1218, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 239, + "responseStart": 1238, + "end": 1239, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 239, + "responseStart": 1277, + "end": 1278, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 239, + "responseStart": 1351, + "end": 1351, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 240, + "responseStart": 1364, + "end": 1365, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 240, + "responseStart": 1381, + "end": 1382, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 240, + "responseStart": 1383, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 240, + "responseStart": 1395, + "end": 1396, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "bytes": 1742, + "start": 240, + "responseStart": 1441, + "end": 1442, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 240, + "responseStart": 1520, + "end": 1520, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 240, + "responseStart": 1530, + "end": 1531, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 240, + "responseStart": 1537, + "end": 1537, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 240, + "responseStart": 1549, + "end": 1550, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 240, + "responseStart": 1564, + "end": 1565, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 241, + "responseStart": 1600, + "end": 1600, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 241, + "responseStart": 1679, + "end": 1679, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 241, + "responseStart": 1694, + "end": 1694, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 241, + "responseStart": 1703, + "end": 1704, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 241, + "responseStart": 1706, + "end": 1706, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 241, + "responseStart": 1728, + "end": 1728, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 241, + "responseStart": 1771, + "end": 1772, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 241, + "responseStart": 1836, + "end": 1836, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 241, + "responseStart": 1852, + "end": 1852, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 241, + "responseStart": 1871, + "end": 1872, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 242, + "responseStart": 1865, + "end": 1866, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 242, + "responseStart": 1905, + "end": 1906, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 242, + "responseStart": 1929, + "end": 1929, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 242, + "responseStart": 1996, + "end": 1996, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 242, + "responseStart": 2020, + "end": 2020, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 242, + "responseStart": 2027, + "end": 2028, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 242, + "responseStart": 2031, + "end": 2031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 242, + "responseStart": 2065, + "end": 2065, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 242, + "responseStart": 2090, + "end": 2090, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 243, + "responseStart": 2153, + "end": 2154, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 243, + "responseStart": 2193, + "end": 2193, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 243, + "responseStart": 2192, + "end": 2194, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 243, + "responseStart": 2194, + "end": 2194, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 243, + "responseStart": 2221, + "end": 2221, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 243, + "responseStart": 2246, + "end": 2246, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "bytes": 164863, + "start": 243, + "responseStart": 2621, + "end": 3130, + "initiator": "script" + } + ] + }, + { + "fcp": 1029, + "requests": [ + { + "url": "http://127.0.0.1:5591/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 343, + "startMs": 18, + "headersMs": 170, + "endMs": 227 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 344, + "startMs": 235, + "headersMs": 386, + "endMs": 389 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 345, + "startMs": 235, + "headersMs": 387, + "endMs": 770 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 346, + "startMs": 236, + "headersMs": 388, + "endMs": 555 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 347, + "startMs": 237, + "headersMs": 388, + "endMs": 411 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 348, + "startMs": 238, + "headersMs": 389, + "endMs": 418 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 349, + "startMs": 238, + "headersMs": 389, + "endMs": 418 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 350, + "startMs": 390, + "headersMs": 543, + "endMs": 563 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 351, + "startMs": 412, + "headersMs": 563, + "endMs": 567 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 352, + "startMs": 418, + "headersMs": 570, + "endMs": 575 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 353, + "startMs": 419, + "headersMs": 570, + "endMs": 571 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 354, + "startMs": 558, + "headersMs": 711, + "endMs": 714 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 355, + "startMs": 563, + "headersMs": 714, + "endMs": 717 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 356, + "startMs": 567, + "headersMs": 718, + "endMs": 722 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 357, + "startMs": 572, + "headersMs": 722, + "endMs": 724 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 358, + "startMs": 576, + "headersMs": 728, + "endMs": 737 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 359, + "startMs": 714, + "headersMs": 866, + "endMs": 872 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 360, + "startMs": 717, + "headersMs": 868, + "endMs": 876 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 361, + "startMs": 723, + "headersMs": 873, + "endMs": 876 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 362, + "startMs": 725, + "headersMs": 875, + "endMs": 876 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 363, + "startMs": 738, + "headersMs": 888, + "endMs": 927 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 364, + "startMs": 771, + "headersMs": 922, + "endMs": 950 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 365, + "startMs": 873, + "headersMs": 1024, + "endMs": 1030 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 366, + "startMs": 878, + "headersMs": 1028, + "endMs": 1051 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 367, + "startMs": 878, + "headersMs": 1028, + "endMs": 1042 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 368, + "startMs": 878, + "headersMs": 1029, + "endMs": 1044 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 369, + "startMs": 928, + "headersMs": 1079, + "endMs": 1083 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 370, + "startMs": 951, + "headersMs": 1103, + "endMs": 1115 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 371, + "startMs": 1032, + "headersMs": 1184, + "endMs": 1192 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 372, + "startMs": 1042, + "headersMs": 1193, + "endMs": 1206 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 373, + "startMs": 1044, + "headersMs": 1195, + "endMs": 1203 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 374, + "startMs": 1052, + "headersMs": 1204, + "endMs": 1219 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 375, + "startMs": 1084, + "headersMs": 1236, + "endMs": 1244 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 376, + "startMs": 1115, + "headersMs": 1267, + "endMs": 1278 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 377, + "startMs": 1193, + "headersMs": 1345, + "endMs": 1350 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 378, + "startMs": 1204, + "headersMs": 1356, + "endMs": 1379 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 379, + "startMs": 1207, + "headersMs": 1358, + "endMs": 1363 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 380, + "startMs": 1220, + "headersMs": 1371, + "endMs": 1386 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 381, + "startMs": 1244, + "headersMs": 1395, + "endMs": 1400 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 382, + "startMs": 1279, + "headersMs": 1431, + "endMs": 1439 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 383, + "startMs": 1351, + "headersMs": 1503, + "endMs": 1529 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 384, + "startMs": 1364, + "headersMs": 1515, + "endMs": 1519 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 385, + "startMs": 1380, + "headersMs": 1532, + "endMs": 1535 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 386, + "startMs": 1386, + "headersMs": 1538, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 387, + "startMs": 1401, + "headersMs": 1554, + "endMs": 1569 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 388, + "startMs": 1440, + "headersMs": 1591, + "endMs": 1598 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 389, + "startMs": 1520, + "headersMs": 1671, + "endMs": 1679 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 390, + "startMs": 1530, + "headersMs": 1681, + "endMs": 1703 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 391, + "startMs": 1536, + "headersMs": 1686, + "endMs": 1690 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 392, + "startMs": 1554, + "headersMs": 1705, + "endMs": 1710 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 393, + "startMs": 1570, + "headersMs": 1722, + "endMs": 1733 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 394, + "startMs": 1599, + "headersMs": 1750, + "endMs": 1771 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 395, + "startMs": 1680, + "headersMs": 1832, + "endMs": 1837 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 396, + "startMs": 1691, + "headersMs": 1841, + "endMs": 1847 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 397, + "startMs": 1705, + "headersMs": 1858, + "endMs": 1875 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 398, + "startMs": 1711, + "headersMs": 1861, + "endMs": 1869 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 399, + "startMs": 1734, + "headersMs": 1886, + "endMs": 1909 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 400, + "startMs": 1772, + "headersMs": 1925, + "endMs": 1931 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 401, + "startMs": 1838, + "headersMs": 1991, + "endMs": 1998 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 402, + "startMs": 1848, + "headersMs": 1998, + "endMs": 2011 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 403, + "startMs": 1869, + "headersMs": 2021, + "endMs": 2032 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 404, + "startMs": 1876, + "headersMs": 2026, + "endMs": 2032 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 405, + "startMs": 1910, + "headersMs": 2061, + "endMs": 2067 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 406, + "startMs": 1931, + "headersMs": 2084, + "endMs": 2091 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 407, + "startMs": 1999, + "headersMs": 2150, + "endMs": 2154 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 408, + "startMs": 2011, + "headersMs": 2163, + "endMs": 2183 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 409, + "startMs": 2033, + "headersMs": 2184, + "endMs": 2199 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 410, + "startMs": 2034, + "headersMs": 2185, + "endMs": 2195 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 411, + "startMs": 2068, + "headersMs": 2221, + "endMs": 2222 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 2092, + "headersMs": 2244, + "endMs": 2249 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 413, + "startMs": 2155, + "headersMs": 2308, + "endMs": 3133 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 414, + "startMs": 2184, + "headersMs": 2334, + "endMs": 2508 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 415, + "startMs": 2197, + "headersMs": 2348, + "endMs": 2506 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 416, + "startMs": 2200, + "headersMs": 2350, + "endMs": 2354 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 417, + "startMs": 3182, + "headersMs": 3334, + "endMs": 3336 + }, + { + "url": "http://127.0.0.1:5591/api/version", + "status": 200, + "bytes": 62, + "index": 418, + "startMs": 3252, + "headersMs": 3403, + "endMs": 3404 + }, + { + "url": "http://127.0.0.1:5591/api/user/sync", + "status": 200, + "bytes": 11, + "index": 419, + "startMs": 3253, + "headersMs": 3404, + "endMs": 3405 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 420, + "startMs": 3281, + "headersMs": 3432, + "endMs": 3473 + }, + { + "url": "http://127.0.0.1:5591/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 421, + "startMs": 3408, + "headersMs": 3559, + "endMs": 3561 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 422, + "startMs": 3480, + "headersMs": 3631, + "endMs": 3640 + }, + { + "url": "http://127.0.0.1:5591/api/manifest", + "status": 200, + "bytes": 3178, + "index": 423, + "startMs": 3645, + "headersMs": 3797, + "endMs": 3813 + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 424, + "startMs": 3844, + "headersMs": 3996, + "endMs": 4821 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 425, + "startMs": 3844, + "headersMs": 3996, + "endMs": 4005 + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 426, + "startMs": 3844, + "headersMs": 3996, + "endMs": 4000 + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 427, + "startMs": 3844, + "headersMs": 3996, + "endMs": 3999 + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 428, + "startMs": 3845, + "headersMs": 3996, + "endMs": 4003 + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 429, + "startMs": 3845, + "headersMs": 3997, + "endMs": 3999 + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 430, + "startMs": 4002, + "headersMs": 4152, + "endMs": 4162 + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 431, + "startMs": 4002, + "headersMs": 4153, + "endMs": 4158 + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 432, + "startMs": 4002, + "headersMs": 4153, + "endMs": 4154 + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 433, + "startMs": 4005, + "headersMs": 4154, + "endMs": 4176 + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 434, + "startMs": 4006, + "headersMs": 4157, + "endMs": 4164 + }, + { + "url": "http://127.0.0.1:5591/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 435, + "startMs": 4156, + "headersMs": 4309, + "endMs": 4315 + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 436, + "startMs": 4160, + "headersMs": 4311, + "endMs": 4319 + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 437, + "startMs": 4164, + "headersMs": 4316, + "endMs": 4317 + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 438, + "startMs": 4165, + "headersMs": 4316, + "endMs": 4319 + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 439, + "startMs": 4180, + "headersMs": 4333, + "endMs": 4336 + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 440, + "startMs": 4317, + "headersMs": 4470, + "endMs": 4489 + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 441, + "startMs": 4319, + "headersMs": 4471, + "endMs": 4481 + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 442, + "startMs": 4320, + "headersMs": 4471, + "endMs": 4477 + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 443, + "startMs": 4320, + "headersMs": 4471, + "endMs": 4477 + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 444, + "startMs": 4338, + "headersMs": 4490, + "endMs": 4513 + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 445, + "startMs": 4480, + "headersMs": 4630, + "endMs": 4637 + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 446, + "startMs": 4480, + "headersMs": 4631, + "endMs": 4642 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 447, + "startMs": 4483, + "headersMs": 4635, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:5591/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 448, + "startMs": 4491, + "headersMs": 4642, + "endMs": 5026 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 449, + "startMs": 4516, + "headersMs": 4668, + "endMs": 4766 + }, + { + "url": "http://127.0.0.1:5591/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 450, + "startMs": 4640, + "headersMs": 4791, + "endMs": 4964 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 451, + "startMs": 4644, + "headersMs": 4794, + "endMs": 4854 + }, + { + "url": "http://127.0.0.1:5591/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 452, + "startMs": 4769, + "headersMs": 4921, + "endMs": 5078 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 453, + "startMs": 4790, + "headersMs": 4941, + "endMs": 5050 + }, + { + "url": "http://127.0.0.1:5591/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 454, + "startMs": 4826, + "headersMs": 4977, + "endMs": 5115 + }, + { + "url": "http://127.0.0.1:5591/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 455, + "startMs": 4856, + "headersMs": 5008, + "endMs": 5010 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 456, + "startMs": 4968, + "headersMs": 5119, + "endMs": 5128 + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 457, + "startMs": 5012, + "headersMs": 5164, + "endMs": 5179 + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 458, + "startMs": 5029, + "headersMs": 5180, + "endMs": 5197 + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 459, + "startMs": 5052, + "headersMs": 5204, + "endMs": 5209 + }, + { + "url": "http://127.0.0.1:5591/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 460, + "startMs": 5080, + "headersMs": 5231, + "endMs": 5234 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 461, + "startMs": 5118, + "headersMs": 5270, + "endMs": 5278 + }, + { + "url": "http://127.0.0.1:5591/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 462, + "startMs": 5130, + "headersMs": 5282, + "endMs": 5306 + }, + { + "url": "http://127.0.0.1:5591/index.html?v=33e10c4b2d", + "status": 200, + "bytes": 11500, + "index": 463, + "startMs": 5182, + "headersMs": 5333, + "endMs": 5390 + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 464, + "startMs": 5200, + "headersMs": 5352, + "endMs": 5358 + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 465, + "startMs": 5211, + "headersMs": 5361, + "endMs": 5371 + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 466, + "startMs": 5235, + "headersMs": 5387, + "endMs": 5388 + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 467, + "startMs": 5280, + "headersMs": 5433, + "endMs": 5438 + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 468, + "startMs": 5308, + "headersMs": 5458, + "endMs": 5474 + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 469, + "startMs": 5360, + "headersMs": 5512, + "endMs": 5515 + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 470, + "startMs": 5373, + "headersMs": 5524, + "endMs": 5536 + }, + { + "url": "http://127.0.0.1:5591/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 471, + "startMs": 5390, + "headersMs": 5542, + "endMs": 5545 + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 472, + "startMs": 5393, + "headersMs": 5542, + "endMs": 5553 + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 473, + "startMs": 5441, + "headersMs": 5593, + "endMs": 5599 + }, + { + "url": "http://127.0.0.1:5591/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 474, + "startMs": 5476, + "headersMs": 5627, + "endMs": 5647 + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 475, + "startMs": 5517, + "headersMs": 5668, + "endMs": 5691 + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 476, + "startMs": 5539, + "headersMs": 5691, + "endMs": 5712 + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 477, + "startMs": 5547, + "headersMs": 5699, + "endMs": 5704 + }, + { + "url": "http://127.0.0.1:5591/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 478, + "startMs": 5555, + "headersMs": 5705, + "endMs": 5712 + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 479, + "startMs": 5601, + "headersMs": 5753, + "endMs": 5767 + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 480, + "startMs": 5649, + "headersMs": 5802, + "endMs": 5808 + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 481, + "startMs": 5695, + "headersMs": 5846, + "endMs": 5851 + }, + { + "url": "http://127.0.0.1:5591/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 482, + "startMs": 5706, + "headersMs": 5856, + "endMs": 5869 + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 483, + "startMs": 5714, + "headersMs": 5867, + "endMs": 5887 + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 484, + "startMs": 5714, + "headersMs": 5867, + "endMs": 5871 + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 485, + "startMs": 5770, + "headersMs": 5921, + "endMs": 5926 + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 486, + "startMs": 5811, + "headersMs": 5963, + "endMs": 5992 + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 487, + "startMs": 5853, + "headersMs": 6005, + "endMs": 6008 + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 488, + "startMs": 5871, + "headersMs": 6022, + "endMs": 6025 + }, + { + "url": "http://127.0.0.1:5591/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 489, + "startMs": 5873, + "headersMs": 6024, + "endMs": 6028 + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 490, + "startMs": 5890, + "headersMs": 6041, + "endMs": 6044 + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 491, + "startMs": 5928, + "headersMs": 6080, + "endMs": 6084 + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 492, + "startMs": 5995, + "headersMs": 6146, + "endMs": 6152 + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 493, + "startMs": 6010, + "headersMs": 6162, + "endMs": 6184 + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 494, + "startMs": 6027, + "headersMs": 6179, + "endMs": 6194 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 495, + "startMs": 6030, + "headersMs": 6182, + "endMs": 6186 + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 496, + "startMs": 6046, + "headersMs": 6198, + "endMs": 6213 + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 497, + "startMs": 6086, + "headersMs": 6237, + "endMs": 6246 + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 498, + "startMs": 6154, + "headersMs": 6306, + "endMs": 6323 + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 499, + "startMs": 6187, + "headersMs": 6338, + "endMs": 6351 + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 500, + "startMs": 6188, + "headersMs": 6338, + "endMs": 6506 + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 501, + "startMs": 6196, + "headersMs": 6346, + "endMs": 6372 + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 502, + "startMs": 6215, + "headersMs": 6366, + "endMs": 6404 + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 503, + "startMs": 6248, + "headersMs": 6400, + "endMs": 6420 + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 504, + "startMs": 6325, + "headersMs": 6477, + "endMs": 6504 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 505, + "startMs": 6353, + "headersMs": 6504, + "endMs": 6513 + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 506, + "startMs": 6374, + "headersMs": 6526, + "endMs": 6531 + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 507, + "startMs": 6407, + "headersMs": 6560, + "endMs": 6591 + }, + { + "url": "http://127.0.0.1:5591/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 508, + "startMs": 6423, + "headersMs": 6573, + "endMs": 6799 + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 509, + "startMs": 6507, + "headersMs": 6659, + "endMs": 6671 + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 510, + "startMs": 6509, + "headersMs": 6660, + "endMs": 6663 + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 511, + "startMs": 6515, + "headersMs": 6666, + "endMs": 6673 + }, + { + "url": "http://127.0.0.1:5591/sw.js", + "status": 200, + "bytes": 8052, + "index": 512, + "startMs": 6811, + "headersMs": 6964, + "endMs": 7005 + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "status": 200, + "bytes": 1742, + "index": 513, + "startMs": 7008, + "headersMs": 7159, + "endMs": 7168 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5591/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 218, + "responseStart": 372, + "end": 373, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 218, + "responseStart": 395, + "end": 395, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 218, + "responseStart": 401, + "end": 401, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 218, + "responseStart": 402, + "end": 402, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 218, + "responseStart": 539, + "end": 540, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 218, + "responseStart": 546, + "end": 546, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/recommendations.css?v=055101368d", + "bytes": 983, + "start": 218, + "responseStart": 550, + "end": 550, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 219, + "responseStart": 554, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 219, + "responseStart": 559, + "end": 559, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 219, + "responseStart": 697, + "end": 697, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 219, + "responseStart": 700, + "end": 700, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 219, + "responseStart": 705, + "end": 706, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 219, + "responseStart": 707, + "end": 708, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 219, + "responseStart": 720, + "end": 721, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 220, + "responseStart": 855, + "end": 856, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 220, + "responseStart": 859, + "end": 860, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 220, + "responseStart": 860, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 220, + "responseStart": 860, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 220, + "responseStart": 910, + "end": 911, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 220, + "responseStart": 934, + "end": 934, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5591/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 223, + "responseStart": 1013, + "end": 1014, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 224, + "responseStart": 1025, + "end": 1025, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 224, + "responseStart": 1027, + "end": 1027, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 224, + "responseStart": 1034, + "end": 1035, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 224, + "responseStart": 1066, + "end": 1067, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 224, + "responseStart": 1098, + "end": 1098, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 224, + "responseStart": 1175, + "end": 1176, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 224, + "responseStart": 1187, + "end": 1187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 224, + "responseStart": 1190, + "end": 1190, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 224, + "responseStart": 1202, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 225, + "responseStart": 1227, + "end": 1227, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 225, + "responseStart": 1261, + "end": 1262, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 225, + "responseStart": 1334, + "end": 1334, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 225, + "responseStart": 1347, + "end": 1347, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 225, + "responseStart": 1362, + "end": 1363, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 225, + "responseStart": 1369, + "end": 1369, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 225, + "responseStart": 1383, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/asset-sync-core.js?v=4e5dd69c40", + "bytes": 1742, + "start": 225, + "responseStart": 1422, + "end": 1422, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 226, + "responseStart": 1502, + "end": 1502, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 226, + "responseStart": 1512, + "end": 1513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 226, + "responseStart": 1518, + "end": 1518, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 226, + "responseStart": 1536, + "end": 1537, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 226, + "responseStart": 1553, + "end": 1553, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 226, + "responseStart": 1581, + "end": 1582, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 227, + "responseStart": 1662, + "end": 1663, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 227, + "responseStart": 1673, + "end": 1673, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 227, + "responseStart": 1686, + "end": 1687, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 227, + "responseStart": 1693, + "end": 1693, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 227, + "responseStart": 1717, + "end": 1717, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 227, + "responseStart": 1755, + "end": 1755, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 227, + "responseStart": 1820, + "end": 1821, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 227, + "responseStart": 1830, + "end": 1830, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 228, + "responseStart": 1852, + "end": 1852, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 228, + "responseStart": 1858, + "end": 1858, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 228, + "responseStart": 1892, + "end": 1892, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 228, + "responseStart": 1914, + "end": 1914, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 228, + "responseStart": 1981, + "end": 1982, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 228, + "responseStart": 1994, + "end": 1994, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 228, + "responseStart": 2015, + "end": 2016, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 228, + "responseStart": 2016, + "end": 2017, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 229, + "responseStart": 2051, + "end": 2051, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 229, + "responseStart": 2075, + "end": 2075, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 229, + "responseStart": 2138, + "end": 2138, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 229, + "responseStart": 2166, + "end": 2166, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 229, + "responseStart": 2178, + "end": 2179, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 229, + "responseStart": 2182, + "end": 2182, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 229, + "responseStart": 2206, + "end": 2206, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 229, + "responseStart": 2232, + "end": 2233, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5591/app.js?v=32f243e804", + "bytes": 164863, + "start": 230, + "responseStart": 2618, + "end": 3118, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-before-phase3.json b/perf/results/phase6-before-phase3.json new file mode 100644 index 0000000..d5e0df0 --- /dev/null +++ b/perf/results/phase6-before-phase3.json @@ -0,0 +1,6846 @@ +{ + "date": "2026-10-08T00:29:54.100Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-phase3", + "sourceCommit": "cd4a25ae23f0dd8034b012e4606dec8bf5337de5", + "frontendBuildTag": "bea1f63eba85", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 148, + "min": 148, + "max": 148, + "values": [ + 148, + 148, + 148 + ] + }, + "wireBytes": { + "median": 1108191, + "min": 1108191, + "max": 1108191, + "values": [ + 1108191, + 1108191, + 1108191 + ] + }, + "fcp": { + "median": 1646, + "min": 1636, + "max": 2635, + "values": [ + 2635, + 1646, + 1636 + ] + }, + "lcp": { + "median": 1726, + "min": 1723, + "max": 2706, + "values": [ + 2706, + 1726, + 1723 + ] + }, + "domContentLoaded": { + "median": 2450, + "min": 2449, + "max": 3456, + "values": [ + 3456, + 2450, + 2449 + ] + }, + "bootDone": { + "median": 2455, + "min": 2455, + "max": 3463, + "values": [ + 3463, + 2455, + 2455 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31666, + "min": 31660, + "max": 32605, + "values": [ + 32605, + 31666, + 31660 + ] + }, + "swInstallBytes": { + "median": 1108191, + "min": 1108191, + "max": 1108191, + "values": [ + 1108191, + 1108191, + 1108191 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 27464, + "js": 568878, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 4693, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5487/?v=benchmedia01", + "status": 200, + "bytes": 13732, + "index": 1, + "startMs": 17, + "headersMs": 234, + "endMs": 304 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 312, + "headersMs": 464, + "endMs": 848 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 313, + "headersMs": 466, + "endMs": 640 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 4, + "startMs": 313, + "headersMs": 474, + "endMs": 489 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 314, + "headersMs": 477, + "endMs": 480 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 314, + "headersMs": 658, + "endMs": 826 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 315, + "headersMs": 676, + "endMs": 698 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 490, + "headersMs": 677, + "endMs": 678 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 481, + "headersMs": 704, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 641, + "headersMs": 795, + "endMs": 800 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 679, + "headersMs": 836, + "endMs": 842 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 699, + "headersMs": 853, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 735, + "headersMs": 891, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 801, + "headersMs": 960, + "endMs": 969 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 828, + "headersMs": 982, + "endMs": 984 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 842, + "headersMs": 996, + "endMs": 999 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 848, + "headersMs": 1003, + "endMs": 1010 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 859, + "headersMs": 1025, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 895, + "headersMs": 1057, + "endMs": 1073 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 970, + "headersMs": 1125, + "endMs": 1128 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 985, + "headersMs": 1143, + "endMs": 1155 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 1000, + "headersMs": 1156, + "endMs": 1164 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1011, + "headersMs": 1172, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1049, + "headersMs": 1203, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1074, + "headersMs": 1234, + "endMs": 1245 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1129, + "headersMs": 1285, + "endMs": 1292 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1156, + "headersMs": 1312, + "endMs": 1317 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1165, + "headersMs": 1322, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1190, + "headersMs": 1355, + "endMs": 1381 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1211, + "headersMs": 1364, + "endMs": 1368 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1246, + "headersMs": 1400, + "endMs": 1404 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1294, + "headersMs": 1456, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1317, + "headersMs": 1480, + "endMs": 1496 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1331, + "headersMs": 1487, + "endMs": 1491 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1369, + "headersMs": 1523, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1382, + "headersMs": 1539, + "endMs": 1549 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1405, + "headersMs": 1569, + "endMs": 1588 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1472, + "headersMs": 1627, + "endMs": 1632 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1491, + "headersMs": 1646, + "endMs": 1652 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1497, + "headersMs": 1650, + "endMs": 1652 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1529, + "headersMs": 1683, + "endMs": 1687 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1550, + "headersMs": 1705, + "endMs": 1709 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1589, + "headersMs": 1749, + "endMs": 1762 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 44, + "startMs": 1633, + "headersMs": 2559, + "endMs": 3391 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 45, + "startMs": 1653, + "headersMs": 2580, + "endMs": 2601 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 46, + "startMs": 1653, + "headersMs": 2585, + "endMs": 2588 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 47, + "startMs": 3441, + "headersMs": 3595, + "endMs": 3597 + }, + { + "url": "http://127.0.0.1:5487/api/version", + "status": 200, + "bytes": 62, + "index": 48, + "startMs": 3460, + "headersMs": 3611, + "endMs": 3613 + }, + { + "url": "http://127.0.0.1:5487/api/user/sync", + "status": 200, + "bytes": 11, + "index": 49, + "startMs": 3461, + "headersMs": 3618, + "endMs": 3620 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 50, + "startMs": 3466, + "headersMs": 3651, + "endMs": 3697 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 51, + "startMs": 3622, + "headersMs": 3775, + "endMs": 3776 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 52, + "startMs": 3704, + "headersMs": 3856, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:5487/api/manifest", + "status": 200, + "bytes": 3460, + "index": 53, + "startMs": 3873, + "headersMs": 4041, + "endMs": 4059 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 54, + "startMs": 4085, + "headersMs": 4238, + "endMs": 5067 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 4086, + "headersMs": 4239, + "endMs": 4247 + }, + { + "url": "http://127.0.0.1:5487/assets.json?v=aa3952024e", + "status": 200, + "bytes": 1112, + "index": 56, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4251 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 57, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4249 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 58, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4249 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 59, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4251 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 60, + "startMs": 4250, + "headersMs": 4403, + "endMs": 4405 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 61, + "startMs": 4251, + "headersMs": 4403, + "endMs": 4407 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 62, + "startMs": 4251, + "headersMs": 4404, + "endMs": 4407 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 63, + "startMs": 4252, + "headersMs": 4404, + "endMs": 4423 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 64, + "startMs": 4252, + "headersMs": 4404, + "endMs": 4415 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 65, + "startMs": 4408, + "headersMs": 4560, + "endMs": 4565 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 66, + "startMs": 4408, + "headersMs": 4560, + "endMs": 4572 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 67, + "startMs": 4409, + "headersMs": 4561, + "endMs": 4567 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 68, + "startMs": 4417, + "headersMs": 4569, + "endMs": 4581 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 69, + "startMs": 4425, + "headersMs": 4576, + "endMs": 4730 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 70, + "startMs": 4569, + "headersMs": 4720, + "endMs": 5105 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 71, + "startMs": 4569, + "headersMs": 4720, + "endMs": 4818 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 72, + "startMs": 4574, + "headersMs": 4725, + "endMs": 4898 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 73, + "startMs": 4584, + "headersMs": 4735, + "endMs": 4794 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 74, + "startMs": 4732, + "headersMs": 4884, + "endMs": 5043 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 75, + "startMs": 4796, + "headersMs": 4948, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 76, + "startMs": 4820, + "headersMs": 4973, + "endMs": 4982 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 77, + "startMs": 4900, + "headersMs": 5051, + "endMs": 5066 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 78, + "startMs": 4953, + "headersMs": 5103, + "endMs": 5111 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 79, + "startMs": 4985, + "headersMs": 5138, + "endMs": 5162 + }, + { + "url": "http://127.0.0.1:5487/index.html?v=b9eda89698", + "status": 200, + "bytes": 13732, + "index": 80, + "startMs": 5046, + "headersMs": 5198, + "endMs": 5266 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 81, + "startMs": 5069, + "headersMs": 5221, + "endMs": 5222 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 82, + "startMs": 5073, + "headersMs": 5224, + "endMs": 5240 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 83, + "startMs": 5109, + "headersMs": 5260, + "endMs": 5267 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 84, + "startMs": 5113, + "headersMs": 5263, + "endMs": 5274 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 85, + "startMs": 5165, + "headersMs": 5318, + "endMs": 5334 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 86, + "startMs": 5224, + "headersMs": 5375, + "endMs": 5379 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 87, + "startMs": 5242, + "headersMs": 5394, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 88, + "startMs": 5269, + "headersMs": 5421, + "endMs": 5427 + }, + { + "url": "http://127.0.0.1:5487/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 89, + "startMs": 5269, + "headersMs": 5435, + "endMs": 5456 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 90, + "startMs": 5275, + "headersMs": 5435, + "endMs": 5457 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 91, + "startMs": 5336, + "headersMs": 5488, + "endMs": 5491 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 92, + "startMs": 5380, + "headersMs": 5532, + "endMs": 5537 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 93, + "startMs": 5400, + "headersMs": 5552, + "endMs": 5581 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 94, + "startMs": 5429, + "headersMs": 5581, + "endMs": 5584 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 95, + "startMs": 5458, + "headersMs": 5609, + "endMs": 5612 + }, + { + "url": "http://127.0.0.1:5487/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 96, + "startMs": 5459, + "headersMs": 5612, + "endMs": 5617 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 97, + "startMs": 5493, + "headersMs": 5645, + "endMs": 5648 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 98, + "startMs": 5539, + "headersMs": 5692, + "endMs": 5697 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 99, + "startMs": 5583, + "headersMs": 5735, + "endMs": 5740 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 100, + "startMs": 5585, + "headersMs": 5736, + "endMs": 5759 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 101, + "startMs": 5614, + "headersMs": 5765, + "endMs": 5770 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 102, + "startMs": 5618, + "headersMs": 5769, + "endMs": 5785 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 103, + "startMs": 5650, + "headersMs": 5802, + "endMs": 5810 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 104, + "startMs": 5698, + "headersMs": 5850, + "endMs": 5867 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 105, + "startMs": 5742, + "headersMs": 5894, + "endMs": 6062 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 106, + "startMs": 5763, + "headersMs": 5915, + "endMs": 5941 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 107, + "startMs": 5772, + "headersMs": 5923, + "endMs": 5943 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 108, + "startMs": 5787, + "headersMs": 5938, + "endMs": 5941 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 109, + "startMs": 6073, + "headersMs": 6225, + "endMs": 6270 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 110, + "startMs": 6272, + "headersMs": 6424, + "endMs": 6434 + }, + { + "url": "http://127.0.0.1:5487/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 111, + "startMs": 7097, + "headersMs": 7254, + "endMs": 7261 + }, + { + "url": "http://127.0.0.1:5487/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 112, + "startMs": 7097, + "headersMs": 7255, + "endMs": 7258 + }, + { + "url": "http://127.0.0.1:5487/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 113, + "startMs": 7097, + "headersMs": 7261, + "endMs": 7272 + }, + { + "url": "http://127.0.0.1:5487/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 114, + "startMs": 7097, + "headersMs": 7263, + "endMs": 7265 + }, + { + "url": "http://127.0.0.1:5487/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 115, + "startMs": 7097, + "headersMs": 7276, + "endMs": 7297 + }, + { + "url": "http://127.0.0.1:5487/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 116, + "startMs": 7097, + "headersMs": 7280, + "endMs": 7287 + }, + { + "url": "http://127.0.0.1:5487/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 117, + "startMs": 7261, + "headersMs": 7417, + "endMs": 7422 + }, + { + "url": "http://127.0.0.1:5487/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 118, + "startMs": 7263, + "headersMs": 7421, + "endMs": 7429 + }, + { + "url": "http://127.0.0.1:5487/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 119, + "startMs": 7266, + "headersMs": 7424, + "endMs": 7431 + }, + { + "url": "http://127.0.0.1:5487/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 120, + "startMs": 7273, + "headersMs": 7428, + "endMs": 7435 + }, + { + "url": "http://127.0.0.1:5487/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 121, + "startMs": 7289, + "headersMs": 7454, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 122, + "startMs": 7299, + "headersMs": 7455, + "endMs": 7563 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 123, + "startMs": 7424, + "headersMs": 7576, + "endMs": 7712 + }, + { + "url": "http://127.0.0.1:5487/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 124, + "startMs": 7432, + "headersMs": 7591, + "endMs": 7607 + }, + { + "url": "http://127.0.0.1:5487/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 125, + "startMs": 7432, + "headersMs": 7594, + "endMs": 7600 + }, + { + "url": "http://127.0.0.1:5487/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 126, + "startMs": 7437, + "headersMs": 7596, + "endMs": 7600 + }, + { + "url": "http://127.0.0.1:5487/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 127, + "startMs": 7480, + "headersMs": 7633, + "endMs": 7636 + }, + { + "url": "http://127.0.0.1:5487/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 128, + "startMs": 7567, + "headersMs": 7721, + "endMs": 7726 + }, + { + "url": "http://127.0.0.1:5487/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 129, + "startMs": 7602, + "headersMs": 7762, + "endMs": 7775 + }, + { + "url": "http://127.0.0.1:5487/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 7602, + "headersMs": 7770, + "endMs": 7781 + }, + { + "url": "http://127.0.0.1:5487/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 131, + "startMs": 7609, + "headersMs": 7789, + "endMs": 7811 + }, + { + "url": "http://127.0.0.1:5487/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 132, + "startMs": 7637, + "headersMs": 7793, + "endMs": 7799 + }, + { + "url": "http://127.0.0.1:5487/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 133, + "startMs": 7714, + "headersMs": 7871, + "endMs": 7880 + }, + { + "url": "http://127.0.0.1:5487/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 134, + "startMs": 7728, + "headersMs": 7891, + "endMs": 7905 + }, + { + "url": "http://127.0.0.1:5487/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 135, + "startMs": 7778, + "headersMs": 7933, + "endMs": 7940 + }, + { + "url": "http://127.0.0.1:5487/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 136, + "startMs": 7784, + "headersMs": 7937, + "endMs": 7942 + }, + { + "url": "http://127.0.0.1:5487/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 137, + "startMs": 7801, + "headersMs": 7952, + "endMs": 7965 + }, + { + "url": "http://127.0.0.1:5487/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 138, + "startMs": 7813, + "headersMs": 7978, + "endMs": 7999 + }, + { + "url": "http://127.0.0.1:5487/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 139, + "startMs": 7883, + "headersMs": 8043, + "endMs": 8058 + }, + { + "url": "http://127.0.0.1:5487/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 140, + "startMs": 7908, + "headersMs": 8068, + "endMs": 8082 + }, + { + "url": "http://127.0.0.1:5487/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 141, + "startMs": 7942, + "headersMs": 8133, + "endMs": 8172 + }, + { + "url": "http://127.0.0.1:5487/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 142, + "startMs": 7943, + "headersMs": 8161, + "endMs": 8189 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 143, + "startMs": 7967, + "headersMs": 8169, + "endMs": 8178 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 144, + "startMs": 8001, + "headersMs": 8175, + "endMs": 8180 + }, + { + "url": "http://127.0.0.1:5487/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 145, + "startMs": 8062, + "headersMs": 8246, + "endMs": 8276 + }, + { + "url": "http://127.0.0.1:5487/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 146, + "startMs": 8084, + "headersMs": 8450, + "endMs": 8676 + }, + { + "url": "http://127.0.0.1:5487/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 147, + "startMs": 8174, + "headersMs": 8462, + "endMs": 8474 + }, + { + "url": "http://127.0.0.1:5487/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 148, + "startMs": 8179, + "headersMs": 8466, + "endMs": 8473 + } + ], + "initialJsCss": { + "median": 274813, + "min": 274813, + "max": 274813, + "values": [ + 274813, + 274813, + 274813 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 309, + "responseStart": 477, + "end": 478, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 309, + "responseStart": 486, + "end": 487, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 309, + "responseStart": 676, + "end": 676, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 309, + "responseStart": 696, + "end": 696, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 309, + "responseStart": 732, + "end": 732, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "bytes": 983, + "start": 309, + "responseStart": 797, + "end": 798, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 309, + "responseStart": 823, + "end": 824, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 310, + "responseStart": 839, + "end": 839, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 310, + "responseStart": 856, + "end": 857, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 310, + "responseStart": 892, + "end": 892, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 310, + "responseStart": 967, + "end": 967, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 310, + "responseStart": 982, + "end": 982, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 310, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 311, + "responseStart": 1008, + "end": 1008, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 311, + "responseStart": 1045, + "end": 1046, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 311, + "responseStart": 1071, + "end": 1071, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 311, + "responseStart": 1126, + "end": 1126, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 311, + "responseStart": 1153, + "end": 1153, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 312, + "responseStart": 1161, + "end": 1162, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 312, + "responseStart": 1187, + "end": 1187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 312, + "responseStart": 1207, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 312, + "responseStart": 1243, + "end": 1243, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 312, + "responseStart": 1290, + "end": 1291, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 312, + "responseStart": 1314, + "end": 1315, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 312, + "responseStart": 1328, + "end": 1328, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 312, + "responseStart": 1365, + "end": 1366, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 312, + "responseStart": 1379, + "end": 1379, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 313, + "responseStart": 1402, + "end": 1402, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 313, + "responseStart": 1469, + "end": 1469, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 313, + "responseStart": 1488, + "end": 1488, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 313, + "responseStart": 1493, + "end": 1494, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 313, + "responseStart": 1526, + "end": 1526, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 313, + "responseStart": 1547, + "end": 1547, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 313, + "responseStart": 1585, + "end": 1586, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 313, + "responseStart": 1629, + "end": 1630, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 313, + "responseStart": 1649, + "end": 1650, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 314, + "responseStart": 1650, + "end": 1650, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 314, + "responseStart": 1684, + "end": 1685, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 314, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 314, + "responseStart": 1760, + "end": 1760, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "bytes": 165918, + "start": 314, + "responseStart": 2884, + "end": 3389, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 490, + "responseStart": 2599, + "end": 2599, + "initiator": "link" + } + ], + "waterfalls": [ + { + "fcp": 2635, + "requests": [ + { + "url": "http://127.0.0.1:5487/?v=benchmedia01", + "status": 200, + "bytes": 13732, + "index": 1, + "startMs": 17, + "headersMs": 234, + "endMs": 304 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 312, + "headersMs": 464, + "endMs": 848 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 313, + "headersMs": 466, + "endMs": 640 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 4, + "startMs": 313, + "headersMs": 474, + "endMs": 489 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 314, + "headersMs": 477, + "endMs": 480 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 314, + "headersMs": 658, + "endMs": 826 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 315, + "headersMs": 676, + "endMs": 698 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 490, + "headersMs": 677, + "endMs": 678 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 481, + "headersMs": 704, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 641, + "headersMs": 795, + "endMs": 800 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 679, + "headersMs": 836, + "endMs": 842 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 699, + "headersMs": 853, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 735, + "headersMs": 891, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 801, + "headersMs": 960, + "endMs": 969 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 828, + "headersMs": 982, + "endMs": 984 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 842, + "headersMs": 996, + "endMs": 999 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 848, + "headersMs": 1003, + "endMs": 1010 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 859, + "headersMs": 1025, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 895, + "headersMs": 1057, + "endMs": 1073 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 970, + "headersMs": 1125, + "endMs": 1128 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 985, + "headersMs": 1143, + "endMs": 1155 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 1000, + "headersMs": 1156, + "endMs": 1164 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1011, + "headersMs": 1172, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1049, + "headersMs": 1203, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1074, + "headersMs": 1234, + "endMs": 1245 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1129, + "headersMs": 1285, + "endMs": 1292 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1156, + "headersMs": 1312, + "endMs": 1317 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1165, + "headersMs": 1322, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1190, + "headersMs": 1355, + "endMs": 1381 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1211, + "headersMs": 1364, + "endMs": 1368 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1246, + "headersMs": 1400, + "endMs": 1404 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1294, + "headersMs": 1456, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1317, + "headersMs": 1480, + "endMs": 1496 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1331, + "headersMs": 1487, + "endMs": 1491 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1369, + "headersMs": 1523, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1382, + "headersMs": 1539, + "endMs": 1549 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1405, + "headersMs": 1569, + "endMs": 1588 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1472, + "headersMs": 1627, + "endMs": 1632 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1491, + "headersMs": 1646, + "endMs": 1652 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1497, + "headersMs": 1650, + "endMs": 1652 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1529, + "headersMs": 1683, + "endMs": 1687 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1550, + "headersMs": 1705, + "endMs": 1709 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1589, + "headersMs": 1749, + "endMs": 1762 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 44, + "startMs": 1633, + "headersMs": 2559, + "endMs": 3391 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 45, + "startMs": 1653, + "headersMs": 2580, + "endMs": 2601 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 46, + "startMs": 1653, + "headersMs": 2585, + "endMs": 2588 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 47, + "startMs": 3441, + "headersMs": 3595, + "endMs": 3597 + }, + { + "url": "http://127.0.0.1:5487/api/version", + "status": 200, + "bytes": 62, + "index": 48, + "startMs": 3460, + "headersMs": 3611, + "endMs": 3613 + }, + { + "url": "http://127.0.0.1:5487/api/user/sync", + "status": 200, + "bytes": 11, + "index": 49, + "startMs": 3461, + "headersMs": 3618, + "endMs": 3620 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 50, + "startMs": 3466, + "headersMs": 3651, + "endMs": 3697 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 51, + "startMs": 3622, + "headersMs": 3775, + "endMs": 3776 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 52, + "startMs": 3704, + "headersMs": 3856, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:5487/api/manifest", + "status": 200, + "bytes": 3460, + "index": 53, + "startMs": 3873, + "headersMs": 4041, + "endMs": 4059 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 54, + "startMs": 4085, + "headersMs": 4238, + "endMs": 5067 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 4086, + "headersMs": 4239, + "endMs": 4247 + }, + { + "url": "http://127.0.0.1:5487/assets.json?v=aa3952024e", + "status": 200, + "bytes": 1112, + "index": 56, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4251 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 57, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4249 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 58, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4249 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 59, + "startMs": 4086, + "headersMs": 4245, + "endMs": 4251 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 60, + "startMs": 4250, + "headersMs": 4403, + "endMs": 4405 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 61, + "startMs": 4251, + "headersMs": 4403, + "endMs": 4407 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 62, + "startMs": 4251, + "headersMs": 4404, + "endMs": 4407 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 63, + "startMs": 4252, + "headersMs": 4404, + "endMs": 4423 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 64, + "startMs": 4252, + "headersMs": 4404, + "endMs": 4415 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 65, + "startMs": 4408, + "headersMs": 4560, + "endMs": 4565 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 66, + "startMs": 4408, + "headersMs": 4560, + "endMs": 4572 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 67, + "startMs": 4409, + "headersMs": 4561, + "endMs": 4567 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 68, + "startMs": 4417, + "headersMs": 4569, + "endMs": 4581 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 69, + "startMs": 4425, + "headersMs": 4576, + "endMs": 4730 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 70, + "startMs": 4569, + "headersMs": 4720, + "endMs": 5105 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 71, + "startMs": 4569, + "headersMs": 4720, + "endMs": 4818 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 72, + "startMs": 4574, + "headersMs": 4725, + "endMs": 4898 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 73, + "startMs": 4584, + "headersMs": 4735, + "endMs": 4794 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 74, + "startMs": 4732, + "headersMs": 4884, + "endMs": 5043 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 75, + "startMs": 4796, + "headersMs": 4948, + "endMs": 4950 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 76, + "startMs": 4820, + "headersMs": 4973, + "endMs": 4982 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 77, + "startMs": 4900, + "headersMs": 5051, + "endMs": 5066 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 78, + "startMs": 4953, + "headersMs": 5103, + "endMs": 5111 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 79, + "startMs": 4985, + "headersMs": 5138, + "endMs": 5162 + }, + { + "url": "http://127.0.0.1:5487/index.html?v=b9eda89698", + "status": 200, + "bytes": 13732, + "index": 80, + "startMs": 5046, + "headersMs": 5198, + "endMs": 5266 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 81, + "startMs": 5069, + "headersMs": 5221, + "endMs": 5222 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 82, + "startMs": 5073, + "headersMs": 5224, + "endMs": 5240 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 83, + "startMs": 5109, + "headersMs": 5260, + "endMs": 5267 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 84, + "startMs": 5113, + "headersMs": 5263, + "endMs": 5274 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 85, + "startMs": 5165, + "headersMs": 5318, + "endMs": 5334 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 86, + "startMs": 5224, + "headersMs": 5375, + "endMs": 5379 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 87, + "startMs": 5242, + "headersMs": 5394, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 88, + "startMs": 5269, + "headersMs": 5421, + "endMs": 5427 + }, + { + "url": "http://127.0.0.1:5487/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 89, + "startMs": 5269, + "headersMs": 5435, + "endMs": 5456 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 90, + "startMs": 5275, + "headersMs": 5435, + "endMs": 5457 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 91, + "startMs": 5336, + "headersMs": 5488, + "endMs": 5491 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 92, + "startMs": 5380, + "headersMs": 5532, + "endMs": 5537 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 93, + "startMs": 5400, + "headersMs": 5552, + "endMs": 5581 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 94, + "startMs": 5429, + "headersMs": 5581, + "endMs": 5584 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 95, + "startMs": 5458, + "headersMs": 5609, + "endMs": 5612 + }, + { + "url": "http://127.0.0.1:5487/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 96, + "startMs": 5459, + "headersMs": 5612, + "endMs": 5617 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 97, + "startMs": 5493, + "headersMs": 5645, + "endMs": 5648 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 98, + "startMs": 5539, + "headersMs": 5692, + "endMs": 5697 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 99, + "startMs": 5583, + "headersMs": 5735, + "endMs": 5740 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 100, + "startMs": 5585, + "headersMs": 5736, + "endMs": 5759 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 101, + "startMs": 5614, + "headersMs": 5765, + "endMs": 5770 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 102, + "startMs": 5618, + "headersMs": 5769, + "endMs": 5785 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 103, + "startMs": 5650, + "headersMs": 5802, + "endMs": 5810 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 104, + "startMs": 5698, + "headersMs": 5850, + "endMs": 5867 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 105, + "startMs": 5742, + "headersMs": 5894, + "endMs": 6062 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 106, + "startMs": 5763, + "headersMs": 5915, + "endMs": 5941 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 107, + "startMs": 5772, + "headersMs": 5923, + "endMs": 5943 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 108, + "startMs": 5787, + "headersMs": 5938, + "endMs": 5941 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 109, + "startMs": 6073, + "headersMs": 6225, + "endMs": 6270 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 110, + "startMs": 6272, + "headersMs": 6424, + "endMs": 6434 + }, + { + "url": "http://127.0.0.1:5487/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 111, + "startMs": 7097, + "headersMs": 7254, + "endMs": 7261 + }, + { + "url": "http://127.0.0.1:5487/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 112, + "startMs": 7097, + "headersMs": 7255, + "endMs": 7258 + }, + { + "url": "http://127.0.0.1:5487/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 113, + "startMs": 7097, + "headersMs": 7261, + "endMs": 7272 + }, + { + "url": "http://127.0.0.1:5487/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 114, + "startMs": 7097, + "headersMs": 7263, + "endMs": 7265 + }, + { + "url": "http://127.0.0.1:5487/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 115, + "startMs": 7097, + "headersMs": 7276, + "endMs": 7297 + }, + { + "url": "http://127.0.0.1:5487/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 116, + "startMs": 7097, + "headersMs": 7280, + "endMs": 7287 + }, + { + "url": "http://127.0.0.1:5487/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 117, + "startMs": 7261, + "headersMs": 7417, + "endMs": 7422 + }, + { + "url": "http://127.0.0.1:5487/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 118, + "startMs": 7263, + "headersMs": 7421, + "endMs": 7429 + }, + { + "url": "http://127.0.0.1:5487/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 119, + "startMs": 7266, + "headersMs": 7424, + "endMs": 7431 + }, + { + "url": "http://127.0.0.1:5487/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 120, + "startMs": 7273, + "headersMs": 7428, + "endMs": 7435 + }, + { + "url": "http://127.0.0.1:5487/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 121, + "startMs": 7289, + "headersMs": 7454, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 122, + "startMs": 7299, + "headersMs": 7455, + "endMs": 7563 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 123, + "startMs": 7424, + "headersMs": 7576, + "endMs": 7712 + }, + { + "url": "http://127.0.0.1:5487/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 124, + "startMs": 7432, + "headersMs": 7591, + "endMs": 7607 + }, + { + "url": "http://127.0.0.1:5487/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 125, + "startMs": 7432, + "headersMs": 7594, + "endMs": 7600 + }, + { + "url": "http://127.0.0.1:5487/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 126, + "startMs": 7437, + "headersMs": 7596, + "endMs": 7600 + }, + { + "url": "http://127.0.0.1:5487/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 127, + "startMs": 7480, + "headersMs": 7633, + "endMs": 7636 + }, + { + "url": "http://127.0.0.1:5487/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 128, + "startMs": 7567, + "headersMs": 7721, + "endMs": 7726 + }, + { + "url": "http://127.0.0.1:5487/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 129, + "startMs": 7602, + "headersMs": 7762, + "endMs": 7775 + }, + { + "url": "http://127.0.0.1:5487/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 7602, + "headersMs": 7770, + "endMs": 7781 + }, + { + "url": "http://127.0.0.1:5487/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 131, + "startMs": 7609, + "headersMs": 7789, + "endMs": 7811 + }, + { + "url": "http://127.0.0.1:5487/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 132, + "startMs": 7637, + "headersMs": 7793, + "endMs": 7799 + }, + { + "url": "http://127.0.0.1:5487/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 133, + "startMs": 7714, + "headersMs": 7871, + "endMs": 7880 + }, + { + "url": "http://127.0.0.1:5487/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 134, + "startMs": 7728, + "headersMs": 7891, + "endMs": 7905 + }, + { + "url": "http://127.0.0.1:5487/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 135, + "startMs": 7778, + "headersMs": 7933, + "endMs": 7940 + }, + { + "url": "http://127.0.0.1:5487/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 136, + "startMs": 7784, + "headersMs": 7937, + "endMs": 7942 + }, + { + "url": "http://127.0.0.1:5487/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 137, + "startMs": 7801, + "headersMs": 7952, + "endMs": 7965 + }, + { + "url": "http://127.0.0.1:5487/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 138, + "startMs": 7813, + "headersMs": 7978, + "endMs": 7999 + }, + { + "url": "http://127.0.0.1:5487/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 139, + "startMs": 7883, + "headersMs": 8043, + "endMs": 8058 + }, + { + "url": "http://127.0.0.1:5487/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 140, + "startMs": 7908, + "headersMs": 8068, + "endMs": 8082 + }, + { + "url": "http://127.0.0.1:5487/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 141, + "startMs": 7942, + "headersMs": 8133, + "endMs": 8172 + }, + { + "url": "http://127.0.0.1:5487/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 142, + "startMs": 7943, + "headersMs": 8161, + "endMs": 8189 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 143, + "startMs": 7967, + "headersMs": 8169, + "endMs": 8178 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 144, + "startMs": 8001, + "headersMs": 8175, + "endMs": 8180 + }, + { + "url": "http://127.0.0.1:5487/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 145, + "startMs": 8062, + "headersMs": 8246, + "endMs": 8276 + }, + { + "url": "http://127.0.0.1:5487/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 146, + "startMs": 8084, + "headersMs": 8450, + "endMs": 8676 + }, + { + "url": "http://127.0.0.1:5487/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 147, + "startMs": 8174, + "headersMs": 8462, + "endMs": 8474 + }, + { + "url": "http://127.0.0.1:5487/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 148, + "startMs": 8179, + "headersMs": 8466, + "endMs": 8473 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 309, + "responseStart": 477, + "end": 478, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 309, + "responseStart": 486, + "end": 487, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 309, + "responseStart": 676, + "end": 676, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 309, + "responseStart": 696, + "end": 696, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 309, + "responseStart": 732, + "end": 732, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "bytes": 983, + "start": 309, + "responseStart": 797, + "end": 798, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 309, + "responseStart": 823, + "end": 824, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 310, + "responseStart": 839, + "end": 839, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 310, + "responseStart": 856, + "end": 857, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 310, + "responseStart": 892, + "end": 892, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 310, + "responseStart": 967, + "end": 967, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 310, + "responseStart": 982, + "end": 982, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 310, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 311, + "responseStart": 1008, + "end": 1008, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 311, + "responseStart": 1045, + "end": 1046, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 311, + "responseStart": 1071, + "end": 1071, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 311, + "responseStart": 1126, + "end": 1126, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 311, + "responseStart": 1153, + "end": 1153, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 312, + "responseStart": 1161, + "end": 1162, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 312, + "responseStart": 1187, + "end": 1187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 312, + "responseStart": 1207, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 312, + "responseStart": 1243, + "end": 1243, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 312, + "responseStart": 1290, + "end": 1291, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 312, + "responseStart": 1314, + "end": 1315, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 312, + "responseStart": 1328, + "end": 1328, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 312, + "responseStart": 1365, + "end": 1366, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 312, + "responseStart": 1379, + "end": 1379, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 313, + "responseStart": 1402, + "end": 1402, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 313, + "responseStart": 1469, + "end": 1469, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 313, + "responseStart": 1488, + "end": 1488, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 313, + "responseStart": 1493, + "end": 1494, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 313, + "responseStart": 1526, + "end": 1526, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 313, + "responseStart": 1547, + "end": 1547, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 313, + "responseStart": 1585, + "end": 1586, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 313, + "responseStart": 1629, + "end": 1630, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 313, + "responseStart": 1649, + "end": 1650, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 314, + "responseStart": 1650, + "end": 1650, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 314, + "responseStart": 1684, + "end": 1685, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 314, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 314, + "responseStart": 1760, + "end": 1760, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "bytes": 165918, + "start": 314, + "responseStart": 2884, + "end": 3389, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 490, + "responseStart": 2599, + "end": 2599, + "initiator": "link" + } + ] + }, + { + "fcp": 1646, + "requests": [ + { + "url": "http://127.0.0.1:5487/?v=benchmedia01", + "status": 200, + "bytes": 13732, + "index": 149, + "startMs": 16, + "headersMs": 170, + "endMs": 238 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 150, + "startMs": 245, + "headersMs": 399, + "endMs": 783 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 151, + "startMs": 246, + "headersMs": 400, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 152, + "startMs": 246, + "headersMs": 400, + "endMs": 415 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 153, + "startMs": 246, + "headersMs": 400, + "endMs": 403 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 154, + "startMs": 247, + "headersMs": 400, + "endMs": 568 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 155, + "startMs": 247, + "headersMs": 400, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 156, + "startMs": 404, + "headersMs": 556, + "endMs": 586 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 157, + "startMs": 415, + "headersMs": 567, + "endMs": 569 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 158, + "startMs": 424, + "headersMs": 575, + "endMs": 579 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 159, + "startMs": 569, + "headersMs": 721, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 160, + "startMs": 569, + "headersMs": 721, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 161, + "startMs": 573, + "headersMs": 723, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 162, + "startMs": 580, + "headersMs": 730, + "endMs": 738 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 163, + "startMs": 587, + "headersMs": 737, + "endMs": 739 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 164, + "startMs": 728, + "headersMs": 879, + "endMs": 882 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 165, + "startMs": 728, + "headersMs": 879, + "endMs": 886 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 166, + "startMs": 728, + "headersMs": 879, + "endMs": 902 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 167, + "startMs": 739, + "headersMs": 890, + "endMs": 905 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 168, + "startMs": 740, + "headersMs": 891, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 169, + "startMs": 784, + "headersMs": 936, + "endMs": 948 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 170, + "startMs": 883, + "headersMs": 1034, + "endMs": 1042 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 171, + "startMs": 887, + "headersMs": 1037, + "endMs": 1052 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 172, + "startMs": 895, + "headersMs": 1045, + "endMs": 1052 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 173, + "startMs": 902, + "headersMs": 1053, + "endMs": 1063 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 174, + "startMs": 906, + "headersMs": 1057, + "endMs": 1063 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 175, + "startMs": 949, + "headersMs": 1101, + "endMs": 1106 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 176, + "startMs": 1043, + "headersMs": 1196, + "endMs": 1206 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 177, + "startMs": 1053, + "headersMs": 1204, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 178, + "startMs": 1053, + "headersMs": 1204, + "endMs": 1207 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 179, + "startMs": 1064, + "headersMs": 1217, + "endMs": 1220 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 180, + "startMs": 1065, + "headersMs": 1217, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 181, + "startMs": 1107, + "headersMs": 1259, + "endMs": 1275 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 182, + "startMs": 1207, + "headersMs": 1358, + "endMs": 1361 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 183, + "startMs": 1208, + "headersMs": 1359, + "endMs": 1363 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 184, + "startMs": 1221, + "headersMs": 1372, + "endMs": 1382 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 185, + "startMs": 1230, + "headersMs": 1382, + "endMs": 1401 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 186, + "startMs": 1231, + "headersMs": 1382, + "endMs": 1387 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 187, + "startMs": 1276, + "headersMs": 1428, + "endMs": 1433 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 188, + "startMs": 1362, + "headersMs": 1512, + "endMs": 1514 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 189, + "startMs": 1364, + "headersMs": 1514, + "endMs": 1518 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 190, + "startMs": 1383, + "headersMs": 1533, + "endMs": 1538 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 191, + "startMs": 1387, + "headersMs": 1538, + "endMs": 1551 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 192, + "startMs": 1402, + "headersMs": 1553, + "endMs": 2385 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 193, + "startMs": 1434, + "headersMs": 1586, + "endMs": 1607 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 194, + "startMs": 1515, + "headersMs": 1667, + "endMs": 1670 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 195, + "startMs": 2433, + "headersMs": 2586, + "endMs": 2587 + }, + { + "url": "http://127.0.0.1:5487/api/version", + "status": 200, + "bytes": 62, + "index": 196, + "startMs": 2452, + "headersMs": 2605, + "endMs": 2607 + }, + { + "url": "http://127.0.0.1:5487/api/user/sync", + "status": 200, + "bytes": 11, + "index": 197, + "startMs": 2453, + "headersMs": 2607, + "endMs": 2608 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 198, + "startMs": 2458, + "headersMs": 2608, + "endMs": 2652 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 199, + "startMs": 2611, + "headersMs": 2764, + "endMs": 2766 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 200, + "startMs": 2659, + "headersMs": 2812, + "endMs": 2821 + }, + { + "url": "http://127.0.0.1:5487/api/manifest", + "status": 200, + "bytes": 3460, + "index": 201, + "startMs": 2826, + "headersMs": 2978, + "endMs": 2996 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 202, + "startMs": 3019, + "headersMs": 3172, + "endMs": 4002 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 203, + "startMs": 3019, + "headersMs": 3172, + "endMs": 3181 + }, + { + "url": "http://127.0.0.1:5487/assets.json?v=aa3952024e", + "status": 200, + "bytes": 1112, + "index": 204, + "startMs": 3019, + "headersMs": 3173, + "endMs": 3178 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 205, + "startMs": 3019, + "headersMs": 3173, + "endMs": 3177 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 206, + "startMs": 3019, + "headersMs": 3173, + "endMs": 3175 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 207, + "startMs": 3020, + "headersMs": 3173, + "endMs": 3180 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 208, + "startMs": 3178, + "headersMs": 3332, + "endMs": 3334 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 209, + "startMs": 3178, + "headersMs": 3333, + "endMs": 3336 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 210, + "startMs": 3180, + "headersMs": 3333, + "endMs": 3337 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 211, + "startMs": 3181, + "headersMs": 3333, + "endMs": 3350 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 212, + "startMs": 3183, + "headersMs": 3333, + "endMs": 3343 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 213, + "startMs": 3336, + "headersMs": 3494, + "endMs": 3498 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 214, + "startMs": 3337, + "headersMs": 3494, + "endMs": 3506 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 215, + "startMs": 3338, + "headersMs": 3494, + "endMs": 3501 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 216, + "startMs": 3345, + "headersMs": 3496, + "endMs": 3507 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 217, + "startMs": 3352, + "headersMs": 3503, + "endMs": 3658 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 218, + "startMs": 3501, + "headersMs": 3654, + "endMs": 4037 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 219, + "startMs": 3502, + "headersMs": 3654, + "endMs": 3751 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 220, + "startMs": 3508, + "headersMs": 3662, + "endMs": 3835 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 221, + "startMs": 3509, + "headersMs": 3662, + "endMs": 3721 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 222, + "startMs": 3661, + "headersMs": 3813, + "endMs": 3971 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 223, + "startMs": 3724, + "headersMs": 3875, + "endMs": 3878 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 224, + "startMs": 3754, + "headersMs": 3905, + "endMs": 3914 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 225, + "startMs": 3837, + "headersMs": 3989, + "endMs": 4003 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 226, + "startMs": 3880, + "headersMs": 4032, + "endMs": 4041 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 227, + "startMs": 3916, + "headersMs": 4068, + "endMs": 4092 + }, + { + "url": "http://127.0.0.1:5487/index.html?v=b9eda89698", + "status": 200, + "bytes": 13732, + "index": 228, + "startMs": 3975, + "headersMs": 4128, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 229, + "startMs": 4008, + "headersMs": 4160, + "endMs": 4161 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 230, + "startMs": 4008, + "headersMs": 4160, + "endMs": 4175 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 231, + "startMs": 4039, + "headersMs": 4192, + "endMs": 4197 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 232, + "startMs": 4042, + "headersMs": 4197, + "endMs": 4206 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 233, + "startMs": 4095, + "headersMs": 4247, + "endMs": 4263 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 234, + "startMs": 4163, + "headersMs": 4315, + "endMs": 4318 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 235, + "startMs": 4177, + "headersMs": 4328, + "endMs": 4332 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 236, + "startMs": 4199, + "headersMs": 4350, + "endMs": 4355 + }, + { + "url": "http://127.0.0.1:5487/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 237, + "startMs": 4199, + "headersMs": 4350, + "endMs": 4370 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 238, + "startMs": 4212, + "headersMs": 4362, + "endMs": 4385 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 239, + "startMs": 4265, + "headersMs": 4418, + "endMs": 4422 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 240, + "startMs": 4321, + "headersMs": 4473, + "endMs": 4477 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 241, + "startMs": 4334, + "headersMs": 4487, + "endMs": 4516 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 242, + "startMs": 4357, + "headersMs": 4509, + "endMs": 4511 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 243, + "startMs": 4372, + "headersMs": 4523, + "endMs": 4527 + }, + { + "url": "http://127.0.0.1:5487/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 244, + "startMs": 4387, + "headersMs": 4537, + "endMs": 4543 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 245, + "startMs": 4424, + "headersMs": 4576, + "endMs": 4580 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 246, + "startMs": 4479, + "headersMs": 4631, + "endMs": 4636 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 247, + "startMs": 4513, + "headersMs": 4666, + "endMs": 4672 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 248, + "startMs": 4519, + "headersMs": 4669, + "endMs": 4692 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 249, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4685 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 250, + "startMs": 4545, + "headersMs": 4696, + "endMs": 4711 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 251, + "startMs": 4581, + "headersMs": 4735, + "endMs": 4744 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 252, + "startMs": 4638, + "headersMs": 4788, + "endMs": 4805 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 253, + "startMs": 4674, + "headersMs": 4826, + "endMs": 4994 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 254, + "startMs": 4687, + "headersMs": 4842, + "endMs": 4867 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 255, + "startMs": 4694, + "headersMs": 4845, + "endMs": 4865 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 256, + "startMs": 4714, + "headersMs": 4865, + "endMs": 4867 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 257, + "startMs": 5004, + "headersMs": 5156, + "endMs": 5201 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 258, + "startMs": 5203, + "headersMs": 5359, + "endMs": 5367 + }, + { + "url": "http://127.0.0.1:5487/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 259, + "startMs": 6030, + "headersMs": 6182, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:5487/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 260, + "startMs": 6030, + "headersMs": 6182, + "endMs": 6184 + }, + { + "url": "http://127.0.0.1:5487/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 261, + "startMs": 6030, + "headersMs": 6183, + "endMs": 6192 + }, + { + "url": "http://127.0.0.1:5487/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 262, + "startMs": 6030, + "headersMs": 6183, + "endMs": 6184 + }, + { + "url": "http://127.0.0.1:5487/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 263, + "startMs": 6030, + "headersMs": 6183, + "endMs": 6204 + }, + { + "url": "http://127.0.0.1:5487/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 264, + "startMs": 6030, + "headersMs": 6183, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:5487/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 265, + "startMs": 6186, + "headersMs": 6338, + "endMs": 6344 + }, + { + "url": "http://127.0.0.1:5487/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 266, + "startMs": 6186, + "headersMs": 6338, + "endMs": 6346 + }, + { + "url": "http://127.0.0.1:5487/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 267, + "startMs": 6191, + "headersMs": 6341, + "endMs": 6347 + }, + { + "url": "http://127.0.0.1:5487/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 268, + "startMs": 6191, + "headersMs": 6341, + "endMs": 6349 + }, + { + "url": "http://127.0.0.1:5487/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 269, + "startMs": 6194, + "headersMs": 6344, + "endMs": 6368 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 270, + "startMs": 6207, + "headersMs": 6357, + "endMs": 6466 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 271, + "startMs": 6347, + "headersMs": 6499, + "endMs": 6635 + }, + { + "url": "http://127.0.0.1:5487/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 272, + "startMs": 6348, + "headersMs": 6499, + "endMs": 6515 + }, + { + "url": "http://127.0.0.1:5487/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 273, + "startMs": 6349, + "headersMs": 6499, + "endMs": 6504 + }, + { + "url": "http://127.0.0.1:5487/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 274, + "startMs": 6350, + "headersMs": 6502, + "endMs": 6504 + }, + { + "url": "http://127.0.0.1:5487/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 275, + "startMs": 6370, + "headersMs": 6522, + "endMs": 6524 + }, + { + "url": "http://127.0.0.1:5487/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 276, + "startMs": 6468, + "headersMs": 6620, + "endMs": 6625 + }, + { + "url": "http://127.0.0.1:5487/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 277, + "startMs": 6506, + "headersMs": 6658, + "endMs": 6669 + }, + { + "url": "http://127.0.0.1:5487/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 278, + "startMs": 6506, + "headersMs": 6658, + "endMs": 6669 + }, + { + "url": "http://127.0.0.1:5487/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 279, + "startMs": 6517, + "headersMs": 6668, + "endMs": 6691 + }, + { + "url": "http://127.0.0.1:5487/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 280, + "startMs": 6526, + "headersMs": 6678, + "endMs": 6683 + }, + { + "url": "http://127.0.0.1:5487/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 281, + "startMs": 6627, + "headersMs": 6779, + "endMs": 6786 + }, + { + "url": "http://127.0.0.1:5487/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 282, + "startMs": 6639, + "headersMs": 6789, + "endMs": 6803 + }, + { + "url": "http://127.0.0.1:5487/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 283, + "startMs": 6672, + "headersMs": 6824, + "endMs": 6830 + }, + { + "url": "http://127.0.0.1:5487/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 284, + "startMs": 6672, + "headersMs": 6824, + "endMs": 6828 + }, + { + "url": "http://127.0.0.1:5487/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 285, + "startMs": 6685, + "headersMs": 6836, + "endMs": 6848 + }, + { + "url": "http://127.0.0.1:5487/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 286, + "startMs": 6693, + "headersMs": 6846, + "endMs": 6867 + }, + { + "url": "http://127.0.0.1:5487/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 287, + "startMs": 6789, + "headersMs": 6940, + "endMs": 6955 + }, + { + "url": "http://127.0.0.1:5487/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 288, + "startMs": 6805, + "headersMs": 6956, + "endMs": 6970 + }, + { + "url": "http://127.0.0.1:5487/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 289, + "startMs": 6830, + "headersMs": 6982, + "endMs": 7020 + }, + { + "url": "http://127.0.0.1:5487/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 290, + "startMs": 6831, + "headersMs": 6983, + "endMs": 7010 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 291, + "startMs": 6850, + "headersMs": 7003, + "endMs": 7012 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 292, + "startMs": 6869, + "headersMs": 7021, + "endMs": 7026 + }, + { + "url": "http://127.0.0.1:5487/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 293, + "startMs": 6958, + "headersMs": 7110, + "endMs": 7140 + }, + { + "url": "http://127.0.0.1:5487/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 294, + "startMs": 6972, + "headersMs": 7124, + "endMs": 7349 + }, + { + "url": "http://127.0.0.1:5487/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 295, + "startMs": 7013, + "headersMs": 7165, + "endMs": 7177 + }, + { + "url": "http://127.0.0.1:5487/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 296, + "startMs": 7014, + "headersMs": 7165, + "endMs": 7172 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 243, + "responseStart": 401, + "end": 402, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 243, + "responseStart": 413, + "end": 413, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 243, + "responseStart": 421, + "end": 421, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 243, + "responseStart": 566, + "end": 567, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 243, + "responseStart": 567, + "end": 567, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 243, + "responseStart": 584, + "end": 585, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "bytes": 983, + "start": 244, + "responseStart": 577, + "end": 577, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 244, + "responseStart": 725, + "end": 725, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 244, + "responseStart": 725, + "end": 726, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 244, + "responseStart": 725, + "end": 726, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 244, + "responseStart": 736, + "end": 737, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 244, + "responseStart": 737, + "end": 737, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 244, + "responseStart": 880, + "end": 880, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 245, + "responseStart": 884, + "end": 885, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 245, + "responseStart": 892, + "end": 892, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 245, + "responseStart": 900, + "end": 900, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 245, + "responseStart": 903, + "end": 903, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 245, + "responseStart": 947, + "end": 947, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 245, + "responseStart": 1040, + "end": 1041, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 245, + "responseStart": 1050, + "end": 1051, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 245, + "responseStart": 1050, + "end": 1051, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 245, + "responseStart": 1062, + "end": 1063, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 246, + "responseStart": 1061, + "end": 1062, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 246, + "responseStart": 1104, + "end": 1104, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 246, + "responseStart": 1204, + "end": 1204, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 246, + "responseStart": 1205, + "end": 1205, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 246, + "responseStart": 1218, + "end": 1219, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 246, + "responseStart": 1228, + "end": 1228, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 246, + "responseStart": 1228, + "end": 1229, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 246, + "responseStart": 1273, + "end": 1274, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 247, + "responseStart": 1359, + "end": 1359, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 247, + "responseStart": 1361, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 247, + "responseStart": 1380, + "end": 1380, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 248, + "responseStart": 1385, + "end": 1385, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 248, + "responseStart": 1399, + "end": 1399, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 248, + "responseStart": 1431, + "end": 1432, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 248, + "responseStart": 1512, + "end": 1513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 248, + "responseStart": 1516, + "end": 1516, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 249, + "responseStart": 1536, + "end": 1536, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 249, + "responseStart": 1549, + "end": 1549, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "bytes": 165918, + "start": 249, + "responseStart": 1833, + "end": 2385, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 416, + "responseStart": 1605, + "end": 1606, + "initiator": "link" + } + ] + }, + { + "fcp": 1636, + "requests": [ + { + "url": "http://127.0.0.1:5487/?v=benchmedia01", + "status": 200, + "bytes": 13732, + "index": 297, + "startMs": 18, + "headersMs": 172, + "endMs": 242 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 298, + "startMs": 249, + "headersMs": 403, + "endMs": 789 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 299, + "startMs": 250, + "headersMs": 403, + "endMs": 576 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 300, + "startMs": 251, + "headersMs": 404, + "endMs": 419 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 301, + "startMs": 251, + "headersMs": 404, + "endMs": 405 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 302, + "startMs": 251, + "headersMs": 404, + "endMs": 571 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 303, + "startMs": 251, + "headersMs": 404, + "endMs": 427 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 304, + "startMs": 406, + "headersMs": 559, + "endMs": 588 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 305, + "startMs": 420, + "headersMs": 572, + "endMs": 573 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 306, + "startMs": 427, + "headersMs": 578, + "endMs": 583 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 307, + "startMs": 573, + "headersMs": 727, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 308, + "startMs": 574, + "headersMs": 727, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 309, + "startMs": 577, + "headersMs": 727, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 310, + "startMs": 583, + "headersMs": 734, + "endMs": 742 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 311, + "startMs": 589, + "headersMs": 739, + "endMs": 741 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 312, + "startMs": 732, + "headersMs": 885, + "endMs": 888 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 313, + "startMs": 733, + "headersMs": 885, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 314, + "startMs": 733, + "headersMs": 885, + "endMs": 908 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 315, + "startMs": 742, + "headersMs": 893, + "endMs": 908 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 316, + "startMs": 743, + "headersMs": 894, + "endMs": 897 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 317, + "startMs": 790, + "headersMs": 941, + "endMs": 954 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 318, + "startMs": 889, + "headersMs": 1039, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 319, + "startMs": 892, + "headersMs": 1043, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 320, + "startMs": 898, + "headersMs": 1048, + "endMs": 1054 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 321, + "startMs": 909, + "headersMs": 1060, + "endMs": 1070 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 322, + "startMs": 909, + "headersMs": 1060, + "endMs": 1067 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 323, + "startMs": 955, + "headersMs": 1107, + "endMs": 1111 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 324, + "startMs": 1049, + "headersMs": 1205, + "endMs": 1215 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 325, + "startMs": 1055, + "headersMs": 1206, + "endMs": 1235 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 326, + "startMs": 1060, + "headersMs": 1214, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 327, + "startMs": 1069, + "headersMs": 1220, + "endMs": 1224 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 328, + "startMs": 1071, + "headersMs": 1220, + "endMs": 1235 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 329, + "startMs": 1112, + "headersMs": 1264, + "endMs": 1280 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 330, + "startMs": 1220, + "headersMs": 1374, + "endMs": 1378 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 331, + "startMs": 1220, + "headersMs": 1374, + "endMs": 1378 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 332, + "startMs": 1224, + "headersMs": 1374, + "endMs": 1385 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 333, + "startMs": 1236, + "headersMs": 1387, + "endMs": 1405 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 334, + "startMs": 1236, + "headersMs": 1387, + "endMs": 1392 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 335, + "startMs": 1281, + "headersMs": 1432, + "endMs": 1438 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 336, + "startMs": 1379, + "headersMs": 1533, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 337, + "startMs": 1379, + "headersMs": 1533, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 338, + "startMs": 1385, + "headersMs": 1536, + "endMs": 1541 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 339, + "startMs": 1392, + "headersMs": 1543, + "endMs": 1556 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 340, + "startMs": 1406, + "headersMs": 1559, + "endMs": 2395 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 341, + "startMs": 1439, + "headersMs": 1591, + "endMs": 1610 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 342, + "startMs": 1537, + "headersMs": 1688, + "endMs": 1692 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 343, + "startMs": 2444, + "headersMs": 2596, + "endMs": 2597 + }, + { + "url": "http://127.0.0.1:5487/api/version", + "status": 200, + "bytes": 62, + "index": 344, + "startMs": 2467, + "headersMs": 2618, + "endMs": 2619 + }, + { + "url": "http://127.0.0.1:5487/api/user/sync", + "status": 200, + "bytes": 11, + "index": 345, + "startMs": 2468, + "headersMs": 2621, + "endMs": 2623 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 346, + "startMs": 2474, + "headersMs": 2626, + "endMs": 2671 + }, + { + "url": "http://127.0.0.1:5487/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 347, + "startMs": 2626, + "headersMs": 2779, + "endMs": 2780 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 348, + "startMs": 2680, + "headersMs": 2832, + "endMs": 2842 + }, + { + "url": "http://127.0.0.1:5487/api/manifest", + "status": 200, + "bytes": 3460, + "index": 349, + "startMs": 2847, + "headersMs": 2999, + "endMs": 3018 + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "status": 200, + "bytes": 165918, + "index": 350, + "startMs": 3042, + "headersMs": 3194, + "endMs": 4023 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 351, + "startMs": 3042, + "headersMs": 3195, + "endMs": 3204 + }, + { + "url": "http://127.0.0.1:5487/assets.json?v=aa3952024e", + "status": 200, + "bytes": 1112, + "index": 352, + "startMs": 3042, + "headersMs": 3195, + "endMs": 3200 + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 353, + "startMs": 3042, + "headersMs": 3195, + "endMs": 3200 + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 354, + "startMs": 3043, + "headersMs": 3195, + "endMs": 3199 + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 355, + "startMs": 3043, + "headersMs": 3195, + "endMs": 3201 + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 356, + "startMs": 3201, + "headersMs": 3352, + "endMs": 3355 + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 357, + "startMs": 3202, + "headersMs": 3353, + "endMs": 3357 + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 358, + "startMs": 3202, + "headersMs": 3353, + "endMs": 3357 + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 359, + "startMs": 3203, + "headersMs": 3353, + "endMs": 3371 + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 360, + "startMs": 3206, + "headersMs": 3355, + "endMs": 3366 + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 361, + "startMs": 3357, + "headersMs": 3509, + "endMs": 3514 + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 362, + "startMs": 3358, + "headersMs": 3509, + "endMs": 3522 + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 363, + "startMs": 3359, + "headersMs": 3510, + "endMs": 3516 + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 364, + "startMs": 3368, + "headersMs": 3519, + "endMs": 3532 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 365, + "startMs": 3375, + "headersMs": 3526, + "endMs": 3680 + }, + { + "url": "http://127.0.0.1:5487/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 366, + "startMs": 3516, + "headersMs": 3668, + "endMs": 4052 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 367, + "startMs": 3517, + "headersMs": 3669, + "endMs": 3767 + }, + { + "url": "http://127.0.0.1:5487/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 368, + "startMs": 3524, + "headersMs": 3676, + "endMs": 3849 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 369, + "startMs": 3533, + "headersMs": 3684, + "endMs": 3743 + }, + { + "url": "http://127.0.0.1:5487/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 370, + "startMs": 3683, + "headersMs": 3836, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5487/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 371, + "startMs": 3746, + "headersMs": 3896, + "endMs": 3899 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 372, + "startMs": 3768, + "headersMs": 3919, + "endMs": 3928 + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 373, + "startMs": 3853, + "headersMs": 4004, + "endMs": 4018 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 374, + "startMs": 3901, + "headersMs": 4053, + "endMs": 4062 + }, + { + "url": "http://127.0.0.1:5487/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 375, + "startMs": 3930, + "headersMs": 4081, + "endMs": 4105 + }, + { + "url": "http://127.0.0.1:5487/index.html?v=b9eda89698", + "status": 200, + "bytes": 13732, + "index": 376, + "startMs": 3997, + "headersMs": 4148, + "endMs": 4216 + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 377, + "startMs": 4021, + "headersMs": 4173, + "endMs": 4174 + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 378, + "startMs": 4029, + "headersMs": 4181, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 379, + "startMs": 4055, + "headersMs": 4206, + "endMs": 4212 + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 380, + "startMs": 4064, + "headersMs": 4215, + "endMs": 4225 + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 381, + "startMs": 4107, + "headersMs": 4259, + "endMs": 4275 + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 382, + "startMs": 4176, + "headersMs": 4328, + "endMs": 4331 + }, + { + "url": "http://127.0.0.1:5487/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 383, + "startMs": 4199, + "headersMs": 4349, + "endMs": 4353 + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 384, + "startMs": 4214, + "headersMs": 4365, + "endMs": 4370 + }, + { + "url": "http://127.0.0.1:5487/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 385, + "startMs": 4219, + "headersMs": 4370, + "endMs": 4390 + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 386, + "startMs": 4228, + "headersMs": 4379, + "endMs": 4402 + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 387, + "startMs": 4277, + "headersMs": 4428, + "endMs": 4431 + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 388, + "startMs": 4333, + "headersMs": 4485, + "endMs": 4490 + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 389, + "startMs": 4355, + "headersMs": 4508, + "endMs": 4538 + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 390, + "startMs": 4372, + "headersMs": 4523, + "endMs": 4525 + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 391, + "startMs": 4393, + "headersMs": 4543, + "endMs": 4546 + }, + { + "url": "http://127.0.0.1:5487/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 392, + "startMs": 4404, + "headersMs": 4555, + "endMs": 4559 + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 393, + "startMs": 4433, + "headersMs": 4585, + "endMs": 4589 + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 394, + "startMs": 4492, + "headersMs": 4644, + "endMs": 4649 + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 395, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4685 + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 396, + "startMs": 4541, + "headersMs": 4692, + "endMs": 4715 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 397, + "startMs": 4548, + "headersMs": 4700, + "endMs": 4706 + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 398, + "startMs": 4561, + "headersMs": 4714, + "endMs": 4730 + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 399, + "startMs": 4591, + "headersMs": 4742, + "endMs": 4751 + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 400, + "startMs": 4651, + "headersMs": 4804, + "endMs": 4821 + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 401, + "startMs": 4687, + "headersMs": 4840, + "endMs": 5010 + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 402, + "startMs": 4708, + "headersMs": 4860, + "endMs": 4885 + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 403, + "startMs": 4717, + "headersMs": 4868, + "endMs": 4889 + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 404, + "startMs": 4732, + "headersMs": 4883, + "endMs": 4885 + }, + { + "url": "http://127.0.0.1:5487/sw.js", + "status": 200, + "bytes": 8941, + "index": 405, + "startMs": 5021, + "headersMs": 5173, + "endMs": 5218 + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 406, + "startMs": 5220, + "headersMs": 5372, + "endMs": 5382 + }, + { + "url": "http://127.0.0.1:5487/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 407, + "startMs": 6046, + "headersMs": 6199, + "endMs": 6207 + }, + { + "url": "http://127.0.0.1:5487/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 408, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6202 + }, + { + "url": "http://127.0.0.1:5487/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 409, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6210 + }, + { + "url": "http://127.0.0.1:5487/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 410, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6201 + }, + { + "url": "http://127.0.0.1:5487/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 411, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6221 + }, + { + "url": "http://127.0.0.1:5487/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 412, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6205 + }, + { + "url": "http://127.0.0.1:5487/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 413, + "startMs": 6203, + "headersMs": 6354, + "endMs": 6361 + }, + { + "url": "http://127.0.0.1:5487/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 414, + "startMs": 6203, + "headersMs": 6354, + "endMs": 6362 + }, + { + "url": "http://127.0.0.1:5487/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 415, + "startMs": 6207, + "headersMs": 6358, + "endMs": 6363 + }, + { + "url": "http://127.0.0.1:5487/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 416, + "startMs": 6208, + "headersMs": 6358, + "endMs": 6365 + }, + { + "url": "http://127.0.0.1:5487/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 417, + "startMs": 6211, + "headersMs": 6363, + "endMs": 6387 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 418, + "startMs": 6223, + "headersMs": 6373, + "endMs": 6483 + }, + { + "url": "http://127.0.0.1:5487/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 419, + "startMs": 6363, + "headersMs": 6515, + "endMs": 6652 + }, + { + "url": "http://127.0.0.1:5487/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 420, + "startMs": 6363, + "headersMs": 6515, + "endMs": 6532 + }, + { + "url": "http://127.0.0.1:5487/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 421, + "startMs": 6364, + "headersMs": 6515, + "endMs": 6521 + }, + { + "url": "http://127.0.0.1:5487/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 422, + "startMs": 6367, + "headersMs": 6518, + "endMs": 6521 + }, + { + "url": "http://127.0.0.1:5487/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 423, + "startMs": 6389, + "headersMs": 6541, + "endMs": 6543 + }, + { + "url": "http://127.0.0.1:5487/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 424, + "startMs": 6486, + "headersMs": 6638, + "endMs": 6644 + }, + { + "url": "http://127.0.0.1:5487/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 425, + "startMs": 6523, + "headersMs": 6674, + "endMs": 6686 + }, + { + "url": "http://127.0.0.1:5487/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 426, + "startMs": 6523, + "headersMs": 6675, + "endMs": 6685 + }, + { + "url": "http://127.0.0.1:5487/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 427, + "startMs": 6534, + "headersMs": 6685, + "endMs": 6708 + }, + { + "url": "http://127.0.0.1:5487/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 428, + "startMs": 6545, + "headersMs": 6695, + "endMs": 6702 + }, + { + "url": "http://127.0.0.1:5487/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 429, + "startMs": 6646, + "headersMs": 6797, + "endMs": 6805 + }, + { + "url": "http://127.0.0.1:5487/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 430, + "startMs": 6654, + "headersMs": 6805, + "endMs": 6819 + }, + { + "url": "http://127.0.0.1:5487/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 431, + "startMs": 6686, + "headersMs": 6838, + "endMs": 6845 + }, + { + "url": "http://127.0.0.1:5487/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 432, + "startMs": 6688, + "headersMs": 6838, + "endMs": 6842 + }, + { + "url": "http://127.0.0.1:5487/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 433, + "startMs": 6703, + "headersMs": 6854, + "endMs": 6867 + }, + { + "url": "http://127.0.0.1:5487/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 434, + "startMs": 6710, + "headersMs": 6861, + "endMs": 6882 + }, + { + "url": "http://127.0.0.1:5487/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 435, + "startMs": 6808, + "headersMs": 6958, + "endMs": 6972 + }, + { + "url": "http://127.0.0.1:5487/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 436, + "startMs": 6822, + "headersMs": 6972, + "endMs": 6986 + }, + { + "url": "http://127.0.0.1:5487/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 437, + "startMs": 6844, + "headersMs": 6995, + "endMs": 7034 + }, + { + "url": "http://127.0.0.1:5487/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 438, + "startMs": 6847, + "headersMs": 6997, + "endMs": 7025 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 439, + "startMs": 6868, + "headersMs": 7019, + "endMs": 7027 + }, + { + "url": "http://127.0.0.1:5487/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 440, + "startMs": 6884, + "headersMs": 7035, + "endMs": 7041 + }, + { + "url": "http://127.0.0.1:5487/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 441, + "startMs": 6974, + "headersMs": 7126, + "endMs": 7156 + }, + { + "url": "http://127.0.0.1:5487/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 442, + "startMs": 6988, + "headersMs": 7139, + "endMs": 7364 + }, + { + "url": "http://127.0.0.1:5487/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 443, + "startMs": 7027, + "headersMs": 7178, + "endMs": 7191 + }, + { + "url": "http://127.0.0.1:5487/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 444, + "startMs": 7030, + "headersMs": 7181, + "endMs": 7187 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5487/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 232, + "responseStart": 388, + "end": 388, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 232, + "responseStart": 401, + "end": 402, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 232, + "responseStart": 409, + "end": 409, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 232, + "responseStart": 554, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 232, + "responseStart": 556, + "end": 556, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 232, + "responseStart": 570, + "end": 570, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/recommendations.css?v=055101368d", + "bytes": 983, + "start": 233, + "responseStart": 565, + "end": 565, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 233, + "responseStart": 714, + "end": 714, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 233, + "responseStart": 715, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 233, + "responseStart": 715, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 233, + "responseStart": 724, + "end": 724, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 233, + "responseStart": 725, + "end": 725, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 233, + "responseStart": 870, + "end": 870, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5487/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 234, + "responseStart": 874, + "end": 874, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 234, + "responseStart": 879, + "end": 880, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 234, + "responseStart": 891, + "end": 891, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 234, + "responseStart": 890, + "end": 891, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 234, + "responseStart": 937, + "end": 937, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 234, + "responseStart": 1030, + "end": 1031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 234, + "responseStart": 1037, + "end": 1037, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 234, + "responseStart": 1041, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 234, + "responseStart": 1053, + "end": 1053, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 235, + "responseStart": 1050, + "end": 1050, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 235, + "responseStart": 1094, + "end": 1094, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 235, + "responseStart": 1200, + "end": 1201, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 235, + "responseStart": 1201, + "end": 1201, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 235, + "responseStart": 1206, + "end": 1206, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 235, + "responseStart": 1217, + "end": 1218, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 235, + "responseStart": 1217, + "end": 1218, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 235, + "responseStart": 1263, + "end": 1263, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 235, + "responseStart": 1360, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 235, + "responseStart": 1361, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 236, + "responseStart": 1367, + "end": 1367, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 236, + "responseStart": 1374, + "end": 1374, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 236, + "responseStart": 1388, + "end": 1388, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 236, + "responseStart": 1420, + "end": 1421, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 236, + "responseStart": 1518, + "end": 1519, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 236, + "responseStart": 1518, + "end": 1519, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 236, + "responseStart": 1523, + "end": 1524, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 236, + "responseStart": 1539, + "end": 1539, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/app.js?v=1d399bd3ef", + "bytes": 165918, + "start": 236, + "responseStart": 1868, + "end": 2379, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5487/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 405, + "responseStart": 1593, + "end": 1593, + "initiator": "link" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-before-phase5.json b/perf/results/phase6-before-phase5.json new file mode 100644 index 0000000..79ffa30 --- /dev/null +++ b/perf/results/phase6-before-phase5.json @@ -0,0 +1,7338 @@ +{ + "date": "2026-10-08T00:31:33.705Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-phase5", + "sourceCommit": "21c12733d326faba1a753ae8c19e9e93d848098f", + "frontendBuildTag": "c3dbdd7039db", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159, + 159, + 159 + ] + }, + "wireBytes": { + "median": 1097007, + "min": 1097007, + "max": 1097007, + "values": [ + 1097007, + 1097007, + 1097007 + ] + }, + "fcp": { + "median": 1736, + "min": 1731, + "max": 2513, + "values": [ + 2513, + 1736, + 1731 + ] + }, + "lcp": { + "median": 1804, + "min": 1802, + "max": 2583, + "values": [ + 2583, + 1804, + 1802 + ] + }, + "domContentLoaded": { + "median": 2315, + "min": 2303, + "max": 3087, + "values": [ + 3087, + 2315, + 2303 + ] + }, + "bootDone": { + "median": 2320, + "min": 2308, + "max": 3094, + "values": [ + 3094, + 2320, + 2308 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31556, + "min": 31487, + "max": 32277, + "values": [ + 32277, + 31556, + 31487 + ] + }, + "swInstallBytes": { + "median": 1097007, + "min": 1097007, + "max": 1097007, + "values": [ + 1097007, + 1097007, + 1097007 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28066, + "js": 556707, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5078, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:4685/?v=benchmedia01", + "status": 200, + "bytes": 14033, + "index": 1, + "startMs": 19, + "headersMs": 234, + "endMs": 306 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 312, + "headersMs": 466, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 313, + "headersMs": 468, + "endMs": 642 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 4, + "startMs": 314, + "headersMs": 477, + "endMs": 493 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 314, + "headersMs": 480, + "endMs": 482 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 314, + "headersMs": 656, + "endMs": 824 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 314, + "headersMs": 671, + "endMs": 695 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 494, + "headersMs": 673, + "endMs": 675 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 483, + "headersMs": 703, + "endMs": 733 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 643, + "headersMs": 798, + "endMs": 803 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 675, + "headersMs": 831, + "endMs": 837 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 696, + "headersMs": 852, + "endMs": 857 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 734, + "headersMs": 888, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 803, + "headersMs": 961, + "endMs": 970 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 826, + "headersMs": 979, + "endMs": 982 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 837, + "headersMs": 991, + "endMs": 994 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 850, + "headersMs": 1006, + "endMs": 1013 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 858, + "headersMs": 1022, + "endMs": 1045 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 892, + "headersMs": 1053, + "endMs": 1069 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 971, + "headersMs": 1125, + "endMs": 1129 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 982, + "headersMs": 1139, + "endMs": 1152 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 994, + "headersMs": 1150, + "endMs": 1159 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1013, + "headersMs": 1173, + "endMs": 1190 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1046, + "headersMs": 1200, + "endMs": 1206 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1070, + "headersMs": 1226, + "endMs": 1238 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1129, + "headersMs": 1286, + "endMs": 1292 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1152, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1159, + "headersMs": 1316, + "endMs": 1326 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1191, + "headersMs": 1357, + "endMs": 1383 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1207, + "headersMs": 1362, + "endMs": 1366 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1239, + "headersMs": 1393, + "endMs": 1397 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1293, + "headersMs": 1455, + "endMs": 1469 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1312, + "headersMs": 1474, + "endMs": 1490 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1327, + "headersMs": 1482, + "endMs": 1486 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1367, + "headersMs": 1522, + "endMs": 1527 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1383, + "headersMs": 1541, + "endMs": 1551 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1398, + "headersMs": 1562, + "endMs": 1580 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1470, + "headersMs": 1625, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1486, + "headersMs": 1640, + "endMs": 1645 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1490, + "headersMs": 1642, + "endMs": 1645 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1528, + "headersMs": 1683, + "endMs": 1686 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1552, + "headersMs": 1707, + "endMs": 1711 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1581, + "headersMs": 1740, + "endMs": 1753 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 44, + "startMs": 1630, + "headersMs": 1796, + "endMs": 1819 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 45, + "startMs": 1646, + "headersMs": 1874, + "endMs": 1971 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 46, + "startMs": 1646, + "headersMs": 1886, + "endMs": 1907 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 47, + "startMs": 1687, + "headersMs": 2435, + "endMs": 3034 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 48, + "startMs": 1713, + "headersMs": 2456, + "endMs": 2476 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1753, + "headersMs": 2461, + "endMs": 2465 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3075, + "headersMs": 3228, + "endMs": 3230 + }, + { + "url": "http://127.0.0.1:4685/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3091, + "headersMs": 3243, + "endMs": 3245 + }, + { + "url": "http://127.0.0.1:4685/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3092, + "headersMs": 3248, + "endMs": 3249 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 53, + "startMs": 3098, + "headersMs": 3287, + "endMs": 3332 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3252, + "headersMs": 3405, + "endMs": 3406 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3340, + "headersMs": 3492, + "endMs": 3502 + }, + { + "url": "http://127.0.0.1:4685/api/manifest", + "status": 200, + "bytes": 3737, + "index": 56, + "startMs": 3507, + "headersMs": 3673, + "endMs": 3692 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3717, + "headersMs": 3869, + "endMs": 4462 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3717, + "headersMs": 3869, + "endMs": 3879 + }, + { + "url": "http://127.0.0.1:4685/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3717, + "headersMs": 3876, + "endMs": 3882 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3717, + "headersMs": 3876, + "endMs": 3880 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3718, + "headersMs": 3876, + "endMs": 3879 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3719, + "headersMs": 3877, + "endMs": 3882 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3881, + "headersMs": 4035, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3882, + "headersMs": 4035, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3882, + "headersMs": 4035, + "endMs": 4039 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3883, + "headersMs": 4035, + "endMs": 4053 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3883, + "headersMs": 4035, + "endMs": 4045 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4040, + "headersMs": 4192, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4040, + "headersMs": 4192, + "endMs": 4205 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4041, + "headersMs": 4193, + "endMs": 4198 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4047, + "headersMs": 4198, + "endMs": 4210 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4055, + "headersMs": 4206, + "endMs": 4359 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4200, + "headersMs": 4352, + "endMs": 4736 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4201, + "headersMs": 4352, + "endMs": 4450 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4207, + "headersMs": 4358, + "endMs": 4532 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4212, + "headersMs": 4362, + "endMs": 4422 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4362, + "headersMs": 4513, + "endMs": 4672 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4425, + "headersMs": 4576, + "endMs": 4579 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4452, + "headersMs": 4604, + "endMs": 4612 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4467, + "headersMs": 4618, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4535, + "headersMs": 4686, + "endMs": 4695 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4581, + "headersMs": 4733, + "endMs": 4757 + }, + { + "url": "http://127.0.0.1:4685/index.html?v=b556b50667", + "status": 200, + "bytes": 14033, + "index": 83, + "startMs": 4614, + "headersMs": 4765, + "endMs": 4836 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4635, + "headersMs": 4786, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4675, + "headersMs": 4827, + "endMs": 4842 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4697, + "headersMs": 4848, + "endMs": 4855 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4738, + "headersMs": 4891, + "endMs": 4900 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4759, + "headersMs": 4910, + "endMs": 4926 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4790, + "headersMs": 4941, + "endMs": 4945 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4838, + "headersMs": 4991, + "endMs": 4995 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4844, + "headersMs": 4995, + "endMs": 5000 + }, + { + "url": "http://127.0.0.1:4685/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4856, + "headersMs": 5020, + "endMs": 5041 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4902, + "headersMs": 5055, + "endMs": 5078 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4928, + "headersMs": 5079, + "endMs": 5082 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4947, + "headersMs": 5098, + "endMs": 5103 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4997, + "headersMs": 5150, + "endMs": 5179 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5002, + "headersMs": 5153, + "endMs": 5155 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5043, + "headersMs": 5195, + "endMs": 5198 + }, + { + "url": "http://127.0.0.1:4685/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5080, + "headersMs": 5236, + "endMs": 5241 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5084, + "headersMs": 5236, + "endMs": 5239 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5105, + "headersMs": 5256, + "endMs": 5261 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5157, + "headersMs": 5308, + "endMs": 5330 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5182, + "headersMs": 5332, + "endMs": 5337 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5200, + "headersMs": 5351, + "endMs": 5374 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5241, + "headersMs": 5392, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5242, + "headersMs": 5392, + "endMs": 5407 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5263, + "headersMs": 5414, + "endMs": 5423 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5332, + "headersMs": 5484, + "endMs": 5500 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5339, + "headersMs": 5490, + "endMs": 5513 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5376, + "headersMs": 5527, + "endMs": 5695 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5400, + "headersMs": 5552, + "endMs": 5578 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5409, + "headersMs": 5560, + "endMs": 5580 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5424, + "headersMs": 5575, + "endMs": 5671 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5502, + "headersMs": 5654, + "endMs": 5657 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 115, + "startMs": 5704, + "headersMs": 5855, + "endMs": 5900 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5903, + "headersMs": 6059, + "endMs": 6069 + }, + { + "url": "http://127.0.0.1:4685/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6731, + "headersMs": 6887, + "endMs": 6894 + }, + { + "url": "http://127.0.0.1:4685/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6731, + "headersMs": 6889, + "endMs": 6892 + }, + { + "url": "http://127.0.0.1:4685/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6731, + "headersMs": 6894, + "endMs": 6904 + }, + { + "url": "http://127.0.0.1:4685/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6731, + "headersMs": 6896, + "endMs": 6897 + }, + { + "url": "http://127.0.0.1:4685/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6731, + "headersMs": 6910, + "endMs": 6932 + }, + { + "url": "http://127.0.0.1:4685/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6731, + "headersMs": 6914, + "endMs": 6921 + }, + { + "url": "http://127.0.0.1:4685/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6894, + "headersMs": 7051, + "endMs": 7058 + }, + { + "url": "http://127.0.0.1:4685/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6895, + "headersMs": 7055, + "endMs": 7062 + }, + { + "url": "http://127.0.0.1:4685/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6899, + "headersMs": 7058, + "endMs": 7063 + }, + { + "url": "http://127.0.0.1:4685/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6907, + "headersMs": 7062, + "endMs": 7070 + }, + { + "url": "http://127.0.0.1:4685/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6922, + "headersMs": 7087, + "endMs": 7111 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6934, + "headersMs": 7087, + "endMs": 7198 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7060, + "headersMs": 7212, + "endMs": 7349 + }, + { + "url": "http://127.0.0.1:4685/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7063, + "headersMs": 7223, + "endMs": 7241 + }, + { + "url": "http://127.0.0.1:4685/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7065, + "headersMs": 7226, + "endMs": 7232 + }, + { + "url": "http://127.0.0.1:4685/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7072, + "headersMs": 7228, + "endMs": 7232 + }, + { + "url": "http://127.0.0.1:4685/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7113, + "headersMs": 7267, + "endMs": 7269 + }, + { + "url": "http://127.0.0.1:4685/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7200, + "headersMs": 7356, + "endMs": 7362 + }, + { + "url": "http://127.0.0.1:4685/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7233, + "headersMs": 7392, + "endMs": 7405 + }, + { + "url": "http://127.0.0.1:4685/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7233, + "headersMs": 7397, + "endMs": 7408 + }, + { + "url": "http://127.0.0.1:4685/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7244, + "headersMs": 7413, + "endMs": 7435 + }, + { + "url": "http://127.0.0.1:4685/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7271, + "headersMs": 7427, + "endMs": 7432 + }, + { + "url": "http://127.0.0.1:4685/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7352, + "headersMs": 7509, + "endMs": 7517 + }, + { + "url": "http://127.0.0.1:4685/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7363, + "headersMs": 7522, + "endMs": 7536 + }, + { + "url": "http://127.0.0.1:4685/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7407, + "headersMs": 7563, + "endMs": 7570 + }, + { + "url": "http://127.0.0.1:4685/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7409, + "headersMs": 7565, + "endMs": 7570 + }, + { + "url": "http://127.0.0.1:4685/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7434, + "headersMs": 7586, + "endMs": 7599 + }, + { + "url": "http://127.0.0.1:4685/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7437, + "headersMs": 7601, + "endMs": 7622 + }, + { + "url": "http://127.0.0.1:4685/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7519, + "headersMs": 7681, + "endMs": 7699 + }, + { + "url": "http://127.0.0.1:4685/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7538, + "headersMs": 7719, + "endMs": 7765 + }, + { + "url": "http://127.0.0.1:4685/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7572, + "headersMs": 7734, + "endMs": 7749 + }, + { + "url": "http://127.0.0.1:4685/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7572, + "headersMs": 7747, + "endMs": 7768 + }, + { + "url": "http://127.0.0.1:4685/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7601, + "headersMs": 7759, + "endMs": 7772 + }, + { + "url": "http://127.0.0.1:4685/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7624, + "headersMs": 7783, + "endMs": 7796 + }, + { + "url": "http://127.0.0.1:4685/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7702, + "headersMs": 7892, + "endMs": 7930 + }, + { + "url": "http://127.0.0.1:4685/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7751, + "headersMs": 7929, + "endMs": 7956 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7768, + "headersMs": 7938, + "endMs": 7946 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7770, + "headersMs": 7944, + "endMs": 7950 + }, + { + "url": "http://127.0.0.1:4685/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7774, + "headersMs": 7976, + "endMs": 8006 + }, + { + "url": "http://127.0.0.1:4685/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7799, + "headersMs": 8170, + "endMs": 8395 + }, + { + "url": "http://127.0.0.1:4685/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7934, + "headersMs": 8180, + "endMs": 8192 + }, + { + "url": "http://127.0.0.1:4685/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7948, + "headersMs": 8183, + "endMs": 8190 + }, + { + "url": "http://127.0.0.1:4685/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7952, + "headersMs": 8205, + "endMs": 8244 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 310, + "responseStart": 479, + "end": 480, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 310, + "responseStart": 490, + "end": 490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 310, + "responseStart": 672, + "end": 672, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 310, + "responseStart": 692, + "end": 693, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 310, + "responseStart": 730, + "end": 731, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "bytes": 983, + "start": 310, + "responseStart": 800, + "end": 800, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 310, + "responseStart": 821, + "end": 823, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 310, + "responseStart": 834, + "end": 834, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 310, + "responseStart": 854, + "end": 855, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 310, + "responseStart": 889, + "end": 889, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 311, + "responseStart": 967, + "end": 967, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 311, + "responseStart": 979, + "end": 979, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 311, + "responseStart": 991, + "end": 991, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 312, + "responseStart": 1010, + "end": 1010, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 312, + "responseStart": 1042, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 312, + "responseStart": 1066, + "end": 1067, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 312, + "responseStart": 1126, + "end": 1126, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 312, + "responseStart": 1149, + "end": 1149, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 312, + "responseStart": 1156, + "end": 1156, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 312, + "responseStart": 1188, + "end": 1188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 313, + "responseStart": 1203, + "end": 1204, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 313, + "responseStart": 1235, + "end": 1236, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 313, + "responseStart": 1290, + "end": 1290, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 313, + "responseStart": 1309, + "end": 1309, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 313, + "responseStart": 1323, + "end": 1323, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 313, + "responseStart": 1363, + "end": 1364, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 313, + "responseStart": 1380, + "end": 1380, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 313, + "responseStart": 1394, + "end": 1394, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 313, + "responseStart": 1466, + "end": 1467, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 313, + "responseStart": 1487, + "end": 1487, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 314, + "responseStart": 1483, + "end": 1483, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 314, + "responseStart": 1524, + "end": 1524, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 314, + "responseStart": 1548, + "end": 1549, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 314, + "responseStart": 1577, + "end": 1578, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 314, + "responseStart": 1627, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 314, + "responseStart": 1642, + "end": 1643, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 314, + "responseStart": 1642, + "end": 1643, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 314, + "responseStart": 1683, + "end": 1684, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 315, + "responseStart": 1709, + "end": 1709, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 315, + "responseStart": 1750, + "end": 1750, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 315, + "responseStart": 1816, + "end": 1816, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 315, + "responseStart": 1905, + "end": 1905, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 315, + "responseStart": 1968, + "end": 1969, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "bytes": 118521, + "start": 315, + "responseStart": 2761, + "end": 3032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 494, + "responseStart": 2473, + "end": 2474, + "initiator": "link" + } + ], + "waterfalls": [ + { + "fcp": 2513, + "requests": [ + { + "url": "http://127.0.0.1:4685/?v=benchmedia01", + "status": 200, + "bytes": 14033, + "index": 1, + "startMs": 19, + "headersMs": 234, + "endMs": 306 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 312, + "headersMs": 466, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 313, + "headersMs": 468, + "endMs": 642 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 4, + "startMs": 314, + "headersMs": 477, + "endMs": 493 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 314, + "headersMs": 480, + "endMs": 482 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 314, + "headersMs": 656, + "endMs": 824 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 314, + "headersMs": 671, + "endMs": 695 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 494, + "headersMs": 673, + "endMs": 675 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 483, + "headersMs": 703, + "endMs": 733 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 643, + "headersMs": 798, + "endMs": 803 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 675, + "headersMs": 831, + "endMs": 837 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 696, + "headersMs": 852, + "endMs": 857 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 734, + "headersMs": 888, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 803, + "headersMs": 961, + "endMs": 970 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 826, + "headersMs": 979, + "endMs": 982 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 837, + "headersMs": 991, + "endMs": 994 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 850, + "headersMs": 1006, + "endMs": 1013 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 858, + "headersMs": 1022, + "endMs": 1045 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 892, + "headersMs": 1053, + "endMs": 1069 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 971, + "headersMs": 1125, + "endMs": 1129 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 982, + "headersMs": 1139, + "endMs": 1152 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 994, + "headersMs": 1150, + "endMs": 1159 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1013, + "headersMs": 1173, + "endMs": 1190 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1046, + "headersMs": 1200, + "endMs": 1206 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1070, + "headersMs": 1226, + "endMs": 1238 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1129, + "headersMs": 1286, + "endMs": 1292 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1152, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1159, + "headersMs": 1316, + "endMs": 1326 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1191, + "headersMs": 1357, + "endMs": 1383 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1207, + "headersMs": 1362, + "endMs": 1366 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1239, + "headersMs": 1393, + "endMs": 1397 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1293, + "headersMs": 1455, + "endMs": 1469 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1312, + "headersMs": 1474, + "endMs": 1490 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1327, + "headersMs": 1482, + "endMs": 1486 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1367, + "headersMs": 1522, + "endMs": 1527 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1383, + "headersMs": 1541, + "endMs": 1551 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1398, + "headersMs": 1562, + "endMs": 1580 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1470, + "headersMs": 1625, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1486, + "headersMs": 1640, + "endMs": 1645 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1490, + "headersMs": 1642, + "endMs": 1645 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1528, + "headersMs": 1683, + "endMs": 1686 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1552, + "headersMs": 1707, + "endMs": 1711 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1581, + "headersMs": 1740, + "endMs": 1753 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 44, + "startMs": 1630, + "headersMs": 1796, + "endMs": 1819 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 45, + "startMs": 1646, + "headersMs": 1874, + "endMs": 1971 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 46, + "startMs": 1646, + "headersMs": 1886, + "endMs": 1907 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 47, + "startMs": 1687, + "headersMs": 2435, + "endMs": 3034 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 48, + "startMs": 1713, + "headersMs": 2456, + "endMs": 2476 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1753, + "headersMs": 2461, + "endMs": 2465 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3075, + "headersMs": 3228, + "endMs": 3230 + }, + { + "url": "http://127.0.0.1:4685/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3091, + "headersMs": 3243, + "endMs": 3245 + }, + { + "url": "http://127.0.0.1:4685/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3092, + "headersMs": 3248, + "endMs": 3249 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 53, + "startMs": 3098, + "headersMs": 3287, + "endMs": 3332 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3252, + "headersMs": 3405, + "endMs": 3406 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3340, + "headersMs": 3492, + "endMs": 3502 + }, + { + "url": "http://127.0.0.1:4685/api/manifest", + "status": 200, + "bytes": 3737, + "index": 56, + "startMs": 3507, + "headersMs": 3673, + "endMs": 3692 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3717, + "headersMs": 3869, + "endMs": 4462 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3717, + "headersMs": 3869, + "endMs": 3879 + }, + { + "url": "http://127.0.0.1:4685/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3717, + "headersMs": 3876, + "endMs": 3882 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3717, + "headersMs": 3876, + "endMs": 3880 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3718, + "headersMs": 3876, + "endMs": 3879 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3719, + "headersMs": 3877, + "endMs": 3882 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3881, + "headersMs": 4035, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3882, + "headersMs": 4035, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3882, + "headersMs": 4035, + "endMs": 4039 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3883, + "headersMs": 4035, + "endMs": 4053 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3883, + "headersMs": 4035, + "endMs": 4045 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4040, + "headersMs": 4192, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4040, + "headersMs": 4192, + "endMs": 4205 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4041, + "headersMs": 4193, + "endMs": 4198 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4047, + "headersMs": 4198, + "endMs": 4210 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4055, + "headersMs": 4206, + "endMs": 4359 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4200, + "headersMs": 4352, + "endMs": 4736 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4201, + "headersMs": 4352, + "endMs": 4450 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4207, + "headersMs": 4358, + "endMs": 4532 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4212, + "headersMs": 4362, + "endMs": 4422 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4362, + "headersMs": 4513, + "endMs": 4672 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4425, + "headersMs": 4576, + "endMs": 4579 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4452, + "headersMs": 4604, + "endMs": 4612 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4467, + "headersMs": 4618, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4535, + "headersMs": 4686, + "endMs": 4695 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4581, + "headersMs": 4733, + "endMs": 4757 + }, + { + "url": "http://127.0.0.1:4685/index.html?v=b556b50667", + "status": 200, + "bytes": 14033, + "index": 83, + "startMs": 4614, + "headersMs": 4765, + "endMs": 4836 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4635, + "headersMs": 4786, + "endMs": 4788 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4675, + "headersMs": 4827, + "endMs": 4842 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4697, + "headersMs": 4848, + "endMs": 4855 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4738, + "headersMs": 4891, + "endMs": 4900 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4759, + "headersMs": 4910, + "endMs": 4926 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4790, + "headersMs": 4941, + "endMs": 4945 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4838, + "headersMs": 4991, + "endMs": 4995 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4844, + "headersMs": 4995, + "endMs": 5000 + }, + { + "url": "http://127.0.0.1:4685/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4856, + "headersMs": 5020, + "endMs": 5041 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4902, + "headersMs": 5055, + "endMs": 5078 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4928, + "headersMs": 5079, + "endMs": 5082 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4947, + "headersMs": 5098, + "endMs": 5103 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4997, + "headersMs": 5150, + "endMs": 5179 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5002, + "headersMs": 5153, + "endMs": 5155 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5043, + "headersMs": 5195, + "endMs": 5198 + }, + { + "url": "http://127.0.0.1:4685/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5080, + "headersMs": 5236, + "endMs": 5241 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5084, + "headersMs": 5236, + "endMs": 5239 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5105, + "headersMs": 5256, + "endMs": 5261 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5157, + "headersMs": 5308, + "endMs": 5330 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5182, + "headersMs": 5332, + "endMs": 5337 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5200, + "headersMs": 5351, + "endMs": 5374 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5241, + "headersMs": 5392, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5242, + "headersMs": 5392, + "endMs": 5407 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5263, + "headersMs": 5414, + "endMs": 5423 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5332, + "headersMs": 5484, + "endMs": 5500 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5339, + "headersMs": 5490, + "endMs": 5513 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5376, + "headersMs": 5527, + "endMs": 5695 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5400, + "headersMs": 5552, + "endMs": 5578 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5409, + "headersMs": 5560, + "endMs": 5580 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5424, + "headersMs": 5575, + "endMs": 5671 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5502, + "headersMs": 5654, + "endMs": 5657 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 115, + "startMs": 5704, + "headersMs": 5855, + "endMs": 5900 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5903, + "headersMs": 6059, + "endMs": 6069 + }, + { + "url": "http://127.0.0.1:4685/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6731, + "headersMs": 6887, + "endMs": 6894 + }, + { + "url": "http://127.0.0.1:4685/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6731, + "headersMs": 6889, + "endMs": 6892 + }, + { + "url": "http://127.0.0.1:4685/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6731, + "headersMs": 6894, + "endMs": 6904 + }, + { + "url": "http://127.0.0.1:4685/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6731, + "headersMs": 6896, + "endMs": 6897 + }, + { + "url": "http://127.0.0.1:4685/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6731, + "headersMs": 6910, + "endMs": 6932 + }, + { + "url": "http://127.0.0.1:4685/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6731, + "headersMs": 6914, + "endMs": 6921 + }, + { + "url": "http://127.0.0.1:4685/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6894, + "headersMs": 7051, + "endMs": 7058 + }, + { + "url": "http://127.0.0.1:4685/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6895, + "headersMs": 7055, + "endMs": 7062 + }, + { + "url": "http://127.0.0.1:4685/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6899, + "headersMs": 7058, + "endMs": 7063 + }, + { + "url": "http://127.0.0.1:4685/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6907, + "headersMs": 7062, + "endMs": 7070 + }, + { + "url": "http://127.0.0.1:4685/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6922, + "headersMs": 7087, + "endMs": 7111 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6934, + "headersMs": 7087, + "endMs": 7198 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7060, + "headersMs": 7212, + "endMs": 7349 + }, + { + "url": "http://127.0.0.1:4685/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7063, + "headersMs": 7223, + "endMs": 7241 + }, + { + "url": "http://127.0.0.1:4685/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7065, + "headersMs": 7226, + "endMs": 7232 + }, + { + "url": "http://127.0.0.1:4685/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7072, + "headersMs": 7228, + "endMs": 7232 + }, + { + "url": "http://127.0.0.1:4685/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7113, + "headersMs": 7267, + "endMs": 7269 + }, + { + "url": "http://127.0.0.1:4685/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7200, + "headersMs": 7356, + "endMs": 7362 + }, + { + "url": "http://127.0.0.1:4685/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7233, + "headersMs": 7392, + "endMs": 7405 + }, + { + "url": "http://127.0.0.1:4685/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7233, + "headersMs": 7397, + "endMs": 7408 + }, + { + "url": "http://127.0.0.1:4685/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7244, + "headersMs": 7413, + "endMs": 7435 + }, + { + "url": "http://127.0.0.1:4685/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7271, + "headersMs": 7427, + "endMs": 7432 + }, + { + "url": "http://127.0.0.1:4685/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7352, + "headersMs": 7509, + "endMs": 7517 + }, + { + "url": "http://127.0.0.1:4685/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7363, + "headersMs": 7522, + "endMs": 7536 + }, + { + "url": "http://127.0.0.1:4685/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7407, + "headersMs": 7563, + "endMs": 7570 + }, + { + "url": "http://127.0.0.1:4685/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7409, + "headersMs": 7565, + "endMs": 7570 + }, + { + "url": "http://127.0.0.1:4685/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7434, + "headersMs": 7586, + "endMs": 7599 + }, + { + "url": "http://127.0.0.1:4685/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7437, + "headersMs": 7601, + "endMs": 7622 + }, + { + "url": "http://127.0.0.1:4685/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7519, + "headersMs": 7681, + "endMs": 7699 + }, + { + "url": "http://127.0.0.1:4685/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7538, + "headersMs": 7719, + "endMs": 7765 + }, + { + "url": "http://127.0.0.1:4685/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7572, + "headersMs": 7734, + "endMs": 7749 + }, + { + "url": "http://127.0.0.1:4685/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7572, + "headersMs": 7747, + "endMs": 7768 + }, + { + "url": "http://127.0.0.1:4685/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7601, + "headersMs": 7759, + "endMs": 7772 + }, + { + "url": "http://127.0.0.1:4685/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7624, + "headersMs": 7783, + "endMs": 7796 + }, + { + "url": "http://127.0.0.1:4685/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7702, + "headersMs": 7892, + "endMs": 7930 + }, + { + "url": "http://127.0.0.1:4685/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7751, + "headersMs": 7929, + "endMs": 7956 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7768, + "headersMs": 7938, + "endMs": 7946 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7770, + "headersMs": 7944, + "endMs": 7950 + }, + { + "url": "http://127.0.0.1:4685/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7774, + "headersMs": 7976, + "endMs": 8006 + }, + { + "url": "http://127.0.0.1:4685/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7799, + "headersMs": 8170, + "endMs": 8395 + }, + { + "url": "http://127.0.0.1:4685/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7934, + "headersMs": 8180, + "endMs": 8192 + }, + { + "url": "http://127.0.0.1:4685/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7948, + "headersMs": 8183, + "endMs": 8190 + }, + { + "url": "http://127.0.0.1:4685/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7952, + "headersMs": 8205, + "endMs": 8244 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 310, + "responseStart": 479, + "end": 480, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 310, + "responseStart": 490, + "end": 490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 310, + "responseStart": 672, + "end": 672, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 310, + "responseStart": 692, + "end": 693, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 310, + "responseStart": 730, + "end": 731, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "bytes": 983, + "start": 310, + "responseStart": 800, + "end": 800, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 310, + "responseStart": 821, + "end": 823, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 310, + "responseStart": 834, + "end": 834, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 310, + "responseStart": 854, + "end": 855, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 310, + "responseStart": 889, + "end": 889, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 311, + "responseStart": 967, + "end": 967, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 311, + "responseStart": 979, + "end": 979, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 311, + "responseStart": 991, + "end": 991, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 312, + "responseStart": 1010, + "end": 1010, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 312, + "responseStart": 1042, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 312, + "responseStart": 1066, + "end": 1067, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 312, + "responseStart": 1126, + "end": 1126, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 312, + "responseStart": 1149, + "end": 1149, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 312, + "responseStart": 1156, + "end": 1156, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 312, + "responseStart": 1188, + "end": 1188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 313, + "responseStart": 1203, + "end": 1204, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 313, + "responseStart": 1235, + "end": 1236, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 313, + "responseStart": 1290, + "end": 1290, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 313, + "responseStart": 1309, + "end": 1309, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 313, + "responseStart": 1323, + "end": 1323, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 313, + "responseStart": 1363, + "end": 1364, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 313, + "responseStart": 1380, + "end": 1380, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 313, + "responseStart": 1394, + "end": 1394, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 313, + "responseStart": 1466, + "end": 1467, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 313, + "responseStart": 1487, + "end": 1487, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 314, + "responseStart": 1483, + "end": 1483, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 314, + "responseStart": 1524, + "end": 1524, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 314, + "responseStart": 1548, + "end": 1549, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 314, + "responseStart": 1577, + "end": 1578, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 314, + "responseStart": 1627, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 314, + "responseStart": 1642, + "end": 1643, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 314, + "responseStart": 1642, + "end": 1643, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 314, + "responseStart": 1683, + "end": 1684, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 315, + "responseStart": 1709, + "end": 1709, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 315, + "responseStart": 1750, + "end": 1750, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 315, + "responseStart": 1816, + "end": 1816, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 315, + "responseStart": 1905, + "end": 1905, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 315, + "responseStart": 1968, + "end": 1969, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "bytes": 118521, + "start": 315, + "responseStart": 2761, + "end": 3032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 494, + "responseStart": 2473, + "end": 2474, + "initiator": "link" + } + ] + }, + { + "fcp": 1736, + "requests": [ + { + "url": "http://127.0.0.1:4685/?v=benchmedia01", + "status": 200, + "bytes": 14033, + "index": 160, + "startMs": 17, + "headersMs": 169, + "endMs": 240 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 161, + "startMs": 247, + "headersMs": 399, + "endMs": 784 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 162, + "startMs": 248, + "headersMs": 400, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 163, + "startMs": 250, + "headersMs": 402, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 164, + "startMs": 251, + "headersMs": 402, + "endMs": 406 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 165, + "startMs": 251, + "headersMs": 403, + "endMs": 570 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 166, + "startMs": 251, + "headersMs": 403, + "endMs": 424 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 167, + "startMs": 406, + "headersMs": 561, + "endMs": 591 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 168, + "startMs": 418, + "headersMs": 569, + "endMs": 571 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 169, + "startMs": 425, + "headersMs": 576, + "endMs": 581 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 170, + "startMs": 572, + "headersMs": 723, + "endMs": 729 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 171, + "startMs": 573, + "headersMs": 724, + "endMs": 729 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 172, + "startMs": 573, + "headersMs": 724, + "endMs": 728 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 173, + "startMs": 582, + "headersMs": 733, + "endMs": 741 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 174, + "startMs": 592, + "headersMs": 742, + "endMs": 745 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 175, + "startMs": 728, + "headersMs": 880, + "endMs": 883 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 176, + "startMs": 729, + "headersMs": 880, + "endMs": 887 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 177, + "startMs": 729, + "headersMs": 881, + "endMs": 903 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 178, + "startMs": 741, + "headersMs": 892, + "endMs": 907 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 179, + "startMs": 746, + "headersMs": 896, + "endMs": 900 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 180, + "startMs": 785, + "headersMs": 937, + "endMs": 949 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 181, + "startMs": 884, + "headersMs": 1035, + "endMs": 1043 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 182, + "startMs": 887, + "headersMs": 1038, + "endMs": 1054 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 183, + "startMs": 900, + "headersMs": 1051, + "endMs": 1058 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 184, + "startMs": 903, + "headersMs": 1054, + "endMs": 1064 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 185, + "startMs": 907, + "headersMs": 1057, + "endMs": 1063 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 186, + "startMs": 950, + "headersMs": 1102, + "endMs": 1106 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 187, + "startMs": 1044, + "headersMs": 1196, + "endMs": 1206 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 188, + "startMs": 1054, + "headersMs": 1206, + "endMs": 1231 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 189, + "startMs": 1059, + "headersMs": 1209, + "endMs": 1213 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 190, + "startMs": 1064, + "headersMs": 1215, + "endMs": 1219 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 191, + "startMs": 1065, + "headersMs": 1215, + "endMs": 1231 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 192, + "startMs": 1107, + "headersMs": 1259, + "endMs": 1275 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 193, + "startMs": 1206, + "headersMs": 1361, + "endMs": 1365 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 194, + "startMs": 1213, + "headersMs": 1365, + "endMs": 1369 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 195, + "startMs": 1219, + "headersMs": 1372, + "endMs": 1383 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 196, + "startMs": 1231, + "headersMs": 1383, + "endMs": 1401 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 197, + "startMs": 1232, + "headersMs": 1383, + "endMs": 1388 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 198, + "startMs": 1276, + "headersMs": 1427, + "endMs": 1433 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 199, + "startMs": 1365, + "headersMs": 1519, + "endMs": 1520 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 200, + "startMs": 1369, + "headersMs": 1520, + "endMs": 1524 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 201, + "startMs": 1384, + "headersMs": 1535, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 202, + "startMs": 1388, + "headersMs": 1539, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 203, + "startMs": 1401, + "headersMs": 1553, + "endMs": 1577 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 204, + "startMs": 1434, + "headersMs": 1584, + "endMs": 1680 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 205, + "startMs": 1521, + "headersMs": 1675, + "endMs": 1697 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 206, + "startMs": 1524, + "headersMs": 1676, + "endMs": 2273 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 207, + "startMs": 1540, + "headersMs": 1691, + "endMs": 1711 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 208, + "startMs": 1553, + "headersMs": 1705, + "endMs": 1708 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 209, + "startMs": 2316, + "headersMs": 2467, + "endMs": 2469 + }, + { + "url": "http://127.0.0.1:4685/api/version", + "status": 200, + "bytes": 62, + "index": 210, + "startMs": 2332, + "headersMs": 2483, + "endMs": 2485 + }, + { + "url": "http://127.0.0.1:4685/api/user/sync", + "status": 200, + "bytes": 11, + "index": 211, + "startMs": 2334, + "headersMs": 2488, + "endMs": 2489 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 212, + "startMs": 2337, + "headersMs": 2488, + "endMs": 2533 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 213, + "startMs": 2492, + "headersMs": 2646, + "endMs": 2647 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 214, + "startMs": 2541, + "headersMs": 2693, + "endMs": 2703 + }, + { + "url": "http://127.0.0.1:4685/api/manifest", + "status": 200, + "bytes": 3737, + "index": 215, + "startMs": 2707, + "headersMs": 2861, + "endMs": 2879 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 216, + "startMs": 2903, + "headersMs": 3057, + "endMs": 3651 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 217, + "startMs": 2903, + "headersMs": 3058, + "endMs": 3066 + }, + { + "url": "http://127.0.0.1:4685/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 218, + "startMs": 2903, + "headersMs": 3058, + "endMs": 3066 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 219, + "startMs": 2903, + "headersMs": 3058, + "endMs": 3062 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 220, + "startMs": 2904, + "headersMs": 3058, + "endMs": 3062 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 221, + "startMs": 2904, + "headersMs": 3058, + "endMs": 3066 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 222, + "startMs": 3066, + "headersMs": 3222, + "endMs": 3225 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 223, + "startMs": 3066, + "headersMs": 3223, + "endMs": 3225 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 224, + "startMs": 3068, + "headersMs": 3223, + "endMs": 3227 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 225, + "startMs": 3068, + "headersMs": 3223, + "endMs": 3241 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 226, + "startMs": 3068, + "headersMs": 3223, + "endMs": 3233 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 227, + "startMs": 3227, + "headersMs": 3379, + "endMs": 3383 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 228, + "startMs": 3227, + "headersMs": 3379, + "endMs": 3391 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 229, + "startMs": 3228, + "headersMs": 3379, + "endMs": 3385 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 230, + "startMs": 3234, + "headersMs": 3385, + "endMs": 3397 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 231, + "startMs": 3242, + "headersMs": 3394, + "endMs": 3547 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 232, + "startMs": 3385, + "headersMs": 3538, + "endMs": 3922 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 233, + "startMs": 3387, + "headersMs": 3538, + "endMs": 3636 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 234, + "startMs": 3392, + "headersMs": 3543, + "endMs": 3716 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 235, + "startMs": 3399, + "headersMs": 3550, + "endMs": 3609 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 236, + "startMs": 3550, + "headersMs": 3702, + "endMs": 3859 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 237, + "startMs": 3612, + "headersMs": 3763, + "endMs": 3766 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 238, + "startMs": 3639, + "headersMs": 3790, + "endMs": 3797 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 239, + "startMs": 3655, + "headersMs": 3806, + "endMs": 3821 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 240, + "startMs": 3719, + "headersMs": 3870, + "endMs": 3878 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 241, + "startMs": 3768, + "headersMs": 3919, + "endMs": 3942 + }, + { + "url": "http://127.0.0.1:4685/index.html?v=b556b50667", + "status": 200, + "bytes": 14033, + "index": 242, + "startMs": 3799, + "headersMs": 3951, + "endMs": 4021 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 243, + "startMs": 3823, + "headersMs": 3974, + "endMs": 3974 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 244, + "startMs": 3862, + "headersMs": 4014, + "endMs": 4031 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 245, + "startMs": 3879, + "headersMs": 4031, + "endMs": 4037 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 246, + "startMs": 3924, + "headersMs": 4076, + "endMs": 4087 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 247, + "startMs": 3943, + "headersMs": 4095, + "endMs": 4110 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 248, + "startMs": 3976, + "headersMs": 4126, + "endMs": 4129 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 249, + "startMs": 4024, + "headersMs": 4176, + "endMs": 4179 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 250, + "startMs": 4033, + "headersMs": 4183, + "endMs": 4190 + }, + { + "url": "http://127.0.0.1:4685/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 251, + "startMs": 4038, + "headersMs": 4190, + "endMs": 4211 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 252, + "startMs": 4089, + "headersMs": 4241, + "endMs": 4263 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 253, + "startMs": 4112, + "headersMs": 4264, + "endMs": 4267 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 254, + "startMs": 4131, + "headersMs": 4282, + "endMs": 4286 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 255, + "startMs": 4181, + "headersMs": 4334, + "endMs": 4364 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 256, + "startMs": 4192, + "headersMs": 4344, + "endMs": 4346 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 257, + "startMs": 4213, + "headersMs": 4365, + "endMs": 4368 + }, + { + "url": "http://127.0.0.1:4685/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 258, + "startMs": 4266, + "headersMs": 4417, + "endMs": 4421 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 259, + "startMs": 4268, + "headersMs": 4419, + "endMs": 4421 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 260, + "startMs": 4288, + "headersMs": 4440, + "endMs": 4443 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 261, + "startMs": 4348, + "headersMs": 4499, + "endMs": 4520 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 262, + "startMs": 4366, + "headersMs": 4518, + "endMs": 4523 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 263, + "startMs": 4369, + "headersMs": 4521, + "endMs": 4543 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 264, + "startMs": 4424, + "headersMs": 4574, + "endMs": 4580 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 265, + "startMs": 4424, + "headersMs": 4575, + "endMs": 4589 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 266, + "startMs": 4445, + "headersMs": 4596, + "endMs": 4605 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 267, + "startMs": 4523, + "headersMs": 4674, + "endMs": 4690 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 268, + "startMs": 4525, + "headersMs": 4676, + "endMs": 4697 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 269, + "startMs": 4545, + "headersMs": 4696, + "endMs": 4864 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 270, + "startMs": 4582, + "headersMs": 4734, + "endMs": 4759 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 271, + "startMs": 4591, + "headersMs": 4743, + "endMs": 4763 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 272, + "startMs": 4607, + "headersMs": 4758, + "endMs": 4853 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 273, + "startMs": 4692, + "headersMs": 4844, + "endMs": 4846 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 274, + "startMs": 4876, + "headersMs": 5027, + "endMs": 5072 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 275, + "startMs": 5074, + "headersMs": 5227, + "endMs": 5236 + }, + { + "url": "http://127.0.0.1:4685/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 276, + "startMs": 5903, + "headersMs": 6054, + "endMs": 6061 + }, + { + "url": "http://127.0.0.1:4685/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 277, + "startMs": 5903, + "headersMs": 6055, + "endMs": 6056 + }, + { + "url": "http://127.0.0.1:4685/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 278, + "startMs": 5903, + "headersMs": 6055, + "endMs": 6065 + }, + { + "url": "http://127.0.0.1:4685/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 279, + "startMs": 5903, + "headersMs": 6055, + "endMs": 6056 + }, + { + "url": "http://127.0.0.1:4685/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 280, + "startMs": 5903, + "headersMs": 6055, + "endMs": 6076 + }, + { + "url": "http://127.0.0.1:4685/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 281, + "startMs": 5903, + "headersMs": 6055, + "endMs": 6061 + }, + { + "url": "http://127.0.0.1:4685/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 282, + "startMs": 6059, + "headersMs": 6212, + "endMs": 6219 + }, + { + "url": "http://127.0.0.1:4685/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 283, + "startMs": 6059, + "headersMs": 6213, + "endMs": 6220 + }, + { + "url": "http://127.0.0.1:4685/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 284, + "startMs": 6063, + "headersMs": 6213, + "endMs": 6217 + }, + { + "url": "http://127.0.0.1:4685/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 285, + "startMs": 6063, + "headersMs": 6213, + "endMs": 6220 + }, + { + "url": "http://127.0.0.1:4685/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 286, + "startMs": 6067, + "headersMs": 6218, + "endMs": 6241 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 287, + "startMs": 6078, + "headersMs": 6230, + "endMs": 6342 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 288, + "startMs": 6219, + "headersMs": 6371, + "endMs": 6507 + }, + { + "url": "http://127.0.0.1:4685/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 289, + "startMs": 6220, + "headersMs": 6371, + "endMs": 6386 + }, + { + "url": "http://127.0.0.1:4685/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 290, + "startMs": 6221, + "headersMs": 6373, + "endMs": 6378 + }, + { + "url": "http://127.0.0.1:4685/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 291, + "startMs": 6221, + "headersMs": 6373, + "endMs": 6376 + }, + { + "url": "http://127.0.0.1:4685/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 292, + "startMs": 6243, + "headersMs": 6394, + "endMs": 6396 + }, + { + "url": "http://127.0.0.1:4685/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 293, + "startMs": 6344, + "headersMs": 6497, + "endMs": 6503 + }, + { + "url": "http://127.0.0.1:4685/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 294, + "startMs": 6378, + "headersMs": 6530, + "endMs": 6542 + }, + { + "url": "http://127.0.0.1:4685/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 295, + "startMs": 6379, + "headersMs": 6530, + "endMs": 6540 + }, + { + "url": "http://127.0.0.1:4685/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 296, + "startMs": 6388, + "headersMs": 6538, + "endMs": 6561 + }, + { + "url": "http://127.0.0.1:4685/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 297, + "startMs": 6398, + "headersMs": 6550, + "endMs": 6555 + }, + { + "url": "http://127.0.0.1:4685/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 298, + "startMs": 6505, + "headersMs": 6658, + "endMs": 6666 + }, + { + "url": "http://127.0.0.1:4685/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 299, + "startMs": 6508, + "headersMs": 6659, + "endMs": 6672 + }, + { + "url": "http://127.0.0.1:4685/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 300, + "startMs": 6542, + "headersMs": 6693, + "endMs": 6701 + }, + { + "url": "http://127.0.0.1:4685/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 301, + "startMs": 6543, + "headersMs": 6693, + "endMs": 6698 + }, + { + "url": "http://127.0.0.1:4685/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 302, + "startMs": 6558, + "headersMs": 6710, + "endMs": 6723 + }, + { + "url": "http://127.0.0.1:4685/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 303, + "startMs": 6563, + "headersMs": 6714, + "endMs": 6734 + }, + { + "url": "http://127.0.0.1:4685/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 304, + "startMs": 6668, + "headersMs": 6822, + "endMs": 6841 + }, + { + "url": "http://127.0.0.1:4685/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 305, + "startMs": 6674, + "headersMs": 6824, + "endMs": 6869 + }, + { + "url": "http://127.0.0.1:4685/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 306, + "startMs": 6700, + "headersMs": 6850, + "endMs": 6866 + }, + { + "url": "http://127.0.0.1:4685/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 307, + "startMs": 6703, + "headersMs": 6853, + "endMs": 6874 + }, + { + "url": "http://127.0.0.1:4685/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 308, + "startMs": 6725, + "headersMs": 6876, + "endMs": 6890 + }, + { + "url": "http://127.0.0.1:4685/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 309, + "startMs": 6736, + "headersMs": 6886, + "endMs": 6900 + }, + { + "url": "http://127.0.0.1:4685/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 310, + "startMs": 6843, + "headersMs": 6997, + "endMs": 7035 + }, + { + "url": "http://127.0.0.1:4685/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 311, + "startMs": 6868, + "headersMs": 7020, + "endMs": 7047 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 312, + "startMs": 6871, + "headersMs": 7021, + "endMs": 7029 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 313, + "startMs": 6876, + "headersMs": 7026, + "endMs": 7031 + }, + { + "url": "http://127.0.0.1:4685/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 314, + "startMs": 6891, + "headersMs": 7042, + "endMs": 7073 + }, + { + "url": "http://127.0.0.1:4685/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 315, + "startMs": 6902, + "headersMs": 7053, + "endMs": 7279 + }, + { + "url": "http://127.0.0.1:4685/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 316, + "startMs": 7031, + "headersMs": 7186, + "endMs": 7198 + }, + { + "url": "http://127.0.0.1:4685/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 317, + "startMs": 7032, + "headersMs": 7186, + "endMs": 7192 + }, + { + "url": "http://127.0.0.1:4685/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 318, + "startMs": 7037, + "headersMs": 7189, + "endMs": 7228 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 231, + "responseStart": 390, + "end": 390, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 231, + "responseStart": 401, + "end": 401, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 232, + "responseStart": 408, + "end": 409, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 232, + "responseStart": 555, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 232, + "responseStart": 554, + "end": 556, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "bytes": 983, + "start": 232, + "responseStart": 565, + "end": 566, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 232, + "responseStart": 575, + "end": 576, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 233, + "responseStart": 713, + "end": 713, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 234, + "responseStart": 712, + "end": 712, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 234, + "responseStart": 713, + "end": 713, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 234, + "responseStart": 725, + "end": 725, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 234, + "responseStart": 729, + "end": 729, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 234, + "responseStart": 867, + "end": 867, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 235, + "responseStart": 871, + "end": 871, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 235, + "responseStart": 884, + "end": 884, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 235, + "responseStart": 887, + "end": 887, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 235, + "responseStart": 890, + "end": 891, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 235, + "responseStart": 933, + "end": 934, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 236, + "responseStart": 1027, + "end": 1028, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 236, + "responseStart": 1038, + "end": 1038, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 236, + "responseStart": 1042, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 236, + "responseStart": 1047, + "end": 1047, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 236, + "responseStart": 1048, + "end": 1049, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 236, + "responseStart": 1090, + "end": 1091, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 236, + "responseStart": 1190, + "end": 1190, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 236, + "responseStart": 1215, + "end": 1215, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 237, + "responseStart": 1197, + "end": 1197, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 237, + "responseStart": 1203, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 237, + "responseStart": 1215, + "end": 1215, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 237, + "responseStart": 1259, + "end": 1260, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 237, + "responseStart": 1349, + "end": 1349, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 237, + "responseStart": 1353, + "end": 1353, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 237, + "responseStart": 1367, + "end": 1367, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 237, + "responseStart": 1385, + "end": 1385, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 238, + "responseStart": 1372, + "end": 1372, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 238, + "responseStart": 1417, + "end": 1417, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 238, + "responseStart": 1504, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 238, + "responseStart": 1508, + "end": 1508, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 238, + "responseStart": 1523, + "end": 1524, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 238, + "responseStart": 1537, + "end": 1537, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 238, + "responseStart": 1561, + "end": 1561, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 238, + "responseStart": 1664, + "end": 1665, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 238, + "responseStart": 1681, + "end": 1682, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "bytes": 118521, + "start": 239, + "responseStart": 1979, + "end": 2258, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 404, + "responseStart": 1695, + "end": 1696, + "initiator": "link" + } + ] + }, + { + "fcp": 1731, + "requests": [ + { + "url": "http://127.0.0.1:4685/?v=benchmedia01", + "status": 200, + "bytes": 14033, + "index": 319, + "startMs": 17, + "headersMs": 169, + "endMs": 240 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 320, + "startMs": 247, + "headersMs": 399, + "endMs": 784 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 321, + "startMs": 247, + "headersMs": 399, + "endMs": 573 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 322, + "startMs": 248, + "headersMs": 399, + "endMs": 416 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 323, + "startMs": 248, + "headersMs": 400, + "endMs": 402 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 324, + "startMs": 248, + "headersMs": 400, + "endMs": 568 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 325, + "startMs": 248, + "headersMs": 400, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 326, + "startMs": 403, + "headersMs": 556, + "endMs": 585 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 327, + "startMs": 417, + "headersMs": 570, + "endMs": 571 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 328, + "startMs": 423, + "headersMs": 573, + "endMs": 578 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 329, + "startMs": 570, + "headersMs": 722, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 330, + "startMs": 571, + "headersMs": 722, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 331, + "startMs": 573, + "headersMs": 723, + "endMs": 726 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 332, + "startMs": 579, + "headersMs": 729, + "endMs": 737 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 333, + "startMs": 586, + "headersMs": 738, + "endMs": 740 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 334, + "startMs": 728, + "headersMs": 880, + "endMs": 882 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 335, + "startMs": 728, + "headersMs": 881, + "endMs": 888 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 336, + "startMs": 728, + "headersMs": 881, + "endMs": 903 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 337, + "startMs": 738, + "headersMs": 888, + "endMs": 903 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 338, + "startMs": 740, + "headersMs": 892, + "endMs": 896 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 339, + "startMs": 785, + "headersMs": 936, + "endMs": 949 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 340, + "startMs": 883, + "headersMs": 1034, + "endMs": 1042 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 341, + "startMs": 889, + "headersMs": 1040, + "endMs": 1056 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 342, + "startMs": 896, + "headersMs": 1047, + "endMs": 1053 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 343, + "startMs": 904, + "headersMs": 1054, + "endMs": 1064 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 344, + "startMs": 904, + "headersMs": 1054, + "endMs": 1061 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 345, + "startMs": 950, + "headersMs": 1102, + "endMs": 1106 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 346, + "startMs": 1043, + "headersMs": 1195, + "endMs": 1205 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 347, + "startMs": 1054, + "headersMs": 1205, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 348, + "startMs": 1056, + "headersMs": 1207, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 349, + "startMs": 1062, + "headersMs": 1214, + "endMs": 1217 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 350, + "startMs": 1064, + "headersMs": 1214, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 351, + "startMs": 1107, + "headersMs": 1258, + "endMs": 1273 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 352, + "startMs": 1206, + "headersMs": 1358, + "endMs": 1362 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 353, + "startMs": 1211, + "headersMs": 1362, + "endMs": 1366 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 354, + "startMs": 1217, + "headersMs": 1369, + "endMs": 1380 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 355, + "startMs": 1231, + "headersMs": 1381, + "endMs": 1400 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 356, + "startMs": 1231, + "headersMs": 1382, + "endMs": 1386 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 357, + "startMs": 1274, + "headersMs": 1426, + "endMs": 1431 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 358, + "startMs": 1362, + "headersMs": 1514, + "endMs": 1516 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 359, + "startMs": 1366, + "headersMs": 1517, + "endMs": 1520 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 360, + "startMs": 1380, + "headersMs": 1532, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 361, + "startMs": 1387, + "headersMs": 1537, + "endMs": 1550 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 362, + "startMs": 1401, + "headersMs": 1554, + "endMs": 1576 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 363, + "startMs": 1432, + "headersMs": 1583, + "endMs": 1678 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 364, + "startMs": 1517, + "headersMs": 1668, + "endMs": 1690 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 365, + "startMs": 1520, + "headersMs": 1671, + "endMs": 2263 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 366, + "startMs": 1537, + "headersMs": 1689, + "endMs": 1709 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 367, + "startMs": 1551, + "headersMs": 1703, + "endMs": 1706 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 368, + "startMs": 2302, + "headersMs": 2454, + "endMs": 2455 + }, + { + "url": "http://127.0.0.1:4685/api/version", + "status": 200, + "bytes": 62, + "index": 369, + "startMs": 2320, + "headersMs": 2473, + "endMs": 2474 + }, + { + "url": "http://127.0.0.1:4685/api/user/sync", + "status": 200, + "bytes": 11, + "index": 370, + "startMs": 2321, + "headersMs": 2475, + "endMs": 2476 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 371, + "startMs": 2325, + "headersMs": 2476, + "endMs": 2521 + }, + { + "url": "http://127.0.0.1:4685/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 372, + "startMs": 2480, + "headersMs": 2631, + "endMs": 2632 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 373, + "startMs": 2528, + "headersMs": 2680, + "endMs": 2689 + }, + { + "url": "http://127.0.0.1:4685/api/manifest", + "status": 200, + "bytes": 3737, + "index": 374, + "startMs": 2694, + "headersMs": 2847, + "endMs": 2866 + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 375, + "startMs": 2889, + "headersMs": 3040, + "endMs": 3632 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 376, + "startMs": 2889, + "headersMs": 3041, + "endMs": 3050 + }, + { + "url": "http://127.0.0.1:4685/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 377, + "startMs": 2889, + "headersMs": 3041, + "endMs": 3048 + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 378, + "startMs": 2889, + "headersMs": 3041, + "endMs": 3045 + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 379, + "startMs": 2890, + "headersMs": 3042, + "endMs": 3045 + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 380, + "startMs": 2890, + "headersMs": 3043, + "endMs": 3049 + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 381, + "startMs": 3047, + "headersMs": 3200, + "endMs": 3203 + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 382, + "startMs": 3048, + "headersMs": 3200, + "endMs": 3203 + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 383, + "startMs": 3049, + "headersMs": 3200, + "endMs": 3204 + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 384, + "startMs": 3050, + "headersMs": 3200, + "endMs": 3218 + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 385, + "startMs": 3052, + "headersMs": 3203, + "endMs": 3214 + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 386, + "startMs": 3205, + "headersMs": 3356, + "endMs": 3360 + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 387, + "startMs": 3205, + "headersMs": 3356, + "endMs": 3369 + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 388, + "startMs": 3206, + "headersMs": 3357, + "endMs": 3363 + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 389, + "startMs": 3215, + "headersMs": 3367, + "endMs": 3380 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 390, + "startMs": 3219, + "headersMs": 3371, + "endMs": 3524 + }, + { + "url": "http://127.0.0.1:4685/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 391, + "startMs": 3363, + "headersMs": 3516, + "endMs": 3901 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 392, + "startMs": 3365, + "headersMs": 3517, + "endMs": 3615 + }, + { + "url": "http://127.0.0.1:4685/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 393, + "startMs": 3371, + "headersMs": 3521, + "endMs": 3695 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 394, + "startMs": 3382, + "headersMs": 3533, + "endMs": 3592 + }, + { + "url": "http://127.0.0.1:4685/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 395, + "startMs": 3527, + "headersMs": 3678, + "endMs": 3836 + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 396, + "startMs": 3594, + "headersMs": 3746, + "endMs": 3749 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 397, + "startMs": 3617, + "headersMs": 3768, + "endMs": 3777 + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 398, + "startMs": 3637, + "headersMs": 3788, + "endMs": 3802 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 399, + "startMs": 3697, + "headersMs": 3848, + "endMs": 3857 + }, + { + "url": "http://127.0.0.1:4685/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 400, + "startMs": 3751, + "headersMs": 3903, + "endMs": 3927 + }, + { + "url": "http://127.0.0.1:4685/index.html?v=b556b50667", + "status": 200, + "bytes": 14033, + "index": 401, + "startMs": 3779, + "headersMs": 3930, + "endMs": 4001 + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 402, + "startMs": 3804, + "headersMs": 3955, + "endMs": 3956 + }, + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 403, + "startMs": 3839, + "headersMs": 3990, + "endMs": 4005 + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 404, + "startMs": 3858, + "headersMs": 4009, + "endMs": 4016 + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 405, + "startMs": 3903, + "headersMs": 4054, + "endMs": 4065 + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 406, + "startMs": 3929, + "headersMs": 4080, + "endMs": 4096 + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 407, + "startMs": 3958, + "headersMs": 4109, + "endMs": 4112 + }, + { + "url": "http://127.0.0.1:4685/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 408, + "startMs": 4004, + "headersMs": 4155, + "endMs": 4158 + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 409, + "startMs": 4007, + "headersMs": 4158, + "endMs": 4163 + }, + { + "url": "http://127.0.0.1:4685/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 410, + "startMs": 4017, + "headersMs": 4168, + "endMs": 4189 + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 411, + "startMs": 4067, + "headersMs": 4218, + "endMs": 4241 + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 4098, + "headersMs": 4250, + "endMs": 4254 + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 413, + "startMs": 4114, + "headersMs": 4265, + "endMs": 4270 + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 414, + "startMs": 4159, + "headersMs": 4311, + "endMs": 4341 + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 415, + "startMs": 4164, + "headersMs": 4315, + "endMs": 4317 + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 416, + "startMs": 4191, + "headersMs": 4342, + "endMs": 4345 + }, + { + "url": "http://127.0.0.1:4685/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 417, + "startMs": 4243, + "headersMs": 4394, + "endMs": 4399 + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 418, + "startMs": 4255, + "headersMs": 4406, + "endMs": 4409 + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 419, + "startMs": 4271, + "headersMs": 4422, + "endMs": 4427 + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 420, + "startMs": 4319, + "headersMs": 4470, + "endMs": 4492 + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 421, + "startMs": 4343, + "headersMs": 4493, + "endMs": 4499 + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 422, + "startMs": 4346, + "headersMs": 4497, + "endMs": 4521 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 423, + "startMs": 4401, + "headersMs": 4552, + "endMs": 4558 + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 424, + "startMs": 4411, + "headersMs": 4562, + "endMs": 4577 + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 425, + "startMs": 4429, + "headersMs": 4579, + "endMs": 4587 + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 426, + "startMs": 4494, + "headersMs": 4646, + "endMs": 4663 + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 427, + "startMs": 4500, + "headersMs": 4652, + "endMs": 4675 + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 428, + "startMs": 4523, + "headersMs": 4675, + "endMs": 4842 + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 429, + "startMs": 4560, + "headersMs": 4712, + "endMs": 4737 + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 430, + "startMs": 4579, + "headersMs": 4732, + "endMs": 4753 + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 431, + "startMs": 4589, + "headersMs": 4740, + "endMs": 4835 + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 432, + "startMs": 4665, + "headersMs": 4816, + "endMs": 4818 + }, + { + "url": "http://127.0.0.1:4685/sw.js", + "status": 200, + "bytes": 8989, + "index": 433, + "startMs": 4853, + "headersMs": 5004, + "endMs": 5049 + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 434, + "startMs": 5052, + "headersMs": 5203, + "endMs": 5213 + }, + { + "url": "http://127.0.0.1:4685/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 435, + "startMs": 5880, + "headersMs": 6032, + "endMs": 6039 + }, + { + "url": "http://127.0.0.1:4685/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 436, + "startMs": 5880, + "headersMs": 6032, + "endMs": 6034 + }, + { + "url": "http://127.0.0.1:4685/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 437, + "startMs": 5880, + "headersMs": 6032, + "endMs": 6043 + }, + { + "url": "http://127.0.0.1:4685/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 438, + "startMs": 5880, + "headersMs": 6032, + "endMs": 6033 + }, + { + "url": "http://127.0.0.1:4685/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 439, + "startMs": 5880, + "headersMs": 6032, + "endMs": 6055 + }, + { + "url": "http://127.0.0.1:4685/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 440, + "startMs": 5880, + "headersMs": 6033, + "endMs": 6039 + }, + { + "url": "http://127.0.0.1:4685/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 441, + "startMs": 6035, + "headersMs": 6188, + "endMs": 6194 + }, + { + "url": "http://127.0.0.1:4685/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 442, + "startMs": 6036, + "headersMs": 6188, + "endMs": 6195 + }, + { + "url": "http://127.0.0.1:4685/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 443, + "startMs": 6041, + "headersMs": 6191, + "endMs": 6196 + }, + { + "url": "http://127.0.0.1:4685/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 444, + "startMs": 6041, + "headersMs": 6191, + "endMs": 6198 + }, + { + "url": "http://127.0.0.1:4685/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 445, + "startMs": 6044, + "headersMs": 6195, + "endMs": 6219 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 446, + "startMs": 6056, + "headersMs": 6207, + "endMs": 6316 + }, + { + "url": "http://127.0.0.1:4685/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 447, + "startMs": 6197, + "headersMs": 6348, + "endMs": 6484 + }, + { + "url": "http://127.0.0.1:4685/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 448, + "startMs": 6197, + "headersMs": 6348, + "endMs": 6364 + }, + { + "url": "http://127.0.0.1:4685/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 449, + "startMs": 6198, + "headersMs": 6348, + "endMs": 6354 + }, + { + "url": "http://127.0.0.1:4685/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 450, + "startMs": 6199, + "headersMs": 6349, + "endMs": 6352 + }, + { + "url": "http://127.0.0.1:4685/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 451, + "startMs": 6221, + "headersMs": 6371, + "endMs": 6374 + }, + { + "url": "http://127.0.0.1:4685/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 452, + "startMs": 6320, + "headersMs": 6472, + "endMs": 6478 + }, + { + "url": "http://127.0.0.1:4685/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 453, + "startMs": 6354, + "headersMs": 6505, + "endMs": 6517 + }, + { + "url": "http://127.0.0.1:4685/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 454, + "startMs": 6355, + "headersMs": 6507, + "endMs": 6517 + }, + { + "url": "http://127.0.0.1:4685/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 455, + "startMs": 6365, + "headersMs": 6517, + "endMs": 6539 + }, + { + "url": "http://127.0.0.1:4685/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 456, + "startMs": 6375, + "headersMs": 6526, + "endMs": 6531 + }, + { + "url": "http://127.0.0.1:4685/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 457, + "startMs": 6480, + "headersMs": 6632, + "endMs": 6639 + }, + { + "url": "http://127.0.0.1:4685/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 458, + "startMs": 6486, + "headersMs": 6636, + "endMs": 6650 + }, + { + "url": "http://127.0.0.1:4685/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 459, + "startMs": 6519, + "headersMs": 6670, + "endMs": 6678 + }, + { + "url": "http://127.0.0.1:4685/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 460, + "startMs": 6519, + "headersMs": 6671, + "endMs": 6675 + }, + { + "url": "http://127.0.0.1:4685/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 461, + "startMs": 6533, + "headersMs": 6683, + "endMs": 6697 + }, + { + "url": "http://127.0.0.1:4685/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 462, + "startMs": 6541, + "headersMs": 6691, + "endMs": 6711 + }, + { + "url": "http://127.0.0.1:4685/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 463, + "startMs": 6641, + "headersMs": 6794, + "endMs": 6812 + }, + { + "url": "http://127.0.0.1:4685/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 464, + "startMs": 6652, + "headersMs": 6803, + "endMs": 6848 + }, + { + "url": "http://127.0.0.1:4685/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 465, + "startMs": 6677, + "headersMs": 6828, + "endMs": 6842 + }, + { + "url": "http://127.0.0.1:4685/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 466, + "startMs": 6680, + "headersMs": 6830, + "endMs": 6851 + }, + { + "url": "http://127.0.0.1:4685/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 467, + "startMs": 6699, + "headersMs": 6850, + "endMs": 6864 + }, + { + "url": "http://127.0.0.1:4685/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 468, + "startMs": 6713, + "headersMs": 6864, + "endMs": 6877 + }, + { + "url": "http://127.0.0.1:4685/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 469, + "startMs": 6814, + "headersMs": 6965, + "endMs": 7003 + }, + { + "url": "http://127.0.0.1:4685/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 470, + "startMs": 6845, + "headersMs": 6998, + "endMs": 7025 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 471, + "startMs": 6850, + "headersMs": 7001, + "endMs": 7009 + }, + { + "url": "http://127.0.0.1:4685/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 472, + "startMs": 6853, + "headersMs": 7004, + "endMs": 7009 + }, + { + "url": "http://127.0.0.1:4685/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 473, + "startMs": 6865, + "headersMs": 7017, + "endMs": 7048 + }, + { + "url": "http://127.0.0.1:4685/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 474, + "startMs": 6879, + "headersMs": 7030, + "endMs": 7256 + }, + { + "url": "http://127.0.0.1:4685/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 475, + "startMs": 7006, + "headersMs": 7159, + "endMs": 7172 + }, + { + "url": "http://127.0.0.1:4685/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 476, + "startMs": 7011, + "headersMs": 7162, + "endMs": 7168 + }, + { + "url": "http://127.0.0.1:4685/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 477, + "startMs": 7011, + "headersMs": 7162, + "endMs": 7199 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4685/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 230, + "responseStart": 400, + "end": 400, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 231, + "responseStart": 386, + "end": 386, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 231, + "responseStart": 406, + "end": 407, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 231, + "responseStart": 552, + "end": 553, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 231, + "responseStart": 554, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/recommendations.css?v=055101368d", + "bytes": 983, + "start": 231, + "responseStart": 562, + "end": 562, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 231, + "responseStart": 569, + "end": 569, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 231, + "responseStart": 710, + "end": 711, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 231, + "responseStart": 710, + "end": 711, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 231, + "responseStart": 711, + "end": 711, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 232, + "responseStart": 721, + "end": 722, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 232, + "responseStart": 724, + "end": 724, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 232, + "responseStart": 866, + "end": 867, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4685/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 232, + "responseStart": 872, + "end": 873, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 232, + "responseStart": 887, + "end": 887, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 232, + "responseStart": 887, + "end": 888, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 233, + "responseStart": 879, + "end": 880, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 233, + "responseStart": 933, + "end": 933, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 233, + "responseStart": 1026, + "end": 1026, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 233, + "responseStart": 1037, + "end": 1037, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 233, + "responseStart": 1040, + "end": 1040, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 233, + "responseStart": 1045, + "end": 1045, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 233, + "responseStart": 1047, + "end": 1048, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 233, + "responseStart": 1090, + "end": 1090, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 233, + "responseStart": 1189, + "end": 1189, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 233, + "responseStart": 1214, + "end": 1215, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 234, + "responseStart": 1194, + "end": 1195, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 234, + "responseStart": 1201, + "end": 1201, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 234, + "responseStart": 1213, + "end": 1214, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 234, + "responseStart": 1257, + "end": 1257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 234, + "responseStart": 1345, + "end": 1346, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 234, + "responseStart": 1350, + "end": 1350, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 234, + "responseStart": 1363, + "end": 1363, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 234, + "responseStart": 1370, + "end": 1370, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 234, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 235, + "responseStart": 1415, + "end": 1415, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 235, + "responseStart": 1500, + "end": 1501, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 235, + "responseStart": 1504, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 235, + "responseStart": 1520, + "end": 1520, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 235, + "responseStart": 1534, + "end": 1534, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 235, + "responseStart": 1560, + "end": 1561, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 235, + "responseStart": 1662, + "end": 1663, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 235, + "responseStart": 1674, + "end": 1675, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/app.js?v=f485286cbc", + "bytes": 118521, + "start": 235, + "responseStart": 1981, + "end": 2248, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4685/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 404, + "responseStart": 1692, + "end": 1693, + "initiator": "link" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-bisect-before-loader.json b/perf/results/phase6-bisect-before-loader.json new file mode 100644 index 0000000..405e7b9 --- /dev/null +++ b/perf/results/phase6-bisect-before-loader.json @@ -0,0 +1,8538 @@ +{ + "date": "2026-10-08T00:40:27.954Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-before-loader", + "sourceCommit": "d98d4445521efdea8ea09b4751936d9cd8f8b5a7", + "frontendBuildTag": "6974ad79723f", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 171, + "min": 171, + "max": 171, + "values": [ + 171, + 171, + 171 + ] + }, + "wireBytes": { + "median": 1191686, + "min": 1191686, + "max": 1191686, + "values": [ + 1191686, + 1191686, + 1191686 + ] + }, + "fcp": { + "median": 1032, + "min": 1029, + "max": 1317, + "values": [ + 1317, + 1032, + 1029 + ] + }, + "lcp": { + "median": 1226, + "min": 1222, + "max": 1500, + "values": [ + 1500, + 1226, + 1222 + ] + }, + "domContentLoaded": { + "median": 3241, + "min": 3234, + "max": 4505, + "values": [ + 4505, + 3241, + 3234 + ] + }, + "bootDone": { + "median": 3267, + "min": 3247, + "max": 4519, + "values": [ + 4519, + 3267, + 3247 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 32460, + "min": 32429, + "max": 33709, + "values": [ + 33709, + 32429, + 32460 + ] + }, + "swInstallBytes": { + "median": 1191686, + "min": 1191686, + "max": 1191686, + "values": [ + 1191686, + 1191686, + 1191686 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 23000, + "js": 603754, + "css": 156688, + "fonts": 397072, + "images": 6278, + "media": 0, + "api": 3328, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5776/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 1, + "startMs": 18, + "headersMs": 226, + "endMs": 286 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 2, + "startMs": 294, + "headersMs": 453, + "endMs": 455 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 3, + "startMs": 296, + "headersMs": 454, + "endMs": 839 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 4, + "startMs": 297, + "headersMs": 629, + "endMs": 796 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 5, + "startMs": 297, + "headersMs": 645, + "endMs": 669 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 6, + "startMs": 298, + "headersMs": 672, + "endMs": 702 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 7, + "startMs": 298, + "headersMs": 704, + "endMs": 736 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 8, + "startMs": 456, + "headersMs": 729, + "endMs": 751 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 9, + "startMs": 670, + "headersMs": 827, + "endMs": 832 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 10, + "startMs": 703, + "headersMs": 858, + "endMs": 864 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 11, + "startMs": 737, + "headersMs": 891, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 12, + "startMs": 752, + "headersMs": 905, + "endMs": 908 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 13, + "startMs": 799, + "headersMs": 953, + "endMs": 955 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 14, + "startMs": 834, + "headersMs": 989, + "endMs": 996 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 15, + "startMs": 839, + "headersMs": 994, + "endMs": 997 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 16, + "startMs": 865, + "headersMs": 1024, + "endMs": 1034 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 17, + "startMs": 894, + "headersMs": 1049, + "endMs": 1055 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 18, + "startMs": 909, + "headersMs": 1065, + "endMs": 1074 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 19, + "startMs": 956, + "headersMs": 1109, + "endMs": 1112 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 20, + "startMs": 996, + "headersMs": 1150, + "endMs": 1153 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 21, + "startMs": 997, + "headersMs": 1188, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 22, + "startMs": 1035, + "headersMs": 1216, + "endMs": 1244 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 23, + "startMs": 1055, + "headersMs": 1222, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 24, + "startMs": 1075, + "headersMs": 1242, + "endMs": 1264 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 25, + "startMs": 1113, + "headersMs": 1272, + "endMs": 1284 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 26, + "startMs": 1154, + "headersMs": 1314, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 27, + "startMs": 1229, + "headersMs": 1383, + "endMs": 1387 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 28, + "startMs": 1229, + "headersMs": 1391, + "endMs": 1404 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 29, + "startMs": 1244, + "headersMs": 1401, + "endMs": 1409 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 30, + "startMs": 1265, + "headersMs": 1424, + "endMs": 1439 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 31, + "startMs": 1285, + "headersMs": 1443, + "endMs": 1452 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 32, + "startMs": 1331, + "headersMs": 1492, + "endMs": 1507 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 33, + "startMs": 1388, + "headersMs": 1543, + "endMs": 1550 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 34, + "startMs": 1405, + "headersMs": 1566, + "endMs": 1576 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 35, + "startMs": 1410, + "headersMs": 1572, + "endMs": 1578 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 36, + "startMs": 1440, + "headersMs": 1607, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 37, + "startMs": 1453, + "headersMs": 1612, + "endMs": 1621 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 38, + "startMs": 1508, + "headersMs": 1670, + "endMs": 1684 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 39, + "startMs": 1551, + "headersMs": 1707, + "endMs": 1712 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 40, + "startMs": 1577, + "headersMs": 1737, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 41, + "startMs": 1579, + "headersMs": 1754, + "endMs": 1780 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 42, + "startMs": 1622, + "headersMs": 1776, + "endMs": 1779 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 43, + "startMs": 1631, + "headersMs": 1785, + "endMs": 1789 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 44, + "startMs": 1684, + "headersMs": 1847, + "endMs": 1862 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 45, + "startMs": 1713, + "headersMs": 1879, + "endMs": 1895 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 46, + "startMs": 1748, + "headersMs": 1904, + "endMs": 1911 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 47, + "startMs": 1781, + "headersMs": 1938, + "endMs": 1946 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 48, + "startMs": 1781, + "headersMs": 1954, + "endMs": 1977 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 49, + "startMs": 1790, + "headersMs": 1957, + "endMs": 1961 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 50, + "startMs": 1863, + "headersMs": 2020, + "endMs": 2025 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 51, + "startMs": 1895, + "headersMs": 2055, + "endMs": 2066 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 52, + "startMs": 1912, + "headersMs": 2079, + "endMs": 2098 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 53, + "startMs": 1947, + "headersMs": 2102, + "endMs": 2106 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 54, + "startMs": 1962, + "headersMs": 2118, + "endMs": 2125 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 55, + "startMs": 1978, + "headersMs": 2144, + "endMs": 2161 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 56, + "startMs": 2025, + "headersMs": 2183, + "endMs": 2191 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 57, + "startMs": 2067, + "headersMs": 2237, + "endMs": 2261 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 58, + "startMs": 2099, + "headersMs": 2254, + "endMs": 2260 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 59, + "startMs": 2107, + "headersMs": 2264, + "endMs": 2272 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 60, + "startMs": 2125, + "headersMs": 2284, + "endMs": 2298 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 61, + "startMs": 2162, + "headersMs": 2322, + "endMs": 2333 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 62, + "startMs": 2192, + "headersMs": 2347, + "endMs": 2353 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 63, + "startMs": 2261, + "headersMs": 2418, + "endMs": 2427 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 64, + "startMs": 2261, + "headersMs": 2422, + "endMs": 2429 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 65, + "startMs": 2273, + "headersMs": 2427, + "endMs": 2431 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 66, + "startMs": 2298, + "headersMs": 2466, + "endMs": 2486 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 67, + "startMs": 2333, + "headersMs": 2496, + "endMs": 2510 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 68, + "startMs": 2355, + "headersMs": 2514, + "endMs": 2525 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 69, + "startMs": 2428, + "headersMs": 2583, + "endMs": 2586 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 70, + "startMs": 2430, + "headersMs": 2586, + "endMs": 2591 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 71, + "startMs": 2432, + "headersMs": 3574, + "endMs": 4399 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 72, + "startMs": 2487, + "headersMs": 3574, + "endMs": 3749 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 2511, + "headersMs": 3575, + "endMs": 3732 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 74, + "startMs": 2526, + "headersMs": 3583, + "endMs": 3587 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 75, + "startMs": 4447, + "headersMs": 4601, + "endMs": 4602 + }, + { + "url": "http://127.0.0.1:5776/api/version", + "status": 200, + "bytes": 62, + "index": 76, + "startMs": 4510, + "headersMs": 4661, + "endMs": 4663 + }, + { + "url": "http://127.0.0.1:5776/api/user/sync", + "status": 200, + "bytes": 11, + "index": 77, + "startMs": 4513, + "headersMs": 4669, + "endMs": 4671 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 78, + "startMs": 4524, + "headersMs": 4699, + "endMs": 4740 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 79, + "startMs": 4673, + "headersMs": 4825, + "endMs": 4826 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 80, + "startMs": 4747, + "headersMs": 4899, + "endMs": 4909 + }, + { + "url": "http://127.0.0.1:5776/api/manifest", + "status": 200, + "bytes": 3207, + "index": 81, + "startMs": 4913, + "headersMs": 5076, + "endMs": 5093 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 82, + "startMs": 5124, + "headersMs": 5279, + "endMs": 6102 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 83, + "startMs": 5124, + "headersMs": 5280, + "endMs": 5290 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 84, + "startMs": 5124, + "headersMs": 5281, + "endMs": 5285 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 85, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5284 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 86, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5288 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 87, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5284 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 88, + "startMs": 5286, + "headersMs": 5440, + "endMs": 5450 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 89, + "startMs": 5286, + "headersMs": 5440, + "endMs": 5446 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 90, + "startMs": 5287, + "headersMs": 5440, + "endMs": 5442 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 91, + "startMs": 5289, + "headersMs": 5441, + "endMs": 5463 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 92, + "startMs": 5291, + "headersMs": 5441, + "endMs": 5448 + }, + { + "url": "http://127.0.0.1:5776/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 93, + "startMs": 5444, + "headersMs": 5600, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 94, + "startMs": 5448, + "headersMs": 5600, + "endMs": 5607 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 96, + "startMs": 5451, + "headersMs": 5603, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 95, + "startMs": 5449, + "headersMs": 5603, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 97, + "startMs": 5464, + "headersMs": 5616, + "endMs": 5620 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 98, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5776 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 99, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5768 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 100, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5766 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 101, + "startMs": 5608, + "headersMs": 5759, + "endMs": 5767 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 102, + "startMs": 5622, + "headersMs": 5773, + "endMs": 5796 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 103, + "startMs": 5768, + "headersMs": 5920, + "endMs": 5926 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 104, + "startMs": 5769, + "headersMs": 5920, + "endMs": 5933 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 105, + "startMs": 5769, + "headersMs": 5920, + "endMs": 6075 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 106, + "startMs": 5778, + "headersMs": 5928, + "endMs": 6312 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 107, + "startMs": 5799, + "headersMs": 5950, + "endMs": 6049 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 108, + "startMs": 5929, + "headersMs": 6081, + "endMs": 6256 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 109, + "startMs": 5934, + "headersMs": 6085, + "endMs": 6144 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 110, + "startMs": 6051, + "headersMs": 6202, + "endMs": 6360 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 111, + "startMs": 6077, + "headersMs": 6228, + "endMs": 6337 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 112, + "startMs": 6107, + "headersMs": 6258, + "endMs": 6394 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 113, + "startMs": 6147, + "headersMs": 6298, + "endMs": 6301 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 114, + "startMs": 6258, + "headersMs": 6411, + "endMs": 6420 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 115, + "startMs": 6303, + "headersMs": 6454, + "endMs": 6468 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 116, + "startMs": 6314, + "headersMs": 6466, + "endMs": 6482 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 117, + "startMs": 6339, + "headersMs": 6490, + "endMs": 6495 + }, + { + "url": "http://127.0.0.1:5776/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 118, + "startMs": 6362, + "headersMs": 6516, + "endMs": 6519 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 119, + "startMs": 6396, + "headersMs": 6547, + "endMs": 6556 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 120, + "startMs": 6422, + "headersMs": 6574, + "endMs": 6598 + }, + { + "url": "http://127.0.0.1:5776/index.html?v=ca12d59818", + "status": 200, + "bytes": 11500, + "index": 121, + "startMs": 6470, + "headersMs": 6623, + "endMs": 6681 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 122, + "startMs": 6484, + "headersMs": 6635, + "endMs": 6642 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 123, + "startMs": 6497, + "headersMs": 6648, + "endMs": 6658 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 124, + "startMs": 6521, + "headersMs": 6672, + "endMs": 6674 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 125, + "startMs": 6558, + "headersMs": 6711, + "endMs": 6716 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 126, + "startMs": 6600, + "headersMs": 6752, + "endMs": 6768 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 127, + "startMs": 6644, + "headersMs": 6795, + "endMs": 6799 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 128, + "startMs": 6661, + "headersMs": 6814, + "endMs": 6827 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 129, + "startMs": 6676, + "headersMs": 6827, + "endMs": 6830 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 6684, + "headersMs": 6835, + "endMs": 6845 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 131, + "startMs": 6718, + "headersMs": 6869, + "endMs": 6875 + }, + { + "url": "http://127.0.0.1:5776/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 132, + "startMs": 6770, + "headersMs": 6935, + "endMs": 6955 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 133, + "startMs": 6801, + "headersMs": 6954, + "endMs": 6978 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 134, + "startMs": 6829, + "headersMs": 6980, + "endMs": 7002 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 135, + "startMs": 6832, + "headersMs": 6983, + "endMs": 6988 + }, + { + "url": "http://127.0.0.1:5776/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 136, + "startMs": 6847, + "headersMs": 7003, + "endMs": 7011 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 137, + "startMs": 6877, + "headersMs": 7028, + "endMs": 7042 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 138, + "startMs": 6957, + "headersMs": 7110, + "endMs": 7117 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 139, + "startMs": 6980, + "headersMs": 7131, + "endMs": 7135 + }, + { + "url": "http://127.0.0.1:5776/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 140, + "startMs": 6990, + "headersMs": 7141, + "endMs": 7154 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 141, + "startMs": 7004, + "headersMs": 7155, + "endMs": 7174 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 142, + "startMs": 7012, + "headersMs": 7162, + "endMs": 7165 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 143, + "startMs": 7044, + "headersMs": 7196, + "endMs": 7200 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 144, + "startMs": 7119, + "headersMs": 7272, + "endMs": 7301 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 145, + "startMs": 7137, + "headersMs": 7288, + "endMs": 7290 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 146, + "startMs": 7155, + "headersMs": 7307, + "endMs": 7310 + }, + { + "url": "http://127.0.0.1:5776/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 147, + "startMs": 7167, + "headersMs": 7322, + "endMs": 7327 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 148, + "startMs": 7176, + "headersMs": 7327, + "endMs": 7330 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 149, + "startMs": 7204, + "headersMs": 7357, + "endMs": 7361 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 150, + "startMs": 7291, + "headersMs": 7444, + "endMs": 7450 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 151, + "startMs": 7303, + "headersMs": 7454, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 152, + "startMs": 7311, + "headersMs": 7463, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 153, + "startMs": 7328, + "headersMs": 7480, + "endMs": 7485 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 154, + "startMs": 7331, + "headersMs": 7482, + "endMs": 7496 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 155, + "startMs": 7363, + "headersMs": 7514, + "endMs": 7523 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 156, + "startMs": 7452, + "headersMs": 7604, + "endMs": 7619 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 157, + "startMs": 7480, + "headersMs": 7631, + "endMs": 7644 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 158, + "startMs": 7480, + "headersMs": 7631, + "endMs": 7798 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 159, + "startMs": 7487, + "headersMs": 7639, + "endMs": 7665 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 160, + "startMs": 7498, + "headersMs": 7648, + "endMs": 7686 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 161, + "startMs": 7525, + "headersMs": 7676, + "endMs": 7696 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 162, + "startMs": 7622, + "headersMs": 7773, + "endMs": 7801 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 163, + "startMs": 7646, + "headersMs": 7799, + "endMs": 7807 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 164, + "startMs": 7667, + "headersMs": 7819, + "endMs": 7825 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 165, + "startMs": 7689, + "headersMs": 7841, + "endMs": 7872 + }, + { + "url": "http://127.0.0.1:5776/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 166, + "startMs": 7698, + "headersMs": 8043, + "endMs": 8270 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 167, + "startMs": 7803, + "headersMs": 8044, + "endMs": 8056 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 168, + "startMs": 7803, + "headersMs": 8047, + "endMs": 8049 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 169, + "startMs": 7808, + "headersMs": 8047, + "endMs": 8053 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 170, + "startMs": 8282, + "headersMs": 8435, + "endMs": 8476 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 171, + "startMs": 8478, + "headersMs": 8631, + "endMs": 8641 + } + ], + "initialJsCss": { + "median": 342547, + "min": 342547, + "max": 342547, + "values": [ + 342547, + 342547, + 342547 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 290, + "responseStart": 452, + "end": 452, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 291, + "responseStart": 665, + "end": 666, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 291, + "responseStart": 699, + "end": 699, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 291, + "responseStart": 732, + "end": 733, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 291, + "responseStart": 747, + "end": 748, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 291, + "responseStart": 793, + "end": 794, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "bytes": 983, + "start": 292, + "responseStart": 828, + "end": 829, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 292, + "responseStart": 861, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 292, + "responseStart": 890, + "end": 890, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 292, + "responseStart": 905, + "end": 905, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 292, + "responseStart": 952, + "end": 952, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 292, + "responseStart": 992, + "end": 992, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 292, + "responseStart": 993, + "end": 993, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 292, + "responseStart": 1030, + "end": 1031, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 292, + "responseStart": 1051, + "end": 1051, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 293, + "responseStart": 1070, + "end": 1071, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 293, + "responseStart": 1109, + "end": 1109, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 293, + "responseStart": 1150, + "end": 1150, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 293, + "responseStart": 1224, + "end": 1225, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 293, + "responseStart": 1240, + "end": 1240, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 297, + "responseStart": 1225, + "end": 1225, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 297, + "responseStart": 1261, + "end": 1261, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 297, + "responseStart": 1280, + "end": 1281, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 297, + "responseStart": 1327, + "end": 1327, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 297, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 297, + "responseStart": 1400, + "end": 1401, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 297, + "responseStart": 1405, + "end": 1406, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 297, + "responseStart": 1435, + "end": 1436, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 297, + "responseStart": 1448, + "end": 1449, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 298, + "responseStart": 1503, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 298, + "responseStart": 1547, + "end": 1547, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 298, + "responseStart": 1572, + "end": 1573, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 298, + "responseStart": 1574, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 298, + "responseStart": 1617, + "end": 1618, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 298, + "responseStart": 1626, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 298, + "responseStart": 1680, + "end": 1680, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 298, + "responseStart": 1708, + "end": 1709, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "bytes": 1889, + "start": 298, + "responseStart": 1744, + "end": 1744, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 298, + "responseStart": 1776, + "end": 1777, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 299, + "responseStart": 1776, + "end": 1777, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 299, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 299, + "responseStart": 1859, + "end": 1859, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 299, + "responseStart": 1891, + "end": 1891, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 299, + "responseStart": 1907, + "end": 1908, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 299, + "responseStart": 1942, + "end": 1943, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 299, + "responseStart": 1958, + "end": 1958, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 299, + "responseStart": 1973, + "end": 1973, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 300, + "responseStart": 2021, + "end": 2021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 300, + "responseStart": 2063, + "end": 2063, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 300, + "responseStart": 2095, + "end": 2095, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 300, + "responseStart": 2103, + "end": 2103, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 300, + "responseStart": 2121, + "end": 2121, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 300, + "responseStart": 2157, + "end": 2158, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 300, + "responseStart": 2188, + "end": 2188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 300, + "responseStart": 2256, + "end": 2257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 300, + "responseStart": 2257, + "end": 2258, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 300, + "responseStart": 2268, + "end": 2269, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 300, + "responseStart": 2294, + "end": 2294, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 301, + "responseStart": 2329, + "end": 2329, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 301, + "responseStart": 2350, + "end": 2350, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 301, + "responseStart": 2423, + "end": 2424, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 301, + "responseStart": 2425, + "end": 2426, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 301, + "responseStart": 2428, + "end": 2428, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 301, + "responseStart": 2482, + "end": 2483, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 301, + "responseStart": 2507, + "end": 2507, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 302, + "responseStart": 2521, + "end": 2522, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 302, + "responseStart": 2582, + "end": 2583, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 302, + "responseStart": 2587, + "end": 2587, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "bytes": 164863, + "start": 302, + "responseStart": 3897, + "end": 4396, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1317, + "requests": [ + { + "url": "http://127.0.0.1:5776/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 1, + "startMs": 18, + "headersMs": 226, + "endMs": 286 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 2, + "startMs": 294, + "headersMs": 453, + "endMs": 455 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 3, + "startMs": 296, + "headersMs": 454, + "endMs": 839 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 4, + "startMs": 297, + "headersMs": 629, + "endMs": 796 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 5, + "startMs": 297, + "headersMs": 645, + "endMs": 669 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 6, + "startMs": 298, + "headersMs": 672, + "endMs": 702 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 7, + "startMs": 298, + "headersMs": 704, + "endMs": 736 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 8, + "startMs": 456, + "headersMs": 729, + "endMs": 751 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 9, + "startMs": 670, + "headersMs": 827, + "endMs": 832 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 10, + "startMs": 703, + "headersMs": 858, + "endMs": 864 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 11, + "startMs": 737, + "headersMs": 891, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 12, + "startMs": 752, + "headersMs": 905, + "endMs": 908 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 13, + "startMs": 799, + "headersMs": 953, + "endMs": 955 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 14, + "startMs": 834, + "headersMs": 989, + "endMs": 996 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 15, + "startMs": 839, + "headersMs": 994, + "endMs": 997 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 16, + "startMs": 865, + "headersMs": 1024, + "endMs": 1034 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 17, + "startMs": 894, + "headersMs": 1049, + "endMs": 1055 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 18, + "startMs": 909, + "headersMs": 1065, + "endMs": 1074 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 19, + "startMs": 956, + "headersMs": 1109, + "endMs": 1112 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 20, + "startMs": 996, + "headersMs": 1150, + "endMs": 1153 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 21, + "startMs": 997, + "headersMs": 1188, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 22, + "startMs": 1035, + "headersMs": 1216, + "endMs": 1244 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 23, + "startMs": 1055, + "headersMs": 1222, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 24, + "startMs": 1075, + "headersMs": 1242, + "endMs": 1264 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 25, + "startMs": 1113, + "headersMs": 1272, + "endMs": 1284 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 26, + "startMs": 1154, + "headersMs": 1314, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 27, + "startMs": 1229, + "headersMs": 1383, + "endMs": 1387 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 28, + "startMs": 1229, + "headersMs": 1391, + "endMs": 1404 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 29, + "startMs": 1244, + "headersMs": 1401, + "endMs": 1409 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 30, + "startMs": 1265, + "headersMs": 1424, + "endMs": 1439 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 31, + "startMs": 1285, + "headersMs": 1443, + "endMs": 1452 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 32, + "startMs": 1331, + "headersMs": 1492, + "endMs": 1507 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 33, + "startMs": 1388, + "headersMs": 1543, + "endMs": 1550 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 34, + "startMs": 1405, + "headersMs": 1566, + "endMs": 1576 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 35, + "startMs": 1410, + "headersMs": 1572, + "endMs": 1578 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 36, + "startMs": 1440, + "headersMs": 1607, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 37, + "startMs": 1453, + "headersMs": 1612, + "endMs": 1621 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 38, + "startMs": 1508, + "headersMs": 1670, + "endMs": 1684 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 39, + "startMs": 1551, + "headersMs": 1707, + "endMs": 1712 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 40, + "startMs": 1577, + "headersMs": 1737, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 41, + "startMs": 1579, + "headersMs": 1754, + "endMs": 1780 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 42, + "startMs": 1622, + "headersMs": 1776, + "endMs": 1779 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 43, + "startMs": 1631, + "headersMs": 1785, + "endMs": 1789 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 44, + "startMs": 1684, + "headersMs": 1847, + "endMs": 1862 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 45, + "startMs": 1713, + "headersMs": 1879, + "endMs": 1895 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 46, + "startMs": 1748, + "headersMs": 1904, + "endMs": 1911 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 47, + "startMs": 1781, + "headersMs": 1938, + "endMs": 1946 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 48, + "startMs": 1781, + "headersMs": 1954, + "endMs": 1977 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 49, + "startMs": 1790, + "headersMs": 1957, + "endMs": 1961 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 50, + "startMs": 1863, + "headersMs": 2020, + "endMs": 2025 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 51, + "startMs": 1895, + "headersMs": 2055, + "endMs": 2066 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 52, + "startMs": 1912, + "headersMs": 2079, + "endMs": 2098 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 53, + "startMs": 1947, + "headersMs": 2102, + "endMs": 2106 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 54, + "startMs": 1962, + "headersMs": 2118, + "endMs": 2125 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 55, + "startMs": 1978, + "headersMs": 2144, + "endMs": 2161 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 56, + "startMs": 2025, + "headersMs": 2183, + "endMs": 2191 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 57, + "startMs": 2067, + "headersMs": 2237, + "endMs": 2261 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 58, + "startMs": 2099, + "headersMs": 2254, + "endMs": 2260 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 59, + "startMs": 2107, + "headersMs": 2264, + "endMs": 2272 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 60, + "startMs": 2125, + "headersMs": 2284, + "endMs": 2298 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 61, + "startMs": 2162, + "headersMs": 2322, + "endMs": 2333 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 62, + "startMs": 2192, + "headersMs": 2347, + "endMs": 2353 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 63, + "startMs": 2261, + "headersMs": 2418, + "endMs": 2427 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 64, + "startMs": 2261, + "headersMs": 2422, + "endMs": 2429 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 65, + "startMs": 2273, + "headersMs": 2427, + "endMs": 2431 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 66, + "startMs": 2298, + "headersMs": 2466, + "endMs": 2486 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 67, + "startMs": 2333, + "headersMs": 2496, + "endMs": 2510 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 68, + "startMs": 2355, + "headersMs": 2514, + "endMs": 2525 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 69, + "startMs": 2428, + "headersMs": 2583, + "endMs": 2586 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 70, + "startMs": 2430, + "headersMs": 2586, + "endMs": 2591 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 71, + "startMs": 2432, + "headersMs": 3574, + "endMs": 4399 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 72, + "startMs": 2487, + "headersMs": 3574, + "endMs": 3749 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 2511, + "headersMs": 3575, + "endMs": 3732 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 74, + "startMs": 2526, + "headersMs": 3583, + "endMs": 3587 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 75, + "startMs": 4447, + "headersMs": 4601, + "endMs": 4602 + }, + { + "url": "http://127.0.0.1:5776/api/version", + "status": 200, + "bytes": 62, + "index": 76, + "startMs": 4510, + "headersMs": 4661, + "endMs": 4663 + }, + { + "url": "http://127.0.0.1:5776/api/user/sync", + "status": 200, + "bytes": 11, + "index": 77, + "startMs": 4513, + "headersMs": 4669, + "endMs": 4671 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 78, + "startMs": 4524, + "headersMs": 4699, + "endMs": 4740 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 79, + "startMs": 4673, + "headersMs": 4825, + "endMs": 4826 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 80, + "startMs": 4747, + "headersMs": 4899, + "endMs": 4909 + }, + { + "url": "http://127.0.0.1:5776/api/manifest", + "status": 200, + "bytes": 3207, + "index": 81, + "startMs": 4913, + "headersMs": 5076, + "endMs": 5093 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 82, + "startMs": 5124, + "headersMs": 5279, + "endMs": 6102 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 83, + "startMs": 5124, + "headersMs": 5280, + "endMs": 5290 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 84, + "startMs": 5124, + "headersMs": 5281, + "endMs": 5285 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 85, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5284 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 86, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5288 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 87, + "startMs": 5125, + "headersMs": 5281, + "endMs": 5284 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 88, + "startMs": 5286, + "headersMs": 5440, + "endMs": 5450 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 89, + "startMs": 5286, + "headersMs": 5440, + "endMs": 5446 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 90, + "startMs": 5287, + "headersMs": 5440, + "endMs": 5442 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 91, + "startMs": 5289, + "headersMs": 5441, + "endMs": 5463 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 92, + "startMs": 5291, + "headersMs": 5441, + "endMs": 5448 + }, + { + "url": "http://127.0.0.1:5776/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 93, + "startMs": 5444, + "headersMs": 5600, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 94, + "startMs": 5448, + "headersMs": 5600, + "endMs": 5607 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 96, + "startMs": 5451, + "headersMs": 5603, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 95, + "startMs": 5449, + "headersMs": 5603, + "endMs": 5605 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 97, + "startMs": 5464, + "headersMs": 5616, + "endMs": 5620 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 98, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5776 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 99, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5768 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 100, + "startMs": 5607, + "headersMs": 5758, + "endMs": 5766 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 101, + "startMs": 5608, + "headersMs": 5759, + "endMs": 5767 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 102, + "startMs": 5622, + "headersMs": 5773, + "endMs": 5796 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 103, + "startMs": 5768, + "headersMs": 5920, + "endMs": 5926 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 104, + "startMs": 5769, + "headersMs": 5920, + "endMs": 5933 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 105, + "startMs": 5769, + "headersMs": 5920, + "endMs": 6075 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 106, + "startMs": 5778, + "headersMs": 5928, + "endMs": 6312 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 107, + "startMs": 5799, + "headersMs": 5950, + "endMs": 6049 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 108, + "startMs": 5929, + "headersMs": 6081, + "endMs": 6256 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 109, + "startMs": 5934, + "headersMs": 6085, + "endMs": 6144 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 110, + "startMs": 6051, + "headersMs": 6202, + "endMs": 6360 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 111, + "startMs": 6077, + "headersMs": 6228, + "endMs": 6337 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 112, + "startMs": 6107, + "headersMs": 6258, + "endMs": 6394 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 113, + "startMs": 6147, + "headersMs": 6298, + "endMs": 6301 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 114, + "startMs": 6258, + "headersMs": 6411, + "endMs": 6420 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 115, + "startMs": 6303, + "headersMs": 6454, + "endMs": 6468 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 116, + "startMs": 6314, + "headersMs": 6466, + "endMs": 6482 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 117, + "startMs": 6339, + "headersMs": 6490, + "endMs": 6495 + }, + { + "url": "http://127.0.0.1:5776/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 118, + "startMs": 6362, + "headersMs": 6516, + "endMs": 6519 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 119, + "startMs": 6396, + "headersMs": 6547, + "endMs": 6556 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 120, + "startMs": 6422, + "headersMs": 6574, + "endMs": 6598 + }, + { + "url": "http://127.0.0.1:5776/index.html?v=ca12d59818", + "status": 200, + "bytes": 11500, + "index": 121, + "startMs": 6470, + "headersMs": 6623, + "endMs": 6681 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 122, + "startMs": 6484, + "headersMs": 6635, + "endMs": 6642 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 123, + "startMs": 6497, + "headersMs": 6648, + "endMs": 6658 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 124, + "startMs": 6521, + "headersMs": 6672, + "endMs": 6674 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 125, + "startMs": 6558, + "headersMs": 6711, + "endMs": 6716 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 126, + "startMs": 6600, + "headersMs": 6752, + "endMs": 6768 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 127, + "startMs": 6644, + "headersMs": 6795, + "endMs": 6799 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 128, + "startMs": 6661, + "headersMs": 6814, + "endMs": 6827 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 129, + "startMs": 6676, + "headersMs": 6827, + "endMs": 6830 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 130, + "startMs": 6684, + "headersMs": 6835, + "endMs": 6845 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 131, + "startMs": 6718, + "headersMs": 6869, + "endMs": 6875 + }, + { + "url": "http://127.0.0.1:5776/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 132, + "startMs": 6770, + "headersMs": 6935, + "endMs": 6955 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 133, + "startMs": 6801, + "headersMs": 6954, + "endMs": 6978 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 134, + "startMs": 6829, + "headersMs": 6980, + "endMs": 7002 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 135, + "startMs": 6832, + "headersMs": 6983, + "endMs": 6988 + }, + { + "url": "http://127.0.0.1:5776/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 136, + "startMs": 6847, + "headersMs": 7003, + "endMs": 7011 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 137, + "startMs": 6877, + "headersMs": 7028, + "endMs": 7042 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 138, + "startMs": 6957, + "headersMs": 7110, + "endMs": 7117 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 139, + "startMs": 6980, + "headersMs": 7131, + "endMs": 7135 + }, + { + "url": "http://127.0.0.1:5776/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 140, + "startMs": 6990, + "headersMs": 7141, + "endMs": 7154 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 141, + "startMs": 7004, + "headersMs": 7155, + "endMs": 7174 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 142, + "startMs": 7012, + "headersMs": 7162, + "endMs": 7165 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 143, + "startMs": 7044, + "headersMs": 7196, + "endMs": 7200 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 144, + "startMs": 7119, + "headersMs": 7272, + "endMs": 7301 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 145, + "startMs": 7137, + "headersMs": 7288, + "endMs": 7290 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 146, + "startMs": 7155, + "headersMs": 7307, + "endMs": 7310 + }, + { + "url": "http://127.0.0.1:5776/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 147, + "startMs": 7167, + "headersMs": 7322, + "endMs": 7327 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 148, + "startMs": 7176, + "headersMs": 7327, + "endMs": 7330 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 149, + "startMs": 7204, + "headersMs": 7357, + "endMs": 7361 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 150, + "startMs": 7291, + "headersMs": 7444, + "endMs": 7450 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 151, + "startMs": 7303, + "headersMs": 7454, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 152, + "startMs": 7311, + "headersMs": 7463, + "endMs": 7478 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 153, + "startMs": 7328, + "headersMs": 7480, + "endMs": 7485 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 154, + "startMs": 7331, + "headersMs": 7482, + "endMs": 7496 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 155, + "startMs": 7363, + "headersMs": 7514, + "endMs": 7523 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 156, + "startMs": 7452, + "headersMs": 7604, + "endMs": 7619 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 157, + "startMs": 7480, + "headersMs": 7631, + "endMs": 7644 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 158, + "startMs": 7480, + "headersMs": 7631, + "endMs": 7798 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 159, + "startMs": 7487, + "headersMs": 7639, + "endMs": 7665 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 160, + "startMs": 7498, + "headersMs": 7648, + "endMs": 7686 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 161, + "startMs": 7525, + "headersMs": 7676, + "endMs": 7696 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 162, + "startMs": 7622, + "headersMs": 7773, + "endMs": 7801 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 163, + "startMs": 7646, + "headersMs": 7799, + "endMs": 7807 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 164, + "startMs": 7667, + "headersMs": 7819, + "endMs": 7825 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 165, + "startMs": 7689, + "headersMs": 7841, + "endMs": 7872 + }, + { + "url": "http://127.0.0.1:5776/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 166, + "startMs": 7698, + "headersMs": 8043, + "endMs": 8270 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 167, + "startMs": 7803, + "headersMs": 8044, + "endMs": 8056 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 168, + "startMs": 7803, + "headersMs": 8047, + "endMs": 8049 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 169, + "startMs": 7808, + "headersMs": 8047, + "endMs": 8053 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 170, + "startMs": 8282, + "headersMs": 8435, + "endMs": 8476 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 171, + "startMs": 8478, + "headersMs": 8631, + "endMs": 8641 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 290, + "responseStart": 452, + "end": 452, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 291, + "responseStart": 665, + "end": 666, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 291, + "responseStart": 699, + "end": 699, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 291, + "responseStart": 732, + "end": 733, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 291, + "responseStart": 747, + "end": 748, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 291, + "responseStart": 793, + "end": 794, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "bytes": 983, + "start": 292, + "responseStart": 828, + "end": 829, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 292, + "responseStart": 861, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 292, + "responseStart": 890, + "end": 890, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 292, + "responseStart": 905, + "end": 905, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 292, + "responseStart": 952, + "end": 952, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 292, + "responseStart": 992, + "end": 992, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 292, + "responseStart": 993, + "end": 993, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 292, + "responseStart": 1030, + "end": 1031, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 292, + "responseStart": 1051, + "end": 1051, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 293, + "responseStart": 1070, + "end": 1071, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 293, + "responseStart": 1109, + "end": 1109, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 293, + "responseStart": 1150, + "end": 1150, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 293, + "responseStart": 1224, + "end": 1225, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 293, + "responseStart": 1240, + "end": 1240, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 297, + "responseStart": 1225, + "end": 1225, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 297, + "responseStart": 1261, + "end": 1261, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 297, + "responseStart": 1280, + "end": 1281, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 297, + "responseStart": 1327, + "end": 1327, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 297, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 297, + "responseStart": 1400, + "end": 1401, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 297, + "responseStart": 1405, + "end": 1406, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 297, + "responseStart": 1435, + "end": 1436, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 297, + "responseStart": 1448, + "end": 1449, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 298, + "responseStart": 1503, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 298, + "responseStart": 1547, + "end": 1547, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 298, + "responseStart": 1572, + "end": 1573, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 298, + "responseStart": 1574, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 298, + "responseStart": 1617, + "end": 1618, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 298, + "responseStart": 1626, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 298, + "responseStart": 1680, + "end": 1680, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 298, + "responseStart": 1708, + "end": 1709, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "bytes": 1889, + "start": 298, + "responseStart": 1744, + "end": 1744, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 298, + "responseStart": 1776, + "end": 1777, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 299, + "responseStart": 1776, + "end": 1777, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 299, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 299, + "responseStart": 1859, + "end": 1859, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 299, + "responseStart": 1891, + "end": 1891, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 299, + "responseStart": 1907, + "end": 1908, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 299, + "responseStart": 1942, + "end": 1943, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 299, + "responseStart": 1958, + "end": 1958, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 299, + "responseStart": 1973, + "end": 1973, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 300, + "responseStart": 2021, + "end": 2021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 300, + "responseStart": 2063, + "end": 2063, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 300, + "responseStart": 2095, + "end": 2095, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 300, + "responseStart": 2103, + "end": 2103, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 300, + "responseStart": 2121, + "end": 2121, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 300, + "responseStart": 2157, + "end": 2158, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 300, + "responseStart": 2188, + "end": 2188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 300, + "responseStart": 2256, + "end": 2257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 300, + "responseStart": 2257, + "end": 2258, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 300, + "responseStart": 2268, + "end": 2269, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 300, + "responseStart": 2294, + "end": 2294, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 301, + "responseStart": 2329, + "end": 2329, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 301, + "responseStart": 2350, + "end": 2350, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 301, + "responseStart": 2423, + "end": 2424, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 301, + "responseStart": 2425, + "end": 2426, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 301, + "responseStart": 2428, + "end": 2428, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 301, + "responseStart": 2482, + "end": 2483, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 301, + "responseStart": 2507, + "end": 2507, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 302, + "responseStart": 2521, + "end": 2522, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 302, + "responseStart": 2582, + "end": 2583, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 302, + "responseStart": 2587, + "end": 2587, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "bytes": 164863, + "start": 302, + "responseStart": 3897, + "end": 4396, + "initiator": "script" + } + ] + }, + { + "fcp": 1032, + "requests": [ + { + "url": "http://127.0.0.1:5776/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 172, + "startMs": 19, + "headersMs": 173, + "endMs": 231 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 173, + "startMs": 239, + "headersMs": 392, + "endMs": 395 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 174, + "startMs": 240, + "headersMs": 393, + "endMs": 777 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 175, + "startMs": 241, + "headersMs": 393, + "endMs": 562 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 176, + "startMs": 241, + "headersMs": 393, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 177, + "startMs": 241, + "headersMs": 394, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 178, + "startMs": 242, + "headersMs": 394, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 179, + "startMs": 396, + "headersMs": 549, + "endMs": 569 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 180, + "startMs": 418, + "headersMs": 569, + "endMs": 574 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 181, + "startMs": 425, + "headersMs": 576, + "endMs": 582 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 182, + "startMs": 425, + "headersMs": 577, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 183, + "startMs": 563, + "headersMs": 716, + "endMs": 718 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 184, + "startMs": 570, + "headersMs": 720, + "endMs": 723 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 185, + "startMs": 574, + "headersMs": 725, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 186, + "startMs": 578, + "headersMs": 730, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 187, + "startMs": 582, + "headersMs": 735, + "endMs": 743 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 188, + "startMs": 719, + "headersMs": 872, + "endMs": 878 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 189, + "startMs": 724, + "headersMs": 875, + "endMs": 884 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 190, + "startMs": 731, + "headersMs": 883, + "endMs": 884 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 191, + "startMs": 735, + "headersMs": 886, + "endMs": 889 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 192, + "startMs": 744, + "headersMs": 896, + "endMs": 934 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 193, + "startMs": 778, + "headersMs": 930, + "endMs": 959 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 194, + "startMs": 879, + "headersMs": 1031, + "endMs": 1036 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 195, + "startMs": 885, + "headersMs": 1036, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 196, + "startMs": 886, + "headersMs": 1036, + "endMs": 1049 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 197, + "startMs": 889, + "headersMs": 1042, + "endMs": 1058 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 198, + "startMs": 935, + "headersMs": 1086, + "endMs": 1090 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 199, + "startMs": 960, + "headersMs": 1111, + "endMs": 1123 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 200, + "startMs": 1041, + "headersMs": 1193, + "endMs": 1201 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 201, + "startMs": 1050, + "headersMs": 1201, + "endMs": 1215 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 202, + "startMs": 1059, + "headersMs": 1211, + "endMs": 1220 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 203, + "startMs": 1060, + "headersMs": 1212, + "endMs": 1227 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 204, + "startMs": 1090, + "headersMs": 1242, + "endMs": 1250 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 205, + "startMs": 1124, + "headersMs": 1276, + "endMs": 1287 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 206, + "startMs": 1202, + "headersMs": 1354, + "endMs": 1360 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 207, + "startMs": 1216, + "headersMs": 1368, + "endMs": 1390 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 208, + "startMs": 1221, + "headersMs": 1373, + "endMs": 1379 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 209, + "startMs": 1228, + "headersMs": 1380, + "endMs": 1393 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 210, + "startMs": 1250, + "headersMs": 1401, + "endMs": 1406 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 211, + "startMs": 1287, + "headersMs": 1439, + "endMs": 1449 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 212, + "startMs": 1361, + "headersMs": 1513, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 213, + "startMs": 1380, + "headersMs": 1531, + "endMs": 1535 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 214, + "startMs": 1391, + "headersMs": 1541, + "endMs": 1546 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 215, + "startMs": 1394, + "headersMs": 1548, + "endMs": 1562 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 216, + "startMs": 1407, + "headersMs": 1558, + "endMs": 1573 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 217, + "startMs": 1451, + "headersMs": 1604, + "endMs": 1610 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 218, + "startMs": 1536, + "headersMs": 1687, + "endMs": 1694 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 219, + "startMs": 1540, + "headersMs": 1692, + "endMs": 1714 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 220, + "startMs": 1546, + "headersMs": 1697, + "endMs": 1701 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 221, + "startMs": 1563, + "headersMs": 1715, + "endMs": 1719 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 222, + "startMs": 1574, + "headersMs": 1726, + "endMs": 1737 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 223, + "startMs": 1611, + "headersMs": 1762, + "endMs": 1780 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 224, + "startMs": 1695, + "headersMs": 1845, + "endMs": 1850 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 225, + "startMs": 1701, + "headersMs": 1852, + "endMs": 1858 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 226, + "startMs": 1715, + "headersMs": 1866, + "endMs": 1881 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 227, + "startMs": 1719, + "headersMs": 1871, + "endMs": 1879 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 228, + "startMs": 1738, + "headersMs": 1890, + "endMs": 1913 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 229, + "startMs": 1781, + "headersMs": 1933, + "endMs": 1939 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 230, + "startMs": 1851, + "headersMs": 2003, + "endMs": 2010 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 231, + "startMs": 1859, + "headersMs": 2011, + "endMs": 2023 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 232, + "startMs": 1880, + "headersMs": 2032, + "endMs": 2041 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 233, + "startMs": 1883, + "headersMs": 2035, + "endMs": 2040 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 234, + "startMs": 1914, + "headersMs": 2065, + "endMs": 2071 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 235, + "startMs": 1940, + "headersMs": 2091, + "endMs": 2099 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 236, + "startMs": 2011, + "headersMs": 2162, + "endMs": 2167 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 237, + "startMs": 2024, + "headersMs": 2175, + "endMs": 2195 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 238, + "startMs": 2040, + "headersMs": 2192, + "endMs": 2206 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 239, + "startMs": 2042, + "headersMs": 2194, + "endMs": 2204 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 240, + "startMs": 2072, + "headersMs": 2223, + "endMs": 2228 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 241, + "startMs": 2100, + "headersMs": 2251, + "endMs": 2253 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 242, + "startMs": 2167, + "headersMs": 2319, + "endMs": 3144 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 243, + "startMs": 2196, + "headersMs": 2349, + "endMs": 2522 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 244, + "startMs": 2205, + "headersMs": 2359, + "endMs": 2518 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 245, + "startMs": 2206, + "headersMs": 2360, + "endMs": 2364 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 246, + "startMs": 3191, + "headersMs": 3345, + "endMs": 3345 + }, + { + "url": "http://127.0.0.1:5776/api/version", + "status": 200, + "bytes": 62, + "index": 247, + "startMs": 3259, + "headersMs": 3411, + "endMs": 3412 + }, + { + "url": "http://127.0.0.1:5776/api/user/sync", + "status": 200, + "bytes": 11, + "index": 248, + "startMs": 3260, + "headersMs": 3413, + "endMs": 3413 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 249, + "startMs": 3286, + "headersMs": 3437, + "endMs": 3478 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 250, + "startMs": 3415, + "headersMs": 3568, + "endMs": 3570 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 251, + "startMs": 3486, + "headersMs": 3638, + "endMs": 3648 + }, + { + "url": "http://127.0.0.1:5776/api/manifest", + "status": 200, + "bytes": 3207, + "index": 252, + "startMs": 3652, + "headersMs": 3804, + "endMs": 3821 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 253, + "startMs": 3854, + "headersMs": 4007, + "endMs": 4830 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 254, + "startMs": 3854, + "headersMs": 4008, + "endMs": 4017 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 255, + "startMs": 3854, + "headersMs": 4008, + "endMs": 4013 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 256, + "startMs": 3854, + "headersMs": 4008, + "endMs": 4011 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 257, + "startMs": 3854, + "headersMs": 4009, + "endMs": 4016 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 258, + "startMs": 3855, + "headersMs": 4009, + "endMs": 4011 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 259, + "startMs": 4013, + "headersMs": 4166, + "endMs": 4177 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 260, + "startMs": 4013, + "headersMs": 4166, + "endMs": 4173 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 261, + "startMs": 4015, + "headersMs": 4166, + "endMs": 4168 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 262, + "startMs": 4018, + "headersMs": 4168, + "endMs": 4190 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 263, + "startMs": 4021, + "headersMs": 4171, + "endMs": 4178 + }, + { + "url": "http://127.0.0.1:5776/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 264, + "startMs": 4171, + "headersMs": 4323, + "endMs": 4329 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 265, + "startMs": 4174, + "headersMs": 4325, + "endMs": 4333 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 266, + "startMs": 4178, + "headersMs": 4329, + "endMs": 4331 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 267, + "startMs": 4179, + "headersMs": 4330, + "endMs": 4334 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 268, + "startMs": 4192, + "headersMs": 4345, + "endMs": 4348 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 269, + "startMs": 4331, + "headersMs": 4483, + "endMs": 4502 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 270, + "startMs": 4333, + "headersMs": 4483, + "endMs": 4493 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 271, + "startMs": 4334, + "headersMs": 4485, + "endMs": 4493 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 272, + "startMs": 4336, + "headersMs": 4487, + "endMs": 4493 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 273, + "startMs": 4350, + "headersMs": 4503, + "endMs": 4527 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 274, + "startMs": 4496, + "headersMs": 4647, + "endMs": 4653 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 275, + "startMs": 4496, + "headersMs": 4647, + "endMs": 4660 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 276, + "startMs": 4496, + "headersMs": 4647, + "endMs": 4801 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 277, + "startMs": 4504, + "headersMs": 4654, + "endMs": 5040 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 278, + "startMs": 4530, + "headersMs": 4681, + "endMs": 4780 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 279, + "startMs": 4655, + "headersMs": 4806, + "endMs": 4979 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 280, + "startMs": 4662, + "headersMs": 4812, + "endMs": 4871 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 281, + "startMs": 4782, + "headersMs": 4934, + "endMs": 5093 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 282, + "startMs": 4804, + "headersMs": 4955, + "endMs": 5065 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 283, + "startMs": 4835, + "headersMs": 4986, + "endMs": 5123 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 284, + "startMs": 4873, + "headersMs": 5025, + "endMs": 5026 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 285, + "startMs": 4981, + "headersMs": 5133, + "endMs": 5141 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 286, + "startMs": 5028, + "headersMs": 5180, + "endMs": 5195 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 287, + "startMs": 5042, + "headersMs": 5192, + "endMs": 5209 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 288, + "startMs": 5067, + "headersMs": 5217, + "endMs": 5223 + }, + { + "url": "http://127.0.0.1:5776/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 289, + "startMs": 5095, + "headersMs": 5248, + "endMs": 5250 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 290, + "startMs": 5125, + "headersMs": 5277, + "endMs": 5286 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 291, + "startMs": 5143, + "headersMs": 5295, + "endMs": 5318 + }, + { + "url": "http://127.0.0.1:5776/index.html?v=ca12d59818", + "status": 200, + "bytes": 11500, + "index": 292, + "startMs": 5197, + "headersMs": 5349, + "endMs": 5406 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 293, + "startMs": 5211, + "headersMs": 5363, + "endMs": 5370 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 294, + "startMs": 5224, + "headersMs": 5376, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 295, + "startMs": 5252, + "headersMs": 5404, + "endMs": 5406 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 296, + "startMs": 5287, + "headersMs": 5439, + "endMs": 5444 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 297, + "startMs": 5320, + "headersMs": 5472, + "endMs": 5488 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 298, + "startMs": 5371, + "headersMs": 5523, + "endMs": 5526 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 299, + "startMs": 5389, + "headersMs": 5539, + "endMs": 5552 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 300, + "startMs": 5408, + "headersMs": 5560, + "endMs": 5563 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 301, + "startMs": 5408, + "headersMs": 5560, + "endMs": 5569 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 302, + "startMs": 5446, + "headersMs": 5598, + "endMs": 5604 + }, + { + "url": "http://127.0.0.1:5776/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 303, + "startMs": 5491, + "headersMs": 5641, + "endMs": 5661 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 304, + "startMs": 5528, + "headersMs": 5680, + "endMs": 5703 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 305, + "startMs": 5554, + "headersMs": 5704, + "endMs": 5727 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 306, + "startMs": 5565, + "headersMs": 5717, + "endMs": 5722 + }, + { + "url": "http://127.0.0.1:5776/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 307, + "startMs": 5571, + "headersMs": 5721, + "endMs": 5728 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 308, + "startMs": 5606, + "headersMs": 5758, + "endMs": 5772 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 309, + "startMs": 5664, + "headersMs": 5815, + "endMs": 5823 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 310, + "startMs": 5705, + "headersMs": 5858, + "endMs": 5863 + }, + { + "url": "http://127.0.0.1:5776/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 311, + "startMs": 5724, + "headersMs": 5876, + "endMs": 5888 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 312, + "startMs": 5729, + "headersMs": 5879, + "endMs": 5899 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 313, + "startMs": 5730, + "headersMs": 5880, + "endMs": 5883 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 314, + "startMs": 5774, + "headersMs": 5925, + "endMs": 5929 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 315, + "startMs": 5827, + "headersMs": 5978, + "endMs": 6007 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 316, + "startMs": 5865, + "headersMs": 6016, + "endMs": 6018 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 317, + "startMs": 5885, + "headersMs": 6036, + "endMs": 6039 + }, + { + "url": "http://127.0.0.1:5776/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 318, + "startMs": 5890, + "headersMs": 6039, + "endMs": 6044 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 319, + "startMs": 5901, + "headersMs": 6051, + "endMs": 6055 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 320, + "startMs": 5931, + "headersMs": 6083, + "endMs": 6087 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 321, + "startMs": 6010, + "headersMs": 6162, + "endMs": 6168 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 322, + "startMs": 6020, + "headersMs": 6171, + "endMs": 6193 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 323, + "startMs": 6041, + "headersMs": 6193, + "endMs": 6208 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 324, + "startMs": 6045, + "headersMs": 6196, + "endMs": 6202 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 325, + "startMs": 6057, + "headersMs": 6209, + "endMs": 6224 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 326, + "startMs": 6089, + "headersMs": 6241, + "endMs": 6250 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 327, + "startMs": 6170, + "headersMs": 6321, + "endMs": 6337 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 328, + "startMs": 6195, + "headersMs": 6346, + "endMs": 6360 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 329, + "startMs": 6204, + "headersMs": 6357, + "endMs": 6524 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 330, + "startMs": 6210, + "headersMs": 6360, + "endMs": 6387 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 331, + "startMs": 6226, + "headersMs": 6377, + "endMs": 6415 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 332, + "startMs": 6252, + "headersMs": 6406, + "endMs": 6425 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 333, + "startMs": 6339, + "headersMs": 6492, + "endMs": 6520 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 334, + "startMs": 6362, + "headersMs": 6514, + "endMs": 6523 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 335, + "startMs": 6389, + "headersMs": 6541, + "endMs": 6547 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 336, + "startMs": 6418, + "headersMs": 6570, + "endMs": 6600 + }, + { + "url": "http://127.0.0.1:5776/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 337, + "startMs": 6427, + "headersMs": 6579, + "endMs": 6804 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 338, + "startMs": 6522, + "headersMs": 6674, + "endMs": 6687 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 339, + "startMs": 6524, + "headersMs": 6675, + "endMs": 6677 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 340, + "startMs": 6528, + "headersMs": 6678, + "endMs": 6684 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 341, + "startMs": 6815, + "headersMs": 6967, + "endMs": 7009 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 342, + "startMs": 7012, + "headersMs": 7163, + "endMs": 7173 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 221, + "responseStart": 378, + "end": 378, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 221, + "responseStart": 400, + "end": 400, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 221, + "responseStart": 544, + "end": 545, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 222, + "responseStart": 406, + "end": 406, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 222, + "responseStart": 406, + "end": 407, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 222, + "responseStart": 551, + "end": 552, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "bytes": 983, + "start": 222, + "responseStart": 556, + "end": 556, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 222, + "responseStart": 560, + "end": 560, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 222, + "responseStart": 564, + "end": 564, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 222, + "responseStart": 701, + "end": 701, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 222, + "responseStart": 706, + "end": 706, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 222, + "responseStart": 713, + "end": 713, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 223, + "responseStart": 717, + "end": 717, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 223, + "responseStart": 726, + "end": 726, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 223, + "responseStart": 860, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 223, + "responseStart": 867, + "end": 867, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 223, + "responseStart": 867, + "end": 868, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 223, + "responseStart": 871, + "end": 871, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 223, + "responseStart": 916, + "end": 917, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 223, + "responseStart": 941, + "end": 942, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 228, + "responseStart": 1019, + "end": 1019, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 228, + "responseStart": 1031, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 228, + "responseStart": 1041, + "end": 1041, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 228, + "responseStart": 1041, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 228, + "responseStart": 1072, + "end": 1072, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 228, + "responseStart": 1106, + "end": 1106, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 228, + "responseStart": 1183, + "end": 1184, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 228, + "responseStart": 1198, + "end": 1198, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 229, + "responseStart": 1203, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 229, + "responseStart": 1209, + "end": 1210, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 229, + "responseStart": 1232, + "end": 1233, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 229, + "responseStart": 1269, + "end": 1269, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 229, + "responseStart": 1343, + "end": 1343, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 229, + "responseStart": 1362, + "end": 1362, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 229, + "responseStart": 1372, + "end": 1373, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 229, + "responseStart": 1376, + "end": 1376, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 229, + "responseStart": 1388, + "end": 1389, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "bytes": 1889, + "start": 230, + "responseStart": 1432, + "end": 1433, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 230, + "responseStart": 1517, + "end": 1518, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 230, + "responseStart": 1521, + "end": 1522, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 230, + "responseStart": 1528, + "end": 1528, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 230, + "responseStart": 1545, + "end": 1545, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 230, + "responseStart": 1555, + "end": 1556, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 230, + "responseStart": 1592, + "end": 1592, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 230, + "responseStart": 1676, + "end": 1677, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 230, + "responseStart": 1683, + "end": 1684, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 230, + "responseStart": 1696, + "end": 1697, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 230, + "responseStart": 1701, + "end": 1701, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 231, + "responseStart": 1720, + "end": 1720, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 231, + "responseStart": 1763, + "end": 1763, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 231, + "responseStart": 1833, + "end": 1833, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 231, + "responseStart": 1841, + "end": 1841, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 231, + "responseStart": 1861, + "end": 1862, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 231, + "responseStart": 1864, + "end": 1864, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 231, + "responseStart": 1895, + "end": 1896, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 231, + "responseStart": 1921, + "end": 1922, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 231, + "responseStart": 1993, + "end": 1993, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 231, + "responseStart": 2005, + "end": 2006, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 232, + "responseStart": 2022, + "end": 2022, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 232, + "responseStart": 2024, + "end": 2024, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 232, + "responseStart": 2054, + "end": 2054, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 232, + "responseStart": 2082, + "end": 2082, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 232, + "responseStart": 2149, + "end": 2149, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 232, + "responseStart": 2178, + "end": 2178, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 233, + "responseStart": 2186, + "end": 2187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 233, + "responseStart": 2188, + "end": 2188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 233, + "responseStart": 2210, + "end": 2211, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 233, + "responseStart": 2236, + "end": 2236, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "bytes": 164863, + "start": 233, + "responseStart": 2628, + "end": 3128, + "initiator": "script" + } + ] + }, + { + "fcp": 1029, + "requests": [ + { + "url": "http://127.0.0.1:5776/?v=benchmedia01", + "status": 200, + "bytes": 11500, + "index": 343, + "startMs": 16, + "headersMs": 169, + "endMs": 227 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 344, + "startMs": 234, + "headersMs": 386, + "endMs": 387 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 345, + "startMs": 235, + "headersMs": 386, + "endMs": 771 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 346, + "startMs": 236, + "headersMs": 387, + "endMs": 555 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 347, + "startMs": 236, + "headersMs": 387, + "endMs": 410 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 348, + "startMs": 237, + "headersMs": 388, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 349, + "startMs": 237, + "headersMs": 388, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 350, + "startMs": 388, + "headersMs": 539, + "endMs": 560 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 351, + "startMs": 412, + "headersMs": 562, + "endMs": 566 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 352, + "startMs": 418, + "headersMs": 569, + "endMs": 575 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 353, + "startMs": 418, + "headersMs": 569, + "endMs": 570 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 354, + "startMs": 557, + "headersMs": 709, + "endMs": 712 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 355, + "startMs": 561, + "headersMs": 712, + "endMs": 714 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 356, + "startMs": 567, + "headersMs": 718, + "endMs": 723 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 357, + "startMs": 571, + "headersMs": 722, + "endMs": 725 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 358, + "startMs": 576, + "headersMs": 726, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 359, + "startMs": 713, + "headersMs": 867, + "endMs": 873 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 360, + "startMs": 715, + "headersMs": 867, + "endMs": 875 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 361, + "startMs": 724, + "headersMs": 875, + "endMs": 876 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 362, + "startMs": 726, + "headersMs": 876, + "endMs": 879 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 363, + "startMs": 735, + "headersMs": 887, + "endMs": 925 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 364, + "startMs": 771, + "headersMs": 923, + "endMs": 951 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 365, + "startMs": 874, + "headersMs": 1026, + "endMs": 1033 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 366, + "startMs": 876, + "headersMs": 1027, + "endMs": 1049 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 367, + "startMs": 876, + "headersMs": 1027, + "endMs": 1038 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 368, + "startMs": 879, + "headersMs": 1031, + "endMs": 1045 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 369, + "startMs": 926, + "headersMs": 1078, + "endMs": 1081 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 370, + "startMs": 952, + "headersMs": 1103, + "endMs": 1116 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 371, + "startMs": 1034, + "headersMs": 1184, + "endMs": 1191 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 372, + "startMs": 1039, + "headersMs": 1191, + "endMs": 1205 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 373, + "startMs": 1046, + "headersMs": 1198, + "endMs": 1205 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 374, + "startMs": 1050, + "headersMs": 1201, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 375, + "startMs": 1082, + "headersMs": 1233, + "endMs": 1239 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 376, + "startMs": 1117, + "headersMs": 1268, + "endMs": 1278 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 377, + "startMs": 1192, + "headersMs": 1343, + "endMs": 1350 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 378, + "startMs": 1206, + "headersMs": 1358, + "endMs": 1380 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 379, + "startMs": 1207, + "headersMs": 1358, + "endMs": 1364 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 380, + "startMs": 1219, + "headersMs": 1373, + "endMs": 1386 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 381, + "startMs": 1240, + "headersMs": 1391, + "endMs": 1396 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 382, + "startMs": 1279, + "headersMs": 1431, + "endMs": 1441 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 383, + "startMs": 1351, + "headersMs": 1503, + "endMs": 1529 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 384, + "startMs": 1364, + "headersMs": 1516, + "endMs": 1520 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 385, + "startMs": 1381, + "headersMs": 1532, + "endMs": 1535 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 386, + "startMs": 1386, + "headersMs": 1540, + "endMs": 1556 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 387, + "startMs": 1397, + "headersMs": 1548, + "endMs": 1562 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 388, + "startMs": 1442, + "headersMs": 1592, + "endMs": 1599 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 389, + "startMs": 1521, + "headersMs": 1672, + "endMs": 1682 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 390, + "startMs": 1530, + "headersMs": 1682, + "endMs": 1704 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 391, + "startMs": 1536, + "headersMs": 1689, + "endMs": 1692 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 392, + "startMs": 1557, + "headersMs": 1709, + "endMs": 1714 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 393, + "startMs": 1563, + "headersMs": 1714, + "endMs": 1724 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 394, + "startMs": 1600, + "headersMs": 1751, + "endMs": 1770 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 395, + "startMs": 1682, + "headersMs": 1834, + "endMs": 1838 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 396, + "startMs": 1693, + "headersMs": 1844, + "endMs": 1851 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 397, + "startMs": 1704, + "headersMs": 1857, + "endMs": 1874 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 398, + "startMs": 1714, + "headersMs": 1866, + "endMs": 1874 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 399, + "startMs": 1725, + "headersMs": 1876, + "endMs": 1901 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 400, + "startMs": 1771, + "headersMs": 1922, + "endMs": 1928 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 401, + "startMs": 1840, + "headersMs": 1992, + "endMs": 2000 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 402, + "startMs": 1852, + "headersMs": 2004, + "endMs": 2015 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 403, + "startMs": 1875, + "headersMs": 2028, + "endMs": 2038 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 404, + "startMs": 1876, + "headersMs": 2028, + "endMs": 2034 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 405, + "startMs": 1902, + "headersMs": 2054, + "endMs": 2061 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 406, + "startMs": 1929, + "headersMs": 2081, + "endMs": 2090 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 407, + "startMs": 2002, + "headersMs": 2152, + "endMs": 2157 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 408, + "startMs": 2016, + "headersMs": 2168, + "endMs": 2187 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 409, + "startMs": 2034, + "headersMs": 2187, + "endMs": 2202 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 410, + "startMs": 2039, + "headersMs": 2190, + "endMs": 2201 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 411, + "startMs": 2062, + "headersMs": 2214, + "endMs": 2216 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 2091, + "headersMs": 2243, + "endMs": 2246 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 413, + "startMs": 2158, + "headersMs": 2310, + "endMs": 3136 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 414, + "startMs": 2188, + "headersMs": 2340, + "endMs": 2512 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 415, + "startMs": 2202, + "headersMs": 2354, + "endMs": 2512 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 416, + "startMs": 2203, + "headersMs": 2354, + "endMs": 2358 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 417, + "startMs": 3180, + "headersMs": 3332, + "endMs": 3333 + }, + { + "url": "http://127.0.0.1:5776/api/version", + "status": 200, + "bytes": 62, + "index": 418, + "startMs": 3252, + "headersMs": 3405, + "endMs": 3405 + }, + { + "url": "http://127.0.0.1:5776/api/user/sync", + "status": 200, + "bytes": 11, + "index": 419, + "startMs": 3254, + "headersMs": 3407, + "endMs": 3407 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 420, + "startMs": 3263, + "headersMs": 3414, + "endMs": 3455 + }, + { + "url": "http://127.0.0.1:5776/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 421, + "startMs": 3409, + "headersMs": 3562, + "endMs": 3562 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 422, + "startMs": 3464, + "headersMs": 3615, + "endMs": 3625 + }, + { + "url": "http://127.0.0.1:5776/api/manifest", + "status": 200, + "bytes": 3207, + "index": 423, + "startMs": 3628, + "headersMs": 3779, + "endMs": 3794 + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "status": 200, + "bytes": 164863, + "index": 424, + "startMs": 3826, + "headersMs": 3979, + "endMs": 4803 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 425, + "startMs": 3826, + "headersMs": 3980, + "endMs": 3989 + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 426, + "startMs": 3826, + "headersMs": 3980, + "endMs": 3984 + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 427, + "startMs": 3826, + "headersMs": 3980, + "endMs": 3984 + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 428, + "startMs": 3827, + "headersMs": 3980, + "endMs": 3988 + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 429, + "startMs": 3827, + "headersMs": 3980, + "endMs": 3983 + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "status": 200, + "bytes": 2029, + "index": 430, + "startMs": 3986, + "headersMs": 4138, + "endMs": 4148 + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 431, + "startMs": 3986, + "headersMs": 4138, + "endMs": 4143 + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 432, + "startMs": 3986, + "headersMs": 4138, + "endMs": 4139 + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "status": 200, + "bytes": 4232, + "index": 433, + "startMs": 3989, + "headersMs": 4140, + "endMs": 4161 + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 434, + "startMs": 3991, + "headersMs": 4143, + "endMs": 4149 + }, + { + "url": "http://127.0.0.1:5776/direct-recv-worker.js?v=8522cdb44b", + "status": 200, + "bytes": 1174, + "index": 435, + "startMs": 4142, + "headersMs": 4292, + "endMs": 4297 + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 436, + "startMs": 4146, + "headersMs": 4296, + "endMs": 4305 + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 437, + "startMs": 4150, + "headersMs": 4300, + "endMs": 4303 + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 438, + "startMs": 4151, + "headersMs": 4301, + "endMs": 4305 + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 439, + "startMs": 4163, + "headersMs": 4316, + "endMs": 4320 + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 440, + "startMs": 4299, + "headersMs": 4451, + "endMs": 4469 + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 441, + "startMs": 4305, + "headersMs": 4456, + "endMs": 4466 + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "status": 200, + "bytes": 1567, + "index": 442, + "startMs": 4307, + "headersMs": 4458, + "endMs": 4466 + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 443, + "startMs": 4307, + "headersMs": 4458, + "endMs": 4466 + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "status": 200, + "bytes": 4747, + "index": 444, + "startMs": 4322, + "headersMs": 4474, + "endMs": 4497 + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 445, + "startMs": 4470, + "headersMs": 4620, + "endMs": 4627 + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 446, + "startMs": 4470, + "headersMs": 4621, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 447, + "startMs": 4470, + "headersMs": 4621, + "endMs": 4774 + }, + { + "url": "http://127.0.0.1:5776/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 448, + "startMs": 4472, + "headersMs": 4623, + "endMs": 5006 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 449, + "startMs": 4500, + "headersMs": 4655, + "endMs": 4753 + }, + { + "url": "http://127.0.0.1:5776/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 450, + "startMs": 4630, + "headersMs": 4781, + "endMs": 4955 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 451, + "startMs": 4634, + "headersMs": 4785, + "endMs": 4844 + }, + { + "url": "http://127.0.0.1:5776/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 452, + "startMs": 4756, + "headersMs": 4909, + "endMs": 5066 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin-ext.woff2", + "status": 200, + "bytes": 21728, + "index": 453, + "startMs": 4776, + "headersMs": 4928, + "endMs": 5036 + }, + { + "url": "http://127.0.0.1:5776/fonts/PlusJakartaSans-latin.woff2", + "status": 200, + "bytes": 27348, + "index": 454, + "startMs": 4808, + "headersMs": 4960, + "endMs": 5096 + }, + { + "url": "http://127.0.0.1:5776/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 455, + "startMs": 4846, + "headersMs": 4998, + "endMs": 5001 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 456, + "startMs": 4957, + "headersMs": 5109, + "endMs": 5118 + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 457, + "startMs": 5004, + "headersMs": 5155, + "endMs": 5170 + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 458, + "startMs": 5009, + "headersMs": 5162, + "endMs": 5179 + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 459, + "startMs": 5039, + "headersMs": 5189, + "endMs": 5195 + }, + { + "url": "http://127.0.0.1:5776/hash-worker.js?v=a08461a7f6", + "status": 200, + "bytes": 576, + "index": 460, + "startMs": 5068, + "headersMs": 5219, + "endMs": 5222 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 461, + "startMs": 5100, + "headersMs": 5251, + "endMs": 5258 + }, + { + "url": "http://127.0.0.1:5776/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 462, + "startMs": 5120, + "headersMs": 5272, + "endMs": 5296 + }, + { + "url": "http://127.0.0.1:5776/index.html?v=ca12d59818", + "status": 200, + "bytes": 11500, + "index": 463, + "startMs": 5173, + "headersMs": 5324, + "endMs": 5382 + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 464, + "startMs": 5181, + "headersMs": 5332, + "endMs": 5339 + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 465, + "startMs": 5196, + "headersMs": 5347, + "endMs": 5358 + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 466, + "startMs": 5224, + "headersMs": 5376, + "endMs": 5378 + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 467, + "startMs": 5260, + "headersMs": 5412, + "endMs": 5417 + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 468, + "startMs": 5298, + "headersMs": 5449, + "endMs": 5465 + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 469, + "startMs": 5341, + "headersMs": 5492, + "endMs": 5495 + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "status": 200, + "bytes": 2447, + "index": 470, + "startMs": 5361, + "headersMs": 5511, + "endMs": 5524 + }, + { + "url": "http://127.0.0.1:5776/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 471, + "startMs": 5380, + "headersMs": 5530, + "endMs": 5533 + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 472, + "startMs": 5384, + "headersMs": 5535, + "endMs": 5546 + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 473, + "startMs": 5419, + "headersMs": 5570, + "endMs": 5576 + }, + { + "url": "http://127.0.0.1:5776/opfs-worker.js?v=310e7a7385", + "status": 200, + "bytes": 3957, + "index": 474, + "startMs": 5467, + "headersMs": 5619, + "endMs": 5639 + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "status": 200, + "bytes": 4553, + "index": 475, + "startMs": 5497, + "headersMs": 5648, + "endMs": 5671 + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "status": 200, + "bytes": 4410, + "index": 476, + "startMs": 5526, + "headersMs": 5678, + "endMs": 5700 + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 477, + "startMs": 5535, + "headersMs": 5687, + "endMs": 5693 + }, + { + "url": "http://127.0.0.1:5776/p2p-recv-worker.js?v=0a3dd19a05", + "status": 200, + "bytes": 1429, + "index": 478, + "startMs": 5549, + "headersMs": 5700, + "endMs": 5707 + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "status": 200, + "bytes": 2758, + "index": 479, + "startMs": 5578, + "headersMs": 5728, + "endMs": 5742 + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 480, + "startMs": 5641, + "headersMs": 5793, + "endMs": 5801 + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 481, + "startMs": 5674, + "headersMs": 5824, + "endMs": 5828 + }, + { + "url": "http://127.0.0.1:5776/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 482, + "startMs": 5695, + "headersMs": 5845, + "endMs": 5858 + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "status": 200, + "bytes": 3986, + "index": 483, + "startMs": 5702, + "headersMs": 5853, + "endMs": 5873 + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 484, + "startMs": 5709, + "headersMs": 5861, + "endMs": 5864 + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 485, + "startMs": 5744, + "headersMs": 5895, + "endMs": 5900 + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 486, + "startMs": 5803, + "headersMs": 5955, + "endMs": 5983 + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 487, + "startMs": 5830, + "headersMs": 5982, + "endMs": 5985 + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 488, + "startMs": 5860, + "headersMs": 6013, + "endMs": 6016 + }, + { + "url": "http://127.0.0.1:5776/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 489, + "startMs": 5866, + "headersMs": 6016, + "endMs": 6020 + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 490, + "startMs": 5876, + "headersMs": 6026, + "endMs": 6030 + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 491, + "startMs": 5902, + "headersMs": 6054, + "endMs": 6059 + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 492, + "startMs": 5987, + "headersMs": 6138, + "endMs": 6144 + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 493, + "startMs": 5987, + "headersMs": 6138, + "endMs": 6161 + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 494, + "startMs": 6018, + "headersMs": 6168, + "endMs": 6182 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 495, + "startMs": 6021, + "headersMs": 6173, + "endMs": 6178 + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "status": 200, + "bytes": 2811, + "index": 496, + "startMs": 6031, + "headersMs": 6182, + "endMs": 6197 + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 497, + "startMs": 6060, + "headersMs": 6211, + "endMs": 6220 + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "status": 200, + "bytes": 3187, + "index": 498, + "startMs": 6146, + "headersMs": 6299, + "endMs": 6315 + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 499, + "startMs": 6164, + "headersMs": 6315, + "endMs": 6329 + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 500, + "startMs": 6180, + "headersMs": 6331, + "endMs": 6498 + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "status": 200, + "bytes": 5152, + "index": 501, + "startMs": 6184, + "headersMs": 6335, + "endMs": 6360 + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 502, + "startMs": 6199, + "headersMs": 6352, + "endMs": 6391 + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 503, + "startMs": 6223, + "headersMs": 6375, + "endMs": 6395 + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 504, + "startMs": 6317, + "headersMs": 6469, + "endMs": 6496 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 505, + "startMs": 6332, + "headersMs": 6482, + "endMs": 6491 + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 506, + "startMs": 6363, + "headersMs": 6515, + "endMs": 6519 + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 507, + "startMs": 6393, + "headersMs": 6544, + "endMs": 6576 + }, + { + "url": "http://127.0.0.1:5776/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 508, + "startMs": 6397, + "headersMs": 6549, + "endMs": 6773 + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 509, + "startMs": 6493, + "headersMs": 6645, + "endMs": 6658 + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 510, + "startMs": 6498, + "headersMs": 6650, + "endMs": 6653 + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 511, + "startMs": 6502, + "headersMs": 6653, + "endMs": 6659 + }, + { + "url": "http://127.0.0.1:5776/sw.js", + "status": 200, + "bytes": 8055, + "index": 512, + "startMs": 6786, + "headersMs": 6938, + "endMs": 6979 + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "status": 200, + "bytes": 1889, + "index": 513, + "startMs": 6982, + "headersMs": 7133, + "endMs": 7142 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5776/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 218, + "responseStart": 372, + "end": 372, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 218, + "responseStart": 395, + "end": 396, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 218, + "responseStart": 540, + "end": 541, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 219, + "responseStart": 401, + "end": 402, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass.css?v=2c482caf77", + "bytes": 6039, + "start": 219, + "responseStart": 401, + "end": 402, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 219, + "responseStart": 545, + "end": 545, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/recommendations.css?v=055101368d", + "bytes": 983, + "start": 219, + "responseStart": 551, + "end": 551, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/direct-media.css?v=19b8428bfd", + "bytes": 370, + "start": 219, + "responseStart": 555, + "end": 555, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 219, + "responseStart": 560, + "end": 560, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/lower-third.css?v=031f8e0ead", + "bytes": 502, + "start": 219, + "responseStart": 696, + "end": 697, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/car-mode.css?v=7d421630b3", + "bytes": 504, + "start": 219, + "responseStart": 699, + "end": 699, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 220, + "responseStart": 708, + "end": 708, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 220, + "responseStart": 710, + "end": 710, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-controls.css?v=3354ad9631", + "bytes": 1782, + "start": 220, + "responseStart": 719, + "end": 719, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-glass-panel.css?v=25aadb0bb7", + "bytes": 1045, + "start": 220, + "responseStart": 858, + "end": 858, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 220, + "responseStart": 860, + "end": 860, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 220, + "responseStart": 860, + "end": 861, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 220, + "responseStart": 863, + "end": 863, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-bento-hub.css?v=f529dc4bb7", + "bytes": 7731, + "start": 220, + "responseStart": 909, + "end": 910, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/theme-f7.css?v=02ba226f82", + "bytes": 5579, + "start": 220, + "responseStart": 935, + "end": 936, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5776/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 224, + "responseStart": 1017, + "end": 1018, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/video-edit.js?v=90c5dd1eb6", + "bytes": 2506, + "start": 224, + "responseStart": 1023, + "end": 1023, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 224, + "responseStart": 1030, + "end": 1030, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/opfs.js?v=0922d5004c", + "bytes": 4553, + "start": 224, + "responseStart": 1033, + "end": 1034, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 224, + "responseStart": 1066, + "end": 1066, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 224, + "responseStart": 1100, + "end": 1101, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/export.js?v=5b7cdcd7a3", + "bytes": 1536, + "start": 225, + "responseStart": 1176, + "end": 1176, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/stats-core.js?v=3de0591d83", + "bytes": 2619, + "start": 225, + "responseStart": 1189, + "end": 1190, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 225, + "responseStart": 1190, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sha256.js?v=68566d2e65", + "bytes": 3187, + "start": 225, + "responseStart": 1202, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 225, + "responseStart": 1224, + "end": 1224, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 225, + "responseStart": 1263, + "end": 1263, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 225, + "responseStart": 1335, + "end": 1335, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-core.js?v=168a879219", + "bytes": 1137, + "start": 225, + "responseStart": 1348, + "end": 1348, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-client.js?v=0c59fc208b", + "bytes": 4410, + "start": 225, + "responseStart": 1365, + "end": 1365, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/p2p-transfer.js?v=2186d77fae", + "bytes": 2758, + "start": 226, + "responseStart": 1370, + "end": 1370, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 226, + "responseStart": 1380, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/asset-sync-core.js?v=5a232b8353", + "bytes": 1889, + "start": 226, + "responseStart": 1425, + "end": 1426, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 226, + "responseStart": 1504, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/sw-update.js?v=0552fc824d", + "bytes": 5152, + "start": 226, + "responseStart": 1514, + "end": 1514, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 226, + "responseStart": 1520, + "end": 1520, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 226, + "responseStart": 1541, + "end": 1541, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/settings-sections.js?v=870249a743", + "bytes": 2811, + "start": 226, + "responseStart": 1547, + "end": 1547, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-protocol.js?v=87a73be90f", + "bytes": 1245, + "start": 226, + "responseStart": 1583, + "end": 1584, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-stream.js?v=d7f9871605", + "bytes": 1457, + "start": 227, + "responseStart": 1666, + "end": 1666, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 227, + "responseStart": 1677, + "end": 1677, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/direct-media.js?v=5c93a4508c", + "bytes": 4232, + "start": 227, + "responseStart": 1688, + "end": 1688, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 227, + "responseStart": 1698, + "end": 1699, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 227, + "responseStart": 1709, + "end": 1709, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 227, + "responseStart": 1754, + "end": 1755, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 227, + "responseStart": 1822, + "end": 1823, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 227, + "responseStart": 1836, + "end": 1836, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/bento-hub.js?v=c867882d7e", + "bytes": 1523, + "start": 227, + "responseStart": 1858, + "end": 1859, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-controls.js?v=a60ed1fe84", + "bytes": 3227, + "start": 227, + "responseStart": 1859, + "end": 1860, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/f7-layout.js?v=99c11c557b", + "bytes": 4747, + "start": 227, + "responseStart": 1885, + "end": 1886, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/glass-panel-layout.js?v=d5417786d0", + "bytes": 1173, + "start": 228, + "responseStart": 1912, + "end": 1913, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/party-dj.js?v=1677c38a88", + "bytes": 1444, + "start": 228, + "responseStart": 1985, + "end": 1985, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lyrics-window.js?v=68591e0c78", + "bytes": 2447, + "start": 228, + "responseStart": 2000, + "end": 2000, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/lower-third.js?v=7705dcbfb4", + "bytes": 1153, + "start": 228, + "responseStart": 2018, + "end": 2018, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/midi.js?v=dbecfa74e1", + "bytes": 2014, + "start": 228, + "responseStart": 2023, + "end": 2023, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/vocal-reducer.js?v=ddb2fc1bbe", + "bytes": 1397, + "start": 228, + "responseStart": 2045, + "end": 2046, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/eq-core.js?v=e9769cb594", + "bytes": 1567, + "start": 228, + "responseStart": 2075, + "end": 2075, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano-core.js?v=77c8269761", + "bytes": 867, + "start": 229, + "responseStart": 2141, + "end": 2142, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/piano.js?v=79b13f0de0", + "bytes": 3986, + "start": 229, + "responseStart": 2172, + "end": 2172, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/car-mode.js?v=19f187c23f", + "bytes": 2029, + "start": 229, + "responseStart": 2186, + "end": 2186, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/setlist-import.js?v=13bc5cc4a4", + "bytes": 2879, + "start": 229, + "responseStart": 2186, + "end": 2187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 229, + "responseStart": 2201, + "end": 2201, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 229, + "responseStart": 2231, + "end": 2231, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5776/app.js?v=32f243e804", + "bytes": 164863, + "start": 229, + "responseStart": 2622, + "end": 3121, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-bisect-first-loader.json b/perf/results/phase6-bisect-first-loader.json new file mode 100644 index 0000000..4a9f465 --- /dev/null +++ b/perf/results/phase6-bisect-first-loader.json @@ -0,0 +1,6742 @@ +{ + "date": "2026-10-08T00:34:47.888Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-first-loader", + "sourceCommit": "5d6a1545df3fa2c39809bf77293df51a7a4b6765", + "frontendBuildTag": "8a23f4f5e0d3", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 146, + "min": 146, + "max": 146, + "values": [ + 146, + 146, + 146 + ] + }, + "wireBytes": { + "median": 1106796, + "min": 1106796, + "max": 1106796, + "values": [ + 1106796, + 1106796, + 1106796 + ] + }, + "fcp": { + "median": 1615, + "min": 1588, + "max": 2797, + "values": [ + 2797, + 1615, + 1588 + ] + }, + "lcp": { + "median": 1700, + "min": 1659, + "max": 2868, + "values": [ + 2868, + 1700, + 1659 + ] + }, + "domContentLoaded": { + "median": 2431, + "min": 2423, + "max": 3580, + "values": [ + 3580, + 2423, + 2431 + ] + }, + "bootDone": { + "median": 2437, + "min": 2429, + "max": 3585, + "values": [ + 3585, + 2429, + 2437 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31621, + "min": 31609, + "max": 32794, + "values": [ + 32794, + 31609, + 31621 + ] + }, + "swInstallBytes": { + "median": 1106796, + "min": 1106796, + "max": 1106796, + "values": [ + 1106796, + 1106796, + 1106796 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 27374, + "js": 568139, + "css": 133136, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 4663, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5024/?v=benchmedia01", + "status": 200, + "bytes": 13687, + "index": 1, + "startMs": 19, + "headersMs": 239, + "endMs": 311 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 2, + "startMs": 318, + "headersMs": 476, + "endMs": 478 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 3, + "startMs": 319, + "headersMs": 476, + "endMs": 861 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 4, + "startMs": 320, + "headersMs": 654, + "endMs": 823 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 5, + "startMs": 320, + "headersMs": 670, + "endMs": 693 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 6, + "startMs": 321, + "headersMs": 696, + "endMs": 726 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 7, + "startMs": 321, + "headersMs": 705, + "endMs": 722 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 8, + "startMs": 479, + "headersMs": 711, + "endMs": 716 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 9, + "startMs": 694, + "headersMs": 851, + "endMs": 858 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 10, + "startMs": 717, + "headersMs": 871, + "endMs": 877 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 11, + "startMs": 722, + "headersMs": 875, + "endMs": 878 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 12, + "startMs": 726, + "headersMs": 883, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 13, + "startMs": 825, + "headersMs": 978, + "endMs": 981 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 14, + "startMs": 858, + "headersMs": 1014, + "endMs": 1017 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 15, + "startMs": 861, + "headersMs": 1018, + "endMs": 1024 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 16, + "startMs": 877, + "headersMs": 1042, + "endMs": 1064 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 17, + "startMs": 879, + "headersMs": 1050, + "endMs": 1065 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 18, + "startMs": 892, + "headersMs": 1056, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 19, + "startMs": 981, + "headersMs": 1140, + "endMs": 1151 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 20, + "startMs": 1017, + "headersMs": 1173, + "endMs": 1181 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 21, + "startMs": 1025, + "headersMs": 1183, + "endMs": 1201 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 22, + "startMs": 1060, + "headersMs": 1215, + "endMs": 1221 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 23, + "startMs": 1065, + "headersMs": 1222, + "endMs": 1232 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 24, + "startMs": 1066, + "headersMs": 1226, + "endMs": 1232 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 25, + "startMs": 1152, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 26, + "startMs": 1182, + "headersMs": 1340, + "endMs": 1350 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 27, + "startMs": 1202, + "headersMs": 1365, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 28, + "startMs": 1222, + "headersMs": 1375, + "endMs": 1377 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 29, + "startMs": 1233, + "headersMs": 1387, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 30, + "startMs": 1233, + "headersMs": 1396, + "endMs": 1411 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 31, + "startMs": 1312, + "headersMs": 1473, + "endMs": 1488 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 32, + "startMs": 1350, + "headersMs": 1505, + "endMs": 1509 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 33, + "startMs": 1378, + "headersMs": 1533, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 34, + "startMs": 1392, + "headersMs": 1548, + "endMs": 1559 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 35, + "startMs": 1392, + "headersMs": 1560, + "endMs": 1578 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 36, + "startMs": 1412, + "headersMs": 1566, + "endMs": 1571 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 37, + "startMs": 1489, + "headersMs": 1645, + "endMs": 1650 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 38, + "startMs": 1510, + "headersMs": 1662, + "endMs": 1665 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 39, + "startMs": 1537, + "headersMs": 1691, + "endMs": 1693 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 40, + "startMs": 1560, + "headersMs": 1715, + "endMs": 1719 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 41, + "startMs": 1572, + "headersMs": 1730, + "endMs": 1742 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 42, + "startMs": 1578, + "headersMs": 2689, + "endMs": 3520 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 43, + "startMs": 1651, + "headersMs": 2712, + "endMs": 2733 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 44, + "startMs": 1665, + "headersMs": 2712, + "endMs": 2886 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 45, + "startMs": 1694, + "headersMs": 2717, + "endMs": 2721 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 46, + "startMs": 3576, + "headersMs": 3729, + "endMs": 3731 + }, + { + "url": "http://127.0.0.1:5024/api/version", + "status": 200, + "bytes": 62, + "index": 47, + "startMs": 3598, + "headersMs": 3748, + "endMs": 3750 + }, + { + "url": "http://127.0.0.1:5024/api/user/sync", + "status": 200, + "bytes": 11, + "index": 48, + "startMs": 3599, + "headersMs": 3755, + "endMs": 3757 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 49, + "startMs": 3603, + "headersMs": 3781, + "endMs": 3826 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3759, + "headersMs": 3913, + "endMs": 3914 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 51, + "startMs": 3833, + "headersMs": 3985, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5024/api/manifest", + "status": 200, + "bytes": 3436, + "index": 52, + "startMs": 3999, + "headersMs": 4165, + "endMs": 4182 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 53, + "startMs": 4206, + "headersMs": 4361, + "endMs": 5189 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 54, + "startMs": 4206, + "headersMs": 4361, + "endMs": 4370 + }, + { + "url": "http://127.0.0.1:5024/assets.json?v=7db52585ba", + "status": 200, + "bytes": 1106, + "index": 55, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 56, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 57, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 58, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4374 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 59, + "startMs": 4372, + "headersMs": 4524, + "endMs": 4526 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 60, + "startMs": 4374, + "headersMs": 4524, + "endMs": 4526 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 61, + "startMs": 4374, + "headersMs": 4526, + "endMs": 4531 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 62, + "startMs": 4374, + "headersMs": 4526, + "endMs": 4545 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 63, + "startMs": 4376, + "headersMs": 4526, + "endMs": 4536 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 64, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4684 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 65, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4692 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 66, + "startMs": 4533, + "headersMs": 4684, + "endMs": 4691 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 67, + "startMs": 4538, + "headersMs": 4689, + "endMs": 4702 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 68, + "startMs": 4547, + "headersMs": 4698, + "endMs": 4852 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 69, + "startMs": 4686, + "headersMs": 4839, + "endMs": 5223 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 70, + "startMs": 4692, + "headersMs": 4844, + "endMs": 4942 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 71, + "startMs": 4694, + "headersMs": 4844, + "endMs": 5018 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 72, + "startMs": 4704, + "headersMs": 4857, + "endMs": 4916 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 4855, + "headersMs": 5007, + "endMs": 5164 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 74, + "startMs": 4918, + "headersMs": 5069, + "endMs": 5072 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 75, + "startMs": 4944, + "headersMs": 5096, + "endMs": 5104 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 76, + "startMs": 5020, + "headersMs": 5172, + "endMs": 5186 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 77, + "startMs": 5074, + "headersMs": 5225, + "endMs": 5234 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 78, + "startMs": 5106, + "headersMs": 5257, + "endMs": 5280 + }, + { + "url": "http://127.0.0.1:5024/index.html?v=275991ee89", + "status": 200, + "bytes": 13687, + "index": 79, + "startMs": 5167, + "headersMs": 5319, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 80, + "startMs": 5188, + "headersMs": 5339, + "endMs": 5353 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 81, + "startMs": 5194, + "headersMs": 5345, + "endMs": 5352 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 82, + "startMs": 5225, + "headersMs": 5378, + "endMs": 5389 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 83, + "startMs": 5235, + "headersMs": 5387, + "endMs": 5403 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 84, + "startMs": 5283, + "headersMs": 5435, + "endMs": 5438 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 85, + "startMs": 5354, + "headersMs": 5506, + "endMs": 5510 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 86, + "startMs": 5355, + "headersMs": 5506, + "endMs": 5512 + }, + { + "url": "http://127.0.0.1:5024/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 87, + "startMs": 5390, + "headersMs": 5553, + "endMs": 5574 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 88, + "startMs": 5390, + "headersMs": 5554, + "endMs": 5575 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 89, + "startMs": 5406, + "headersMs": 5557, + "endMs": 5561 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 90, + "startMs": 5440, + "headersMs": 5591, + "endMs": 5596 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 91, + "startMs": 5512, + "headersMs": 5663, + "endMs": 5693 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 92, + "startMs": 5513, + "headersMs": 5664, + "endMs": 5666 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 93, + "startMs": 5562, + "headersMs": 5714, + "endMs": 5717 + }, + { + "url": "http://127.0.0.1:5024/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 94, + "startMs": 5576, + "headersMs": 5731, + "endMs": 5735 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 95, + "startMs": 5577, + "headersMs": 5732, + "endMs": 5735 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 96, + "startMs": 5597, + "headersMs": 5749, + "endMs": 5753 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 97, + "startMs": 5668, + "headersMs": 5820, + "endMs": 5826 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 98, + "startMs": 5695, + "headersMs": 5847, + "endMs": 5870 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 99, + "startMs": 5719, + "headersMs": 5869, + "endMs": 5874 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 100, + "startMs": 5737, + "headersMs": 5888, + "endMs": 5902 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 101, + "startMs": 5737, + "headersMs": 5889, + "endMs": 5897 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 102, + "startMs": 5755, + "headersMs": 5906, + "endMs": 5923 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 103, + "startMs": 5828, + "headersMs": 5978, + "endMs": 6146 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 104, + "startMs": 5872, + "headersMs": 6024, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 105, + "startMs": 5876, + "headersMs": 6027, + "endMs": 6048 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 106, + "startMs": 5899, + "headersMs": 6051, + "endMs": 6054 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 107, + "startMs": 6156, + "headersMs": 6309, + "endMs": 6354 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 108, + "startMs": 6356, + "headersMs": 6508, + "endMs": 6518 + }, + { + "url": "http://127.0.0.1:5024/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 109, + "startMs": 7181, + "headersMs": 7339, + "endMs": 7345 + }, + { + "url": "http://127.0.0.1:5024/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 110, + "startMs": 7181, + "headersMs": 7340, + "endMs": 7343 + }, + { + "url": "http://127.0.0.1:5024/car-mode.js?v=815b1d6cdb", + "status": 200, + "bytes": 2077, + "index": 111, + "startMs": 7181, + "headersMs": 7346, + "endMs": 7355 + }, + { + "url": "http://127.0.0.1:5024/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 112, + "startMs": 7181, + "headersMs": 7347, + "endMs": 7348 + }, + { + "url": "http://127.0.0.1:5024/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 113, + "startMs": 7181, + "headersMs": 7359, + "endMs": 7380 + }, + { + "url": "http://127.0.0.1:5024/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 114, + "startMs": 7181, + "headersMs": 7363, + "endMs": 7369 + }, + { + "url": "http://127.0.0.1:5024/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 115, + "startMs": 7345, + "headersMs": 7500, + "endMs": 7507 + }, + { + "url": "http://127.0.0.1:5024/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 116, + "startMs": 7347, + "headersMs": 7504, + "endMs": 7512 + }, + { + "url": "http://127.0.0.1:5024/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 117, + "startMs": 7350, + "headersMs": 7507, + "endMs": 7512 + }, + { + "url": "http://127.0.0.1:5024/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 118, + "startMs": 7357, + "headersMs": 7512, + "endMs": 7520 + }, + { + "url": "http://127.0.0.1:5024/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 119, + "startMs": 7371, + "headersMs": 7536, + "endMs": 7561 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 120, + "startMs": 7382, + "headersMs": 7537, + "endMs": 7646 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 121, + "startMs": 7509, + "headersMs": 7660, + "endMs": 7799 + }, + { + "url": "http://127.0.0.1:5024/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 122, + "startMs": 7514, + "headersMs": 7674, + "endMs": 7691 + }, + { + "url": "http://127.0.0.1:5024/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 123, + "startMs": 7514, + "headersMs": 7677, + "endMs": 7682 + }, + { + "url": "http://127.0.0.1:5024/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 124, + "startMs": 7521, + "headersMs": 7679, + "endMs": 7683 + }, + { + "url": "http://127.0.0.1:5024/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 125, + "startMs": 7563, + "headersMs": 7717, + "endMs": 7719 + }, + { + "url": "http://127.0.0.1:5024/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 126, + "startMs": 7648, + "headersMs": 7803, + "endMs": 7808 + }, + { + "url": "http://127.0.0.1:5024/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 127, + "startMs": 7684, + "headersMs": 7842, + "endMs": 7855 + }, + { + "url": "http://127.0.0.1:5024/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 128, + "startMs": 7684, + "headersMs": 7848, + "endMs": 7859 + }, + { + "url": "http://127.0.0.1:5024/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 129, + "startMs": 7692, + "headersMs": 7865, + "endMs": 7888 + }, + { + "url": "http://127.0.0.1:5024/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 130, + "startMs": 7721, + "headersMs": 7876, + "endMs": 7882 + }, + { + "url": "http://127.0.0.1:5024/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 131, + "startMs": 7801, + "headersMs": 7957, + "endMs": 7964 + }, + { + "url": "http://127.0.0.1:5024/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 132, + "startMs": 7810, + "headersMs": 7971, + "endMs": 7985 + }, + { + "url": "http://127.0.0.1:5024/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 133, + "startMs": 7857, + "headersMs": 8012, + "endMs": 8020 + }, + { + "url": "http://127.0.0.1:5024/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 134, + "startMs": 7861, + "headersMs": 8015, + "endMs": 8020 + }, + { + "url": "http://127.0.0.1:5024/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 135, + "startMs": 7884, + "headersMs": 8034, + "endMs": 8047 + }, + { + "url": "http://127.0.0.1:5024/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 136, + "startMs": 7890, + "headersMs": 8054, + "endMs": 8075 + }, + { + "url": "http://127.0.0.1:5024/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 137, + "startMs": 7966, + "headersMs": 8126, + "endMs": 8142 + }, + { + "url": "http://127.0.0.1:5024/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 138, + "startMs": 7987, + "headersMs": 8147, + "endMs": 8161 + }, + { + "url": "http://127.0.0.1:5024/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 139, + "startMs": 8022, + "headersMs": 8213, + "endMs": 8251 + }, + { + "url": "http://127.0.0.1:5024/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 140, + "startMs": 8022, + "headersMs": 8240, + "endMs": 8268 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 141, + "startMs": 8049, + "headersMs": 8248, + "endMs": 8256 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 142, + "startMs": 8077, + "headersMs": 8254, + "endMs": 8258 + }, + { + "url": "http://127.0.0.1:5024/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 143, + "startMs": 8144, + "headersMs": 8328, + "endMs": 8359 + }, + { + "url": "http://127.0.0.1:5024/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 144, + "startMs": 8163, + "headersMs": 8519, + "endMs": 8744 + }, + { + "url": "http://127.0.0.1:5024/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 145, + "startMs": 8254, + "headersMs": 8528, + "endMs": 8541 + }, + { + "url": "http://127.0.0.1:5024/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 146, + "startMs": 8257, + "headersMs": 8532, + "endMs": 8538 + } + ], + "initialJsCss": { + "median": 274209, + "min": 274209, + "max": 274209, + "values": [ + 274209, + 274209, + 274209 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 301, + "responseStart": 461, + "end": 461, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 677, + "end": 677, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 699, + "end": 699, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 301, + "responseStart": 705, + "end": 705, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 709, + "end": 709, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 806, + "end": 807, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 302, + "responseStart": 841, + "end": 841, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 302, + "responseStart": 860, + "end": 860, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 862, + "end": 862, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 875, + "end": 875, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 964, + "end": 964, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 1000, + "end": 1000, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 303, + "responseStart": 1007, + "end": 1007, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1042, + "end": 1043, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 303, + "responseStart": 1048, + "end": 1048, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1048, + "end": 1049, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1135, + "end": 1135, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 303, + "responseStart": 1164, + "end": 1164, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 303, + "responseStart": 1184, + "end": 1184, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 303, + "responseStart": 1204, + "end": 1204, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1215, + "end": 1216, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1216, + "end": 1216, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1295, + "end": 1295, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1333, + "end": 1333, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1360, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 304, + "responseStart": 1374, + "end": 1375, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1374, + "end": 1375, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 304, + "responseStart": 1394, + "end": 1395, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "bytes": 2929, + "start": 304, + "responseStart": 1471, + "end": 1472, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 304, + "responseStart": 1492, + "end": 1492, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 304, + "responseStart": 1520, + "end": 1520, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1542, + "end": 1543, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 305, + "responseStart": 1554, + "end": 1554, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1561, + "end": 1561, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 305, + "responseStart": 1633, + "end": 1633, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 305, + "responseStart": 1648, + "end": 1648, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 305, + "responseStart": 1677, + "end": 1677, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 305, + "responseStart": 1702, + "end": 1703, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 305, + "responseStart": 1726, + "end": 1726, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "bytes": 165895, + "start": 305, + "responseStart": 2999, + "end": 3504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 822, + "responseStart": 2716, + "end": 2717, + "initiator": "link" + } + ], + "waterfalls": [ + { + "fcp": 2797, + "requests": [ + { + "url": "http://127.0.0.1:5024/?v=benchmedia01", + "status": 200, + "bytes": 13687, + "index": 1, + "startMs": 19, + "headersMs": 239, + "endMs": 311 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 2, + "startMs": 318, + "headersMs": 476, + "endMs": 478 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 3, + "startMs": 319, + "headersMs": 476, + "endMs": 861 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 4, + "startMs": 320, + "headersMs": 654, + "endMs": 823 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 5, + "startMs": 320, + "headersMs": 670, + "endMs": 693 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 6, + "startMs": 321, + "headersMs": 696, + "endMs": 726 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 7, + "startMs": 321, + "headersMs": 705, + "endMs": 722 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 8, + "startMs": 479, + "headersMs": 711, + "endMs": 716 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 9, + "startMs": 694, + "headersMs": 851, + "endMs": 858 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 10, + "startMs": 717, + "headersMs": 871, + "endMs": 877 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 11, + "startMs": 722, + "headersMs": 875, + "endMs": 878 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 12, + "startMs": 726, + "headersMs": 883, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 13, + "startMs": 825, + "headersMs": 978, + "endMs": 981 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 14, + "startMs": 858, + "headersMs": 1014, + "endMs": 1017 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 15, + "startMs": 861, + "headersMs": 1018, + "endMs": 1024 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 16, + "startMs": 877, + "headersMs": 1042, + "endMs": 1064 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 17, + "startMs": 879, + "headersMs": 1050, + "endMs": 1065 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 18, + "startMs": 892, + "headersMs": 1056, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 19, + "startMs": 981, + "headersMs": 1140, + "endMs": 1151 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 20, + "startMs": 1017, + "headersMs": 1173, + "endMs": 1181 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 21, + "startMs": 1025, + "headersMs": 1183, + "endMs": 1201 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 22, + "startMs": 1060, + "headersMs": 1215, + "endMs": 1221 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 23, + "startMs": 1065, + "headersMs": 1222, + "endMs": 1232 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 24, + "startMs": 1066, + "headersMs": 1226, + "endMs": 1232 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 25, + "startMs": 1152, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 26, + "startMs": 1182, + "headersMs": 1340, + "endMs": 1350 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 27, + "startMs": 1202, + "headersMs": 1365, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 28, + "startMs": 1222, + "headersMs": 1375, + "endMs": 1377 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 29, + "startMs": 1233, + "headersMs": 1387, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 30, + "startMs": 1233, + "headersMs": 1396, + "endMs": 1411 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 31, + "startMs": 1312, + "headersMs": 1473, + "endMs": 1488 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 32, + "startMs": 1350, + "headersMs": 1505, + "endMs": 1509 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 33, + "startMs": 1378, + "headersMs": 1533, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 34, + "startMs": 1392, + "headersMs": 1548, + "endMs": 1559 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 35, + "startMs": 1392, + "headersMs": 1560, + "endMs": 1578 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 36, + "startMs": 1412, + "headersMs": 1566, + "endMs": 1571 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 37, + "startMs": 1489, + "headersMs": 1645, + "endMs": 1650 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 38, + "startMs": 1510, + "headersMs": 1662, + "endMs": 1665 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 39, + "startMs": 1537, + "headersMs": 1691, + "endMs": 1693 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 40, + "startMs": 1560, + "headersMs": 1715, + "endMs": 1719 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 41, + "startMs": 1572, + "headersMs": 1730, + "endMs": 1742 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 42, + "startMs": 1578, + "headersMs": 2689, + "endMs": 3520 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 43, + "startMs": 1651, + "headersMs": 2712, + "endMs": 2733 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 44, + "startMs": 1665, + "headersMs": 2712, + "endMs": 2886 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 45, + "startMs": 1694, + "headersMs": 2717, + "endMs": 2721 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 46, + "startMs": 3576, + "headersMs": 3729, + "endMs": 3731 + }, + { + "url": "http://127.0.0.1:5024/api/version", + "status": 200, + "bytes": 62, + "index": 47, + "startMs": 3598, + "headersMs": 3748, + "endMs": 3750 + }, + { + "url": "http://127.0.0.1:5024/api/user/sync", + "status": 200, + "bytes": 11, + "index": 48, + "startMs": 3599, + "headersMs": 3755, + "endMs": 3757 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 49, + "startMs": 3603, + "headersMs": 3781, + "endMs": 3826 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3759, + "headersMs": 3913, + "endMs": 3914 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 51, + "startMs": 3833, + "headersMs": 3985, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5024/api/manifest", + "status": 200, + "bytes": 3436, + "index": 52, + "startMs": 3999, + "headersMs": 4165, + "endMs": 4182 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 53, + "startMs": 4206, + "headersMs": 4361, + "endMs": 5189 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 54, + "startMs": 4206, + "headersMs": 4361, + "endMs": 4370 + }, + { + "url": "http://127.0.0.1:5024/assets.json?v=7db52585ba", + "status": 200, + "bytes": 1106, + "index": 55, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 56, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 57, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4372 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 58, + "startMs": 4206, + "headersMs": 4368, + "endMs": 4374 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 59, + "startMs": 4372, + "headersMs": 4524, + "endMs": 4526 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 60, + "startMs": 4374, + "headersMs": 4524, + "endMs": 4526 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 61, + "startMs": 4374, + "headersMs": 4526, + "endMs": 4531 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 62, + "startMs": 4374, + "headersMs": 4526, + "endMs": 4545 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 63, + "startMs": 4376, + "headersMs": 4526, + "endMs": 4536 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 64, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4684 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 65, + "startMs": 4528, + "headersMs": 4679, + "endMs": 4692 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 66, + "startMs": 4533, + "headersMs": 4684, + "endMs": 4691 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 67, + "startMs": 4538, + "headersMs": 4689, + "endMs": 4702 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 68, + "startMs": 4547, + "headersMs": 4698, + "endMs": 4852 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 69, + "startMs": 4686, + "headersMs": 4839, + "endMs": 5223 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 70, + "startMs": 4692, + "headersMs": 4844, + "endMs": 4942 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 71, + "startMs": 4694, + "headersMs": 4844, + "endMs": 5018 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 72, + "startMs": 4704, + "headersMs": 4857, + "endMs": 4916 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 73, + "startMs": 4855, + "headersMs": 5007, + "endMs": 5164 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 74, + "startMs": 4918, + "headersMs": 5069, + "endMs": 5072 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 75, + "startMs": 4944, + "headersMs": 5096, + "endMs": 5104 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 76, + "startMs": 5020, + "headersMs": 5172, + "endMs": 5186 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 77, + "startMs": 5074, + "headersMs": 5225, + "endMs": 5234 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 78, + "startMs": 5106, + "headersMs": 5257, + "endMs": 5280 + }, + { + "url": "http://127.0.0.1:5024/index.html?v=275991ee89", + "status": 200, + "bytes": 13687, + "index": 79, + "startMs": 5167, + "headersMs": 5319, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 80, + "startMs": 5188, + "headersMs": 5339, + "endMs": 5353 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 81, + "startMs": 5194, + "headersMs": 5345, + "endMs": 5352 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 82, + "startMs": 5225, + "headersMs": 5378, + "endMs": 5389 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 83, + "startMs": 5235, + "headersMs": 5387, + "endMs": 5403 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 84, + "startMs": 5283, + "headersMs": 5435, + "endMs": 5438 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 85, + "startMs": 5354, + "headersMs": 5506, + "endMs": 5510 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 86, + "startMs": 5355, + "headersMs": 5506, + "endMs": 5512 + }, + { + "url": "http://127.0.0.1:5024/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 87, + "startMs": 5390, + "headersMs": 5553, + "endMs": 5574 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 88, + "startMs": 5390, + "headersMs": 5554, + "endMs": 5575 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 89, + "startMs": 5406, + "headersMs": 5557, + "endMs": 5561 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 90, + "startMs": 5440, + "headersMs": 5591, + "endMs": 5596 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 91, + "startMs": 5512, + "headersMs": 5663, + "endMs": 5693 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 92, + "startMs": 5513, + "headersMs": 5664, + "endMs": 5666 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 93, + "startMs": 5562, + "headersMs": 5714, + "endMs": 5717 + }, + { + "url": "http://127.0.0.1:5024/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 94, + "startMs": 5576, + "headersMs": 5731, + "endMs": 5735 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 95, + "startMs": 5577, + "headersMs": 5732, + "endMs": 5735 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 96, + "startMs": 5597, + "headersMs": 5749, + "endMs": 5753 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 97, + "startMs": 5668, + "headersMs": 5820, + "endMs": 5826 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 98, + "startMs": 5695, + "headersMs": 5847, + "endMs": 5870 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 99, + "startMs": 5719, + "headersMs": 5869, + "endMs": 5874 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 100, + "startMs": 5737, + "headersMs": 5888, + "endMs": 5902 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 101, + "startMs": 5737, + "headersMs": 5889, + "endMs": 5897 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 102, + "startMs": 5755, + "headersMs": 5906, + "endMs": 5923 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 103, + "startMs": 5828, + "headersMs": 5978, + "endMs": 6146 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 104, + "startMs": 5872, + "headersMs": 6024, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 105, + "startMs": 5876, + "headersMs": 6027, + "endMs": 6048 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 106, + "startMs": 5899, + "headersMs": 6051, + "endMs": 6054 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 107, + "startMs": 6156, + "headersMs": 6309, + "endMs": 6354 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 108, + "startMs": 6356, + "headersMs": 6508, + "endMs": 6518 + }, + { + "url": "http://127.0.0.1:5024/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 109, + "startMs": 7181, + "headersMs": 7339, + "endMs": 7345 + }, + { + "url": "http://127.0.0.1:5024/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 110, + "startMs": 7181, + "headersMs": 7340, + "endMs": 7343 + }, + { + "url": "http://127.0.0.1:5024/car-mode.js?v=815b1d6cdb", + "status": 200, + "bytes": 2077, + "index": 111, + "startMs": 7181, + "headersMs": 7346, + "endMs": 7355 + }, + { + "url": "http://127.0.0.1:5024/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 112, + "startMs": 7181, + "headersMs": 7347, + "endMs": 7348 + }, + { + "url": "http://127.0.0.1:5024/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 113, + "startMs": 7181, + "headersMs": 7359, + "endMs": 7380 + }, + { + "url": "http://127.0.0.1:5024/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 114, + "startMs": 7181, + "headersMs": 7363, + "endMs": 7369 + }, + { + "url": "http://127.0.0.1:5024/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 115, + "startMs": 7345, + "headersMs": 7500, + "endMs": 7507 + }, + { + "url": "http://127.0.0.1:5024/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 116, + "startMs": 7347, + "headersMs": 7504, + "endMs": 7512 + }, + { + "url": "http://127.0.0.1:5024/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 117, + "startMs": 7350, + "headersMs": 7507, + "endMs": 7512 + }, + { + "url": "http://127.0.0.1:5024/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 118, + "startMs": 7357, + "headersMs": 7512, + "endMs": 7520 + }, + { + "url": "http://127.0.0.1:5024/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 119, + "startMs": 7371, + "headersMs": 7536, + "endMs": 7561 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 120, + "startMs": 7382, + "headersMs": 7537, + "endMs": 7646 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 121, + "startMs": 7509, + "headersMs": 7660, + "endMs": 7799 + }, + { + "url": "http://127.0.0.1:5024/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 122, + "startMs": 7514, + "headersMs": 7674, + "endMs": 7691 + }, + { + "url": "http://127.0.0.1:5024/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 123, + "startMs": 7514, + "headersMs": 7677, + "endMs": 7682 + }, + { + "url": "http://127.0.0.1:5024/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 124, + "startMs": 7521, + "headersMs": 7679, + "endMs": 7683 + }, + { + "url": "http://127.0.0.1:5024/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 125, + "startMs": 7563, + "headersMs": 7717, + "endMs": 7719 + }, + { + "url": "http://127.0.0.1:5024/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 126, + "startMs": 7648, + "headersMs": 7803, + "endMs": 7808 + }, + { + "url": "http://127.0.0.1:5024/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 127, + "startMs": 7684, + "headersMs": 7842, + "endMs": 7855 + }, + { + "url": "http://127.0.0.1:5024/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 128, + "startMs": 7684, + "headersMs": 7848, + "endMs": 7859 + }, + { + "url": "http://127.0.0.1:5024/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 129, + "startMs": 7692, + "headersMs": 7865, + "endMs": 7888 + }, + { + "url": "http://127.0.0.1:5024/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 130, + "startMs": 7721, + "headersMs": 7876, + "endMs": 7882 + }, + { + "url": "http://127.0.0.1:5024/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 131, + "startMs": 7801, + "headersMs": 7957, + "endMs": 7964 + }, + { + "url": "http://127.0.0.1:5024/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 132, + "startMs": 7810, + "headersMs": 7971, + "endMs": 7985 + }, + { + "url": "http://127.0.0.1:5024/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 133, + "startMs": 7857, + "headersMs": 8012, + "endMs": 8020 + }, + { + "url": "http://127.0.0.1:5024/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 134, + "startMs": 7861, + "headersMs": 8015, + "endMs": 8020 + }, + { + "url": "http://127.0.0.1:5024/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 135, + "startMs": 7884, + "headersMs": 8034, + "endMs": 8047 + }, + { + "url": "http://127.0.0.1:5024/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 136, + "startMs": 7890, + "headersMs": 8054, + "endMs": 8075 + }, + { + "url": "http://127.0.0.1:5024/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 137, + "startMs": 7966, + "headersMs": 8126, + "endMs": 8142 + }, + { + "url": "http://127.0.0.1:5024/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 138, + "startMs": 7987, + "headersMs": 8147, + "endMs": 8161 + }, + { + "url": "http://127.0.0.1:5024/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 139, + "startMs": 8022, + "headersMs": 8213, + "endMs": 8251 + }, + { + "url": "http://127.0.0.1:5024/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 140, + "startMs": 8022, + "headersMs": 8240, + "endMs": 8268 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 141, + "startMs": 8049, + "headersMs": 8248, + "endMs": 8256 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 142, + "startMs": 8077, + "headersMs": 8254, + "endMs": 8258 + }, + { + "url": "http://127.0.0.1:5024/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 143, + "startMs": 8144, + "headersMs": 8328, + "endMs": 8359 + }, + { + "url": "http://127.0.0.1:5024/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 144, + "startMs": 8163, + "headersMs": 8519, + "endMs": 8744 + }, + { + "url": "http://127.0.0.1:5024/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 145, + "startMs": 8254, + "headersMs": 8528, + "endMs": 8541 + }, + { + "url": "http://127.0.0.1:5024/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 146, + "startMs": 8257, + "headersMs": 8532, + "endMs": 8538 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 301, + "responseStart": 461, + "end": 461, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 677, + "end": 677, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 699, + "end": 699, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 301, + "responseStart": 705, + "end": 705, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 709, + "end": 709, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 806, + "end": 807, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 302, + "responseStart": 841, + "end": 841, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 302, + "responseStart": 860, + "end": 860, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 862, + "end": 862, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 875, + "end": 875, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 964, + "end": 964, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 1000, + "end": 1000, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 303, + "responseStart": 1007, + "end": 1007, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1042, + "end": 1043, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 303, + "responseStart": 1048, + "end": 1048, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1048, + "end": 1049, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1135, + "end": 1135, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 303, + "responseStart": 1164, + "end": 1164, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 303, + "responseStart": 1184, + "end": 1184, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 303, + "responseStart": 1204, + "end": 1204, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1215, + "end": 1216, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1216, + "end": 1216, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1295, + "end": 1295, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1333, + "end": 1333, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1360, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 304, + "responseStart": 1374, + "end": 1375, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1374, + "end": 1375, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 304, + "responseStart": 1394, + "end": 1395, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "bytes": 2929, + "start": 304, + "responseStart": 1471, + "end": 1472, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 304, + "responseStart": 1492, + "end": 1492, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 304, + "responseStart": 1520, + "end": 1520, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1542, + "end": 1543, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 305, + "responseStart": 1554, + "end": 1554, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1561, + "end": 1561, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 305, + "responseStart": 1633, + "end": 1633, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 305, + "responseStart": 1648, + "end": 1648, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 305, + "responseStart": 1677, + "end": 1677, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 305, + "responseStart": 1702, + "end": 1703, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 305, + "responseStart": 1726, + "end": 1726, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "bytes": 165895, + "start": 305, + "responseStart": 2999, + "end": 3504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 822, + "responseStart": 2716, + "end": 2717, + "initiator": "link" + } + ] + }, + { + "fcp": 1615, + "requests": [ + { + "url": "http://127.0.0.1:5024/?v=benchmedia01", + "status": 200, + "bytes": 13687, + "index": 147, + "startMs": 17, + "headersMs": 169, + "endMs": 238 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 148, + "startMs": 247, + "headersMs": 398, + "endMs": 401 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 149, + "startMs": 248, + "headersMs": 399, + "endMs": 785 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 150, + "startMs": 249, + "headersMs": 401, + "endMs": 568 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 151, + "startMs": 249, + "headersMs": 401, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 152, + "startMs": 250, + "headersMs": 401, + "endMs": 431 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 153, + "startMs": 250, + "headersMs": 401, + "endMs": 417 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 154, + "startMs": 401, + "headersMs": 553, + "endMs": 558 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 155, + "startMs": 418, + "headersMs": 570, + "endMs": 575 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 156, + "startMs": 424, + "headersMs": 576, + "endMs": 581 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 157, + "startMs": 432, + "headersMs": 582, + "endMs": 587 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 158, + "startMs": 559, + "headersMs": 710, + "endMs": 719 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 159, + "startMs": 569, + "headersMs": 721, + "endMs": 723 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 160, + "startMs": 576, + "headersMs": 730, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 161, + "startMs": 581, + "headersMs": 732, + "endMs": 738 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 162, + "startMs": 588, + "headersMs": 739, + "endMs": 762 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 163, + "startMs": 720, + "headersMs": 872, + "endMs": 888 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 164, + "startMs": 723, + "headersMs": 875, + "endMs": 879 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 165, + "startMs": 732, + "headersMs": 884, + "endMs": 896 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 166, + "startMs": 738, + "headersMs": 891, + "endMs": 900 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 167, + "startMs": 763, + "headersMs": 914, + "endMs": 931 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 168, + "startMs": 785, + "headersMs": 937, + "endMs": 943 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 169, + "startMs": 879, + "headersMs": 1031, + "endMs": 1042 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 170, + "startMs": 889, + "headersMs": 1041, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 171, + "startMs": 897, + "headersMs": 1048, + "endMs": 1052 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 172, + "startMs": 901, + "headersMs": 1053, + "endMs": 1062 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 173, + "startMs": 932, + "headersMs": 1083, + "endMs": 1109 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 174, + "startMs": 943, + "headersMs": 1095, + "endMs": 1099 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 175, + "startMs": 1043, + "headersMs": 1196, + "endMs": 1200 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 176, + "startMs": 1048, + "headersMs": 1200, + "endMs": 1214 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 177, + "startMs": 1053, + "headersMs": 1203, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 178, + "startMs": 1063, + "headersMs": 1215, + "endMs": 1218 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 179, + "startMs": 1100, + "headersMs": 1253, + "endMs": 1258 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 180, + "startMs": 1110, + "headersMs": 1261, + "endMs": 1272 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 181, + "startMs": 1201, + "headersMs": 1352, + "endMs": 1371 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 182, + "startMs": 1214, + "headersMs": 1366, + "endMs": 1371 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 183, + "startMs": 1219, + "headersMs": 1371, + "endMs": 1377 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 184, + "startMs": 1219, + "headersMs": 1372, + "endMs": 1374 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 185, + "startMs": 1259, + "headersMs": 1410, + "endMs": 1412 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 186, + "startMs": 1272, + "headersMs": 1424, + "endMs": 1429 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 187, + "startMs": 1372, + "headersMs": 1524, + "endMs": 1536 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 188, + "startMs": 1372, + "headersMs": 1525, + "endMs": 2354 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 189, + "startMs": 1375, + "headersMs": 1527, + "endMs": 1547 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 190, + "startMs": 1378, + "headersMs": 1528, + "endMs": 1702 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 191, + "startMs": 1413, + "headersMs": 1565, + "endMs": 1568 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 192, + "startMs": 2415, + "headersMs": 2567, + "endMs": 2569 + }, + { + "url": "http://127.0.0.1:5024/api/version", + "status": 200, + "bytes": 62, + "index": 193, + "startMs": 2439, + "headersMs": 2591, + "endMs": 2592 + }, + { + "url": "http://127.0.0.1:5024/api/user/sync", + "status": 200, + "bytes": 11, + "index": 194, + "startMs": 2440, + "headersMs": 2593, + "endMs": 2594 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 195, + "startMs": 2446, + "headersMs": 2596, + "endMs": 2641 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 196, + "startMs": 2597, + "headersMs": 2750, + "endMs": 2750 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 197, + "startMs": 2648, + "headersMs": 2800, + "endMs": 2809 + }, + { + "url": "http://127.0.0.1:5024/api/manifest", + "status": 200, + "bytes": 3436, + "index": 198, + "startMs": 2814, + "headersMs": 2966, + "endMs": 2984 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 199, + "startMs": 3008, + "headersMs": 3161, + "endMs": 3990 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 200, + "startMs": 3008, + "headersMs": 3161, + "endMs": 3171 + }, + { + "url": "http://127.0.0.1:5024/assets.json?v=7db52585ba", + "status": 200, + "bytes": 1106, + "index": 201, + "startMs": 3008, + "headersMs": 3161, + "endMs": 3167 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 202, + "startMs": 3008, + "headersMs": 3162, + "endMs": 3165 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 203, + "startMs": 3009, + "headersMs": 3162, + "endMs": 3165 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 204, + "startMs": 3009, + "headersMs": 3162, + "endMs": 3167 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 205, + "startMs": 3167, + "headersMs": 3321, + "endMs": 3323 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 206, + "startMs": 3168, + "headersMs": 3321, + "endMs": 3324 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 207, + "startMs": 3169, + "headersMs": 3321, + "endMs": 3326 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 208, + "startMs": 3169, + "headersMs": 3321, + "endMs": 3340 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 209, + "startMs": 3173, + "headersMs": 3323, + "endMs": 3332 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 210, + "startMs": 3325, + "headersMs": 3476, + "endMs": 3480 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 211, + "startMs": 3326, + "headersMs": 3476, + "endMs": 3488 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 212, + "startMs": 3327, + "headersMs": 3477, + "endMs": 3484 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 213, + "startMs": 3334, + "headersMs": 3485, + "endMs": 3498 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 214, + "startMs": 3341, + "headersMs": 3492, + "endMs": 3646 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 215, + "startMs": 3482, + "headersMs": 3634, + "endMs": 4019 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 216, + "startMs": 3485, + "headersMs": 3637, + "endMs": 3734 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 217, + "startMs": 3489, + "headersMs": 3640, + "endMs": 3813 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 218, + "startMs": 3499, + "headersMs": 3650, + "endMs": 3709 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 219, + "startMs": 3648, + "headersMs": 3800, + "endMs": 3958 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 220, + "startMs": 3711, + "headersMs": 3864, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 221, + "startMs": 3736, + "headersMs": 3886, + "endMs": 3896 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 222, + "startMs": 3815, + "headersMs": 3966, + "endMs": 3981 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 223, + "startMs": 3869, + "headersMs": 4020, + "endMs": 4029 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 224, + "startMs": 3898, + "headersMs": 4049, + "endMs": 4073 + }, + { + "url": "http://127.0.0.1:5024/index.html?v=275991ee89", + "status": 200, + "bytes": 13687, + "index": 225, + "startMs": 3960, + "headersMs": 4112, + "endMs": 4181 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 226, + "startMs": 3983, + "headersMs": 4134, + "endMs": 4149 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 227, + "startMs": 3996, + "headersMs": 4147, + "endMs": 4153 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 228, + "startMs": 4021, + "headersMs": 4172, + "endMs": 4183 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 229, + "startMs": 4030, + "headersMs": 4182, + "endMs": 4197 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 230, + "startMs": 4075, + "headersMs": 4225, + "endMs": 4229 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 231, + "startMs": 4151, + "headersMs": 4303, + "endMs": 4307 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 232, + "startMs": 4154, + "headersMs": 4304, + "endMs": 4309 + }, + { + "url": "http://127.0.0.1:5024/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 233, + "startMs": 4183, + "headersMs": 4334, + "endMs": 4354 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 234, + "startMs": 4185, + "headersMs": 4335, + "endMs": 4358 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 235, + "startMs": 4199, + "headersMs": 4350, + "endMs": 4354 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 236, + "startMs": 4231, + "headersMs": 4382, + "endMs": 4387 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 237, + "startMs": 4309, + "headersMs": 4461, + "endMs": 4491 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 238, + "startMs": 4310, + "headersMs": 4461, + "endMs": 4464 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 239, + "startMs": 4357, + "headersMs": 4507, + "endMs": 4510 + }, + { + "url": "http://127.0.0.1:5024/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 240, + "startMs": 4357, + "headersMs": 4507, + "endMs": 4512 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 241, + "startMs": 4360, + "headersMs": 4510, + "endMs": 4514 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 242, + "startMs": 4388, + "headersMs": 4541, + "endMs": 4545 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 243, + "startMs": 4466, + "headersMs": 4617, + "endMs": 4623 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 244, + "startMs": 4493, + "headersMs": 4645, + "endMs": 4668 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 245, + "startMs": 4512, + "headersMs": 4663, + "endMs": 4668 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 246, + "startMs": 4513, + "headersMs": 4663, + "endMs": 4676 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 247, + "startMs": 4515, + "headersMs": 4668, + "endMs": 4677 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 248, + "startMs": 4547, + "headersMs": 4697, + "endMs": 4714 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 249, + "startMs": 4625, + "headersMs": 4777, + "endMs": 4944 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 250, + "startMs": 4670, + "headersMs": 4821, + "endMs": 4847 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 251, + "startMs": 4670, + "headersMs": 4821, + "endMs": 4842 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 252, + "startMs": 4678, + "headersMs": 4829, + "endMs": 4832 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 253, + "startMs": 4954, + "headersMs": 5106, + "endMs": 5150 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 254, + "startMs": 5152, + "headersMs": 5305, + "endMs": 5314 + }, + { + "url": "http://127.0.0.1:5024/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 255, + "startMs": 5978, + "headersMs": 6130, + "endMs": 6138 + }, + { + "url": "http://127.0.0.1:5024/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 256, + "startMs": 5978, + "headersMs": 6131, + "endMs": 6133 + }, + { + "url": "http://127.0.0.1:5024/car-mode.js?v=815b1d6cdb", + "status": 200, + "bytes": 2077, + "index": 257, + "startMs": 5978, + "headersMs": 6131, + "endMs": 6141 + }, + { + "url": "http://127.0.0.1:5024/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 258, + "startMs": 5978, + "headersMs": 6131, + "endMs": 6131 + }, + { + "url": "http://127.0.0.1:5024/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 259, + "startMs": 5978, + "headersMs": 6131, + "endMs": 6152 + }, + { + "url": "http://127.0.0.1:5024/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 260, + "startMs": 5979, + "headersMs": 6131, + "endMs": 6138 + }, + { + "url": "http://127.0.0.1:5024/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 261, + "startMs": 6133, + "headersMs": 6285, + "endMs": 6291 + }, + { + "url": "http://127.0.0.1:5024/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 262, + "startMs": 6134, + "headersMs": 6285, + "endMs": 6292 + }, + { + "url": "http://127.0.0.1:5024/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 263, + "startMs": 6140, + "headersMs": 6291, + "endMs": 6296 + }, + { + "url": "http://127.0.0.1:5024/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 264, + "startMs": 6141, + "headersMs": 6291, + "endMs": 6299 + }, + { + "url": "http://127.0.0.1:5024/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 265, + "startMs": 6142, + "headersMs": 6293, + "endMs": 6316 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 266, + "startMs": 6154, + "headersMs": 6305, + "endMs": 6415 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 267, + "startMs": 6293, + "headersMs": 6443, + "endMs": 6580 + }, + { + "url": "http://127.0.0.1:5024/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 268, + "startMs": 6294, + "headersMs": 6444, + "endMs": 6460 + }, + { + "url": "http://127.0.0.1:5024/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 269, + "startMs": 6298, + "headersMs": 6448, + "endMs": 6453 + }, + { + "url": "http://127.0.0.1:5024/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 270, + "startMs": 6300, + "headersMs": 6451, + "endMs": 6455 + }, + { + "url": "http://127.0.0.1:5024/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 271, + "startMs": 6318, + "headersMs": 6469, + "endMs": 6472 + }, + { + "url": "http://127.0.0.1:5024/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 272, + "startMs": 6417, + "headersMs": 6569, + "endMs": 6576 + }, + { + "url": "http://127.0.0.1:5024/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 273, + "startMs": 6455, + "headersMs": 6607, + "endMs": 6619 + }, + { + "url": "http://127.0.0.1:5024/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 274, + "startMs": 6456, + "headersMs": 6607, + "endMs": 6617 + }, + { + "url": "http://127.0.0.1:5024/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 275, + "startMs": 6464, + "headersMs": 6614, + "endMs": 6637 + }, + { + "url": "http://127.0.0.1:5024/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 276, + "startMs": 6474, + "headersMs": 6624, + "endMs": 6630 + }, + { + "url": "http://127.0.0.1:5024/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 277, + "startMs": 6578, + "headersMs": 6729, + "endMs": 6737 + }, + { + "url": "http://127.0.0.1:5024/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 278, + "startMs": 6582, + "headersMs": 6733, + "endMs": 6747 + }, + { + "url": "http://127.0.0.1:5024/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 279, + "startMs": 6619, + "headersMs": 6770, + "endMs": 6778 + }, + { + "url": "http://127.0.0.1:5024/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 280, + "startMs": 6620, + "headersMs": 6771, + "endMs": 6775 + }, + { + "url": "http://127.0.0.1:5024/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 281, + "startMs": 6632, + "headersMs": 6782, + "endMs": 6794 + }, + { + "url": "http://127.0.0.1:5024/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 282, + "startMs": 6639, + "headersMs": 6789, + "endMs": 6810 + }, + { + "url": "http://127.0.0.1:5024/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 283, + "startMs": 6739, + "headersMs": 6890, + "endMs": 6905 + }, + { + "url": "http://127.0.0.1:5024/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 284, + "startMs": 6749, + "headersMs": 6900, + "endMs": 6914 + }, + { + "url": "http://127.0.0.1:5024/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 285, + "startMs": 6777, + "headersMs": 6927, + "endMs": 6966 + }, + { + "url": "http://127.0.0.1:5024/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 286, + "startMs": 6780, + "headersMs": 6930, + "endMs": 6957 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 287, + "startMs": 6796, + "headersMs": 6947, + "endMs": 6956 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 288, + "startMs": 6813, + "headersMs": 6963, + "endMs": 6970 + }, + { + "url": "http://127.0.0.1:5024/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 289, + "startMs": 6907, + "headersMs": 7059, + "endMs": 7090 + }, + { + "url": "http://127.0.0.1:5024/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 290, + "startMs": 6917, + "headersMs": 7069, + "endMs": 7294 + }, + { + "url": "http://127.0.0.1:5024/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 291, + "startMs": 6958, + "headersMs": 7110, + "endMs": 7123 + }, + { + "url": "http://127.0.0.1:5024/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 292, + "startMs": 6958, + "headersMs": 7110, + "endMs": 7117 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 231, + "responseStart": 385, + "end": 385, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 232, + "responseStart": 402, + "end": 402, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 232, + "responseStart": 408, + "end": 408, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 232, + "responseStart": 415, + "end": 416, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 232, + "responseStart": 552, + "end": 553, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "bytes": 983, + "start": 233, + "responseStart": 543, + "end": 543, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 233, + "responseStart": 560, + "end": 560, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 233, + "responseStart": 565, + "end": 565, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 233, + "responseStart": 571, + "end": 572, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 233, + "responseStart": 703, + "end": 704, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 233, + "responseStart": 707, + "end": 707, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 233, + "responseStart": 716, + "end": 716, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 234, + "responseStart": 722, + "end": 722, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 234, + "responseStart": 746, + "end": 747, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 234, + "responseStart": 873, + "end": 873, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 235, + "responseStart": 863, + "end": 863, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 235, + "responseStart": 880, + "end": 881, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 235, + "responseStart": 885, + "end": 885, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 235, + "responseStart": 915, + "end": 916, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 237, + "responseStart": 927, + "end": 927, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 237, + "responseStart": 1027, + "end": 1027, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 237, + "responseStart": 1032, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 237, + "responseStart": 1037, + "end": 1037, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 237, + "responseStart": 1047, + "end": 1047, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 237, + "responseStart": 1093, + "end": 1094, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 238, + "responseStart": 1084, + "end": 1084, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 238, + "responseStart": 1184, + "end": 1185, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 238, + "responseStart": 1198, + "end": 1199, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 238, + "responseStart": 1203, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "bytes": 2929, + "start": 238, + "responseStart": 1202, + "end": 1203, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 238, + "responseStart": 1242, + "end": 1243, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 239, + "responseStart": 1256, + "end": 1256, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 239, + "responseStart": 1356, + "end": 1356, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 239, + "responseStart": 1355, + "end": 1356, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 239, + "responseStart": 1358, + "end": 1359, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 239, + "responseStart": 1362, + "end": 1362, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 239, + "responseStart": 1397, + "end": 1397, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 239, + "responseStart": 1413, + "end": 1413, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 239, + "responseStart": 1520, + "end": 1521, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "bytes": 165895, + "start": 240, + "responseStart": 1836, + "end": 2339, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 574, + "responseStart": 1532, + "end": 1532, + "initiator": "link" + } + ] + }, + { + "fcp": 1588, + "requests": [ + { + "url": "http://127.0.0.1:5024/?v=benchmedia01", + "status": 200, + "bytes": 13687, + "index": 293, + "startMs": 19, + "headersMs": 171, + "endMs": 240 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 294, + "startMs": 248, + "headersMs": 399, + "endMs": 784 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 295, + "startMs": 249, + "headersMs": 400, + "endMs": 573 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 296, + "startMs": 249, + "headersMs": 400, + "endMs": 403 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 297, + "startMs": 250, + "headersMs": 401, + "endMs": 568 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 298, + "startMs": 250, + "headersMs": 401, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 299, + "startMs": 251, + "headersMs": 401, + "endMs": 430 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 300, + "startMs": 404, + "headersMs": 556, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 301, + "startMs": 424, + "headersMs": 576, + "endMs": 580 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 302, + "startMs": 431, + "headersMs": 582, + "endMs": 587 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 303, + "startMs": 570, + "headersMs": 722, + "endMs": 727 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 304, + "startMs": 572, + "headersMs": 723, + "endMs": 726 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 305, + "startMs": 573, + "headersMs": 723, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 306, + "startMs": 580, + "headersMs": 732, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 307, + "startMs": 587, + "headersMs": 738, + "endMs": 741 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 308, + "startMs": 727, + "headersMs": 879, + "endMs": 885 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 309, + "startMs": 728, + "headersMs": 879, + "endMs": 900 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 310, + "startMs": 732, + "headersMs": 882, + "endMs": 898 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 311, + "startMs": 735, + "headersMs": 886, + "endMs": 890 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 312, + "startMs": 741, + "headersMs": 892, + "endMs": 905 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 313, + "startMs": 785, + "headersMs": 936, + "endMs": 945 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 314, + "startMs": 887, + "headersMs": 1039, + "endMs": 1056 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 315, + "startMs": 890, + "headersMs": 1041, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 316, + "startMs": 898, + "headersMs": 1049, + "endMs": 1060 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 317, + "startMs": 901, + "headersMs": 1052, + "endMs": 1058 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 318, + "startMs": 906, + "headersMs": 1057, + "endMs": 1061 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 319, + "startMs": 946, + "headersMs": 1097, + "endMs": 1107 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 320, + "startMs": 1049, + "headersMs": 1200, + "endMs": 1225 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 321, + "startMs": 1057, + "headersMs": 1208, + "endMs": 1211 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 322, + "startMs": 1058, + "headersMs": 1208, + "endMs": 1212 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 323, + "startMs": 1060, + "headersMs": 1212, + "endMs": 1225 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 324, + "startMs": 1061, + "headersMs": 1212, + "endMs": 1225 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 325, + "startMs": 1108, + "headersMs": 1259, + "endMs": 1263 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 326, + "startMs": 1212, + "headersMs": 1365, + "endMs": 1369 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 327, + "startMs": 1213, + "headersMs": 1365, + "endMs": 1376 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 328, + "startMs": 1227, + "headersMs": 1377, + "endMs": 1396 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 329, + "startMs": 1227, + "headersMs": 1378, + "endMs": 1382 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 330, + "startMs": 1227, + "headersMs": 1378, + "endMs": 1383 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 331, + "startMs": 1263, + "headersMs": 1415, + "endMs": 1418 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 332, + "startMs": 1369, + "headersMs": 1524, + "endMs": 1527 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 333, + "startMs": 1376, + "headersMs": 1527, + "endMs": 1532 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 334, + "startMs": 1383, + "headersMs": 1533, + "endMs": 1546 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 335, + "startMs": 1383, + "headersMs": 1534, + "endMs": 2370 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 336, + "startMs": 1397, + "headersMs": 1547, + "endMs": 1568 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 337, + "startMs": 1418, + "headersMs": 1569, + "endMs": 1573 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 338, + "startMs": 2429, + "headersMs": 2581, + "endMs": 2582 + }, + { + "url": "http://127.0.0.1:5024/api/version", + "status": 200, + "bytes": 62, + "index": 339, + "startMs": 2450, + "headersMs": 2601, + "endMs": 2601 + }, + { + "url": "http://127.0.0.1:5024/api/user/sync", + "status": 200, + "bytes": 11, + "index": 340, + "startMs": 2451, + "headersMs": 2604, + "endMs": 2604 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 341, + "startMs": 2456, + "headersMs": 2607, + "endMs": 2651 + }, + { + "url": "http://127.0.0.1:5024/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 342, + "startMs": 2606, + "headersMs": 2761, + "endMs": 2763 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 343, + "startMs": 2658, + "headersMs": 2809, + "endMs": 2819 + }, + { + "url": "http://127.0.0.1:5024/api/manifest", + "status": 200, + "bytes": 3436, + "index": 344, + "startMs": 2823, + "headersMs": 2976, + "endMs": 2993 + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "status": 200, + "bytes": 165895, + "index": 345, + "startMs": 3015, + "headersMs": 3166, + "endMs": 3996 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 346, + "startMs": 3015, + "headersMs": 3167, + "endMs": 3176 + }, + { + "url": "http://127.0.0.1:5024/assets.json?v=7db52585ba", + "status": 200, + "bytes": 1106, + "index": 347, + "startMs": 3015, + "headersMs": 3167, + "endMs": 3172 + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 348, + "startMs": 3015, + "headersMs": 3167, + "endMs": 3170 + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 349, + "startMs": 3015, + "headersMs": 3167, + "endMs": 3170 + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 350, + "startMs": 3015, + "headersMs": 3167, + "endMs": 3173 + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 351, + "startMs": 3173, + "headersMs": 3325, + "endMs": 3328 + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 352, + "startMs": 3173, + "headersMs": 3325, + "endMs": 3330 + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 353, + "startMs": 3173, + "headersMs": 3326, + "endMs": 3330 + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 354, + "startMs": 3175, + "headersMs": 3326, + "endMs": 3345 + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 355, + "startMs": 3178, + "headersMs": 3329, + "endMs": 3340 + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 356, + "startMs": 3331, + "headersMs": 3482, + "endMs": 3487 + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 357, + "startMs": 3332, + "headersMs": 3482, + "endMs": 3495 + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 358, + "startMs": 3332, + "headersMs": 3482, + "endMs": 3488 + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 359, + "startMs": 3341, + "headersMs": 3492, + "endMs": 3504 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 360, + "startMs": 3346, + "headersMs": 3497, + "endMs": 3651 + }, + { + "url": "http://127.0.0.1:5024/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 361, + "startMs": 3488, + "headersMs": 3640, + "endMs": 4026 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 362, + "startMs": 3490, + "headersMs": 3641, + "endMs": 3738 + }, + { + "url": "http://127.0.0.1:5024/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 363, + "startMs": 3497, + "headersMs": 3647, + "endMs": 3821 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 364, + "startMs": 3505, + "headersMs": 3657, + "endMs": 3716 + }, + { + "url": "http://127.0.0.1:5024/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 365, + "startMs": 3653, + "headersMs": 3804, + "endMs": 3962 + }, + { + "url": "http://127.0.0.1:5024/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 366, + "startMs": 3719, + "headersMs": 3871, + "endMs": 3874 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 367, + "startMs": 3740, + "headersMs": 3891, + "endMs": 3900 + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 368, + "startMs": 3826, + "headersMs": 3977, + "endMs": 3991 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 369, + "startMs": 3875, + "headersMs": 4028, + "endMs": 4036 + }, + { + "url": "http://127.0.0.1:5024/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 370, + "startMs": 3902, + "headersMs": 4053, + "endMs": 4077 + }, + { + "url": "http://127.0.0.1:5024/index.html?v=275991ee89", + "status": 200, + "bytes": 13687, + "index": 371, + "startMs": 3964, + "headersMs": 4115, + "endMs": 4184 + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "status": 200, + "bytes": 3007, + "index": 372, + "startMs": 3994, + "headersMs": 4146, + "endMs": 4161 + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 373, + "startMs": 4002, + "headersMs": 4153, + "endMs": 4159 + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 374, + "startMs": 4029, + "headersMs": 4180, + "endMs": 4191 + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 375, + "startMs": 4038, + "headersMs": 4189, + "endMs": 4204 + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 376, + "startMs": 4079, + "headersMs": 4229, + "endMs": 4233 + }, + { + "url": "http://127.0.0.1:5024/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 377, + "startMs": 4161, + "headersMs": 4314, + "endMs": 4317 + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 378, + "startMs": 4163, + "headersMs": 4314, + "endMs": 4319 + }, + { + "url": "http://127.0.0.1:5024/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 379, + "startMs": 4187, + "headersMs": 4338, + "endMs": 4358 + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 380, + "startMs": 4193, + "headersMs": 4343, + "endMs": 4365 + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 381, + "startMs": 4206, + "headersMs": 4357, + "endMs": 4360 + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 382, + "startMs": 4235, + "headersMs": 4386, + "endMs": 4390 + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 383, + "startMs": 4319, + "headersMs": 4471, + "endMs": 4500 + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 384, + "startMs": 4321, + "headersMs": 4471, + "endMs": 4474 + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 385, + "startMs": 4360, + "headersMs": 4512, + "endMs": 4515 + }, + { + "url": "http://127.0.0.1:5024/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 386, + "startMs": 4361, + "headersMs": 4513, + "endMs": 4517 + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 387, + "startMs": 4366, + "headersMs": 4517, + "endMs": 4521 + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 388, + "startMs": 4392, + "headersMs": 4544, + "endMs": 4548 + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 389, + "startMs": 4475, + "headersMs": 4628, + "endMs": 4633 + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 390, + "startMs": 4504, + "headersMs": 4655, + "endMs": 4677 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 391, + "startMs": 4517, + "headersMs": 4668, + "endMs": 4673 + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "status": 200, + "bytes": 2929, + "index": 392, + "startMs": 4519, + "headersMs": 4669, + "endMs": 4684 + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 393, + "startMs": 4522, + "headersMs": 4673, + "endMs": 4683 + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 394, + "startMs": 4550, + "headersMs": 4701, + "endMs": 4718 + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 395, + "startMs": 4635, + "headersMs": 4787, + "endMs": 4956 + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 396, + "startMs": 4675, + "headersMs": 4826, + "endMs": 4852 + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 397, + "startMs": 4679, + "headersMs": 4829, + "endMs": 4850 + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 398, + "startMs": 4684, + "headersMs": 4835, + "endMs": 4837 + }, + { + "url": "http://127.0.0.1:5024/sw.js", + "status": 200, + "bytes": 8841, + "index": 399, + "startMs": 4966, + "headersMs": 5118, + "endMs": 5162 + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 400, + "startMs": 5164, + "headersMs": 5316, + "endMs": 5325 + }, + { + "url": "http://127.0.0.1:5024/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 401, + "startMs": 5990, + "headersMs": 6142, + "endMs": 6149 + }, + { + "url": "http://127.0.0.1:5024/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 402, + "startMs": 5990, + "headersMs": 6142, + "endMs": 6144 + }, + { + "url": "http://127.0.0.1:5024/car-mode.js?v=815b1d6cdb", + "status": 200, + "bytes": 2077, + "index": 403, + "startMs": 5990, + "headersMs": 6142, + "endMs": 6153 + }, + { + "url": "http://127.0.0.1:5024/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 404, + "startMs": 5990, + "headersMs": 6142, + "endMs": 6144 + }, + { + "url": "http://127.0.0.1:5024/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 405, + "startMs": 5991, + "headersMs": 6143, + "endMs": 6164 + }, + { + "url": "http://127.0.0.1:5024/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 406, + "startMs": 5991, + "headersMs": 6143, + "endMs": 6149 + }, + { + "url": "http://127.0.0.1:5024/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 407, + "startMs": 6146, + "headersMs": 6300, + "endMs": 6306 + }, + { + "url": "http://127.0.0.1:5024/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 408, + "startMs": 6147, + "headersMs": 6300, + "endMs": 6308 + }, + { + "url": "http://127.0.0.1:5024/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 409, + "startMs": 6151, + "headersMs": 6301, + "endMs": 6306 + }, + { + "url": "http://127.0.0.1:5024/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 410, + "startMs": 6151, + "headersMs": 6301, + "endMs": 6308 + }, + { + "url": "http://127.0.0.1:5024/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 411, + "startMs": 6155, + "headersMs": 6306, + "endMs": 6329 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 412, + "startMs": 6166, + "headersMs": 6316, + "endMs": 6429 + }, + { + "url": "http://127.0.0.1:5024/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 413, + "startMs": 6308, + "headersMs": 6458, + "endMs": 6595 + }, + { + "url": "http://127.0.0.1:5024/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 414, + "startMs": 6308, + "headersMs": 6459, + "endMs": 6475 + }, + { + "url": "http://127.0.0.1:5024/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 415, + "startMs": 6309, + "headersMs": 6460, + "endMs": 6466 + }, + { + "url": "http://127.0.0.1:5024/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 416, + "startMs": 6309, + "headersMs": 6460, + "endMs": 6464 + }, + { + "url": "http://127.0.0.1:5024/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 417, + "startMs": 6331, + "headersMs": 6482, + "endMs": 6484 + }, + { + "url": "http://127.0.0.1:5024/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 418, + "startMs": 6431, + "headersMs": 6582, + "endMs": 6588 + }, + { + "url": "http://127.0.0.1:5024/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 419, + "startMs": 6465, + "headersMs": 6617, + "endMs": 6629 + }, + { + "url": "http://127.0.0.1:5024/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 420, + "startMs": 6467, + "headersMs": 6617, + "endMs": 6627 + }, + { + "url": "http://127.0.0.1:5024/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 421, + "startMs": 6477, + "headersMs": 6627, + "endMs": 6649 + }, + { + "url": "http://127.0.0.1:5024/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 422, + "startMs": 6486, + "headersMs": 6637, + "endMs": 6642 + }, + { + "url": "http://127.0.0.1:5024/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 423, + "startMs": 6590, + "headersMs": 6741, + "endMs": 6747 + }, + { + "url": "http://127.0.0.1:5024/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 424, + "startMs": 6597, + "headersMs": 6748, + "endMs": 6761 + }, + { + "url": "http://127.0.0.1:5024/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 425, + "startMs": 6629, + "headersMs": 6781, + "endMs": 6789 + }, + { + "url": "http://127.0.0.1:5024/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 426, + "startMs": 6630, + "headersMs": 6782, + "endMs": 6786 + }, + { + "url": "http://127.0.0.1:5024/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 427, + "startMs": 6644, + "headersMs": 6795, + "endMs": 6807 + }, + { + "url": "http://127.0.0.1:5024/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 428, + "startMs": 6650, + "headersMs": 6801, + "endMs": 6822 + }, + { + "url": "http://127.0.0.1:5024/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 429, + "startMs": 6750, + "headersMs": 6901, + "endMs": 6916 + }, + { + "url": "http://127.0.0.1:5024/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 430, + "startMs": 6763, + "headersMs": 6913, + "endMs": 6927 + }, + { + "url": "http://127.0.0.1:5024/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 431, + "startMs": 6788, + "headersMs": 6939, + "endMs": 6977 + }, + { + "url": "http://127.0.0.1:5024/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 432, + "startMs": 6791, + "headersMs": 6941, + "endMs": 6969 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 433, + "startMs": 6808, + "headersMs": 6960, + "endMs": 6968 + }, + { + "url": "http://127.0.0.1:5024/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 434, + "startMs": 6824, + "headersMs": 6974, + "endMs": 6980 + }, + { + "url": "http://127.0.0.1:5024/theme-glass.css?v=2c482caf77", + "status": 200, + "bytes": 6039, + "index": 435, + "startMs": 6918, + "headersMs": 7070, + "endMs": 7101 + }, + { + "url": "http://127.0.0.1:5024/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 436, + "startMs": 6929, + "headersMs": 7081, + "endMs": 7305 + }, + { + "url": "http://127.0.0.1:5024/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 437, + "startMs": 6970, + "headersMs": 7122, + "endMs": 7134 + }, + { + "url": "http://127.0.0.1:5024/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 438, + "startMs": 6971, + "headersMs": 7122, + "endMs": 7128 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5024/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 230, + "responseStart": 385, + "end": 386, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 230, + "responseStart": 405, + "end": 406, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 230, + "responseStart": 412, + "end": 413, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 230, + "responseStart": 550, + "end": 552, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/lazy.js?v=98f6a419c3", + "bytes": 3007, + "start": 231, + "responseStart": 554, + "end": 554, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/recommendations.css?v=055101368d", + "bytes": 983, + "start": 231, + "responseStart": 562, + "end": 562, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 231, + "responseStart": 569, + "end": 569, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 231, + "responseStart": 708, + "end": 709, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 231, + "responseStart": 709, + "end": 709, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 231, + "responseStart": 713, + "end": 714, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 231, + "responseStart": 716, + "end": 717, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 231, + "responseStart": 723, + "end": 723, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5024/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 232, + "responseStart": 867, + "end": 868, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 232, + "responseStart": 872, + "end": 872, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 232, + "responseStart": 880, + "end": 880, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 232, + "responseStart": 882, + "end": 883, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 232, + "responseStart": 887, + "end": 887, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 232, + "responseStart": 927, + "end": 927, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 232, + "responseStart": 1030, + "end": 1030, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 232, + "responseStart": 1038, + "end": 1038, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 232, + "responseStart": 1042, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 233, + "responseStart": 1040, + "end": 1040, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 233, + "responseStart": 1043, + "end": 1043, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 233, + "responseStart": 1089, + "end": 1089, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 233, + "responseStart": 1194, + "end": 1194, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 233, + "responseStart": 1194, + "end": 1194, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 233, + "responseStart": 1208, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/settings-sections.js?v=f5ff449884", + "bytes": 2929, + "start": 233, + "responseStart": 1208, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 233, + "responseStart": 1207, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 234, + "responseStart": 1245, + "end": 1245, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 234, + "responseStart": 1351, + "end": 1351, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 234, + "responseStart": 1358, + "end": 1358, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 234, + "responseStart": 1364, + "end": 1364, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 234, + "responseStart": 1365, + "end": 1365, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 234, + "responseStart": 1378, + "end": 1379, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 234, + "responseStart": 1400, + "end": 1400, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 234, + "responseStart": 1509, + "end": 1510, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 234, + "responseStart": 1514, + "end": 1515, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 234, + "responseStart": 1528, + "end": 1528, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/app.js?v=4032c3bab6", + "bytes": 165895, + "start": 234, + "responseStart": 1843, + "end": 2354, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5024/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 565, + "responseStart": 1550, + "end": 1551, + "initiator": "link" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-force-cache.json b/perf/results/phase6-force-cache.json new file mode 100644 index 0000000..43e4c6d --- /dev/null +++ b/perf/results/phase6-force-cache.json @@ -0,0 +1,7338 @@ +{ + "date": "2026-10-08T00:36:28.468Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-force-cache", + "sourceCommit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "frontendBuildTag": "90edfddd055d", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159, + 159, + 159 + ] + }, + "wireBytes": { + "median": 1097006, + "min": 1097006, + "max": 1097006, + "values": [ + 1097006, + 1097006, + 1097006 + ] + }, + "fcp": { + "median": 1745, + "min": 1735, + "max": 2505, + "values": [ + 2505, + 1745, + 1735 + ] + }, + "lcp": { + "median": 1819, + "min": 1808, + "max": 2574, + "values": [ + 2574, + 1819, + 1808 + ] + }, + "domContentLoaded": { + "median": 2314, + "min": 2312, + "max": 3075, + "values": [ + 3075, + 2314, + 2312 + ] + }, + "bootDone": { + "median": 2318, + "min": 2316, + "max": 3082, + "values": [ + 3082, + 2318, + 2316 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31460, + "min": 31456, + "max": 32240, + "values": [ + 32240, + 31460, + 31456 + ] + }, + "swInstallBytes": { + "median": 1097006, + "min": 1097006, + "max": 1097006, + "values": [ + 1097006, + 1097006, + 1097006 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28064, + "js": 556707, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5079, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:4913/?v=benchmedia01", + "status": 200, + "bytes": 14032, + "index": 1, + "startMs": 18, + "headersMs": 235, + "endMs": 309 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 316, + "headersMs": 470, + "endMs": 854 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 471, + "endMs": 645 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 4, + "startMs": 318, + "headersMs": 480, + "endMs": 495 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 318, + "headersMs": 483, + "endMs": 486 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 319, + "headersMs": 657, + "endMs": 824 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 319, + "headersMs": 674, + "endMs": 697 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 496, + "headersMs": 678, + "endMs": 680 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 487, + "headersMs": 703, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 646, + "headersMs": 802, + "endMs": 807 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 680, + "headersMs": 838, + "endMs": 843 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 698, + "headersMs": 853, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 733, + "headersMs": 887, + "endMs": 891 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 807, + "headersMs": 968, + "endMs": 977 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 826, + "headersMs": 979, + "endMs": 981 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 843, + "headersMs": 997, + "endMs": 998 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 855, + "headersMs": 1009, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 859, + "headersMs": 1024, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 891, + "headersMs": 1051, + "endMs": 1067 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 978, + "headersMs": 1133, + "endMs": 1137 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 982, + "headersMs": 1140, + "endMs": 1153 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 999, + "headersMs": 1158, + "endMs": 1167 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1017, + "headersMs": 1176, + "endMs": 1193 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1048, + "headersMs": 1203, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1068, + "headersMs": 1224, + "endMs": 1235 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1138, + "headersMs": 1293, + "endMs": 1300 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1154, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1168, + "headersMs": 1325, + "endMs": 1334 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1194, + "headersMs": 1359, + "endMs": 1385 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1210, + "headersMs": 1365, + "endMs": 1368 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1236, + "headersMs": 1389, + "endMs": 1393 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1301, + "headersMs": 1462, + "endMs": 1477 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1312, + "headersMs": 1473, + "endMs": 1489 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1335, + "headersMs": 1489, + "endMs": 1492 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1369, + "headersMs": 1525, + "endMs": 1529 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1386, + "headersMs": 1544, + "endMs": 1555 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1393, + "headersMs": 1555, + "endMs": 1574 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1478, + "headersMs": 1634, + "endMs": 1637 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1489, + "headersMs": 1643, + "endMs": 1648 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1493, + "headersMs": 1645, + "endMs": 1647 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1530, + "headersMs": 1684, + "endMs": 1688 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1556, + "headersMs": 1709, + "endMs": 1714 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1575, + "headersMs": 1734, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 44, + "startMs": 1638, + "headersMs": 1805, + "endMs": 1828 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 45, + "startMs": 1648, + "headersMs": 1880, + "endMs": 1977 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 46, + "startMs": 1649, + "headersMs": 1892, + "endMs": 1915 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 47, + "startMs": 1689, + "headersMs": 2427, + "endMs": 3023 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 48, + "startMs": 1715, + "headersMs": 2448, + "endMs": 2469 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1748, + "headersMs": 2452, + "endMs": 2456 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3063, + "headersMs": 3217, + "endMs": 3219 + }, + { + "url": "http://127.0.0.1:4913/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3079, + "headersMs": 3230, + "endMs": 3232 + }, + { + "url": "http://127.0.0.1:4913/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3080, + "headersMs": 3237, + "endMs": 3239 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 53, + "startMs": 3086, + "headersMs": 3268, + "endMs": 3313 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3242, + "headersMs": 3396, + "endMs": 3398 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3320, + "headersMs": 3474, + "endMs": 3483 + }, + { + "url": "http://127.0.0.1:4913/api/manifest", + "status": 200, + "bytes": 3738, + "index": 56, + "startMs": 3489, + "headersMs": 3658, + "endMs": 3676 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3702, + "headersMs": 3854, + "endMs": 4446 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3702, + "headersMs": 3854, + "endMs": 3864 + }, + { + "url": "http://127.0.0.1:4913/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3868 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3866 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3868 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3866, + "headersMs": 4019, + "endMs": 4022 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3868, + "headersMs": 4020, + "endMs": 4023 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3868, + "headersMs": 4020, + "endMs": 4025 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3870, + "headersMs": 4020, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3870, + "headersMs": 4020, + "endMs": 4031 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4024, + "headersMs": 4178, + "endMs": 4182 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4025, + "headersMs": 4178, + "endMs": 4190 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4026, + "headersMs": 4178, + "endMs": 4185 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4032, + "headersMs": 4184, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4040, + "headersMs": 4191, + "endMs": 4344 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4183, + "headersMs": 4336, + "endMs": 4719 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4187, + "headersMs": 4337, + "endMs": 4435 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4191, + "headersMs": 4343, + "endMs": 4517 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4197, + "headersMs": 4349, + "endMs": 4408 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4347, + "headersMs": 4499, + "endMs": 4656 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4410, + "headersMs": 4563, + "endMs": 4566 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4437, + "headersMs": 4589, + "endMs": 4597 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4451, + "headersMs": 4601, + "endMs": 4616 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4519, + "headersMs": 4671, + "endMs": 4679 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4568, + "headersMs": 4721, + "endMs": 4745 + }, + { + "url": "http://127.0.0.1:4913/index.html?v=340ad0883d", + "status": 200, + "bytes": 14032, + "index": 83, + "startMs": 4599, + "headersMs": 4750, + "endMs": 4820 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4619, + "headersMs": 4773, + "endMs": 4775 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4658, + "headersMs": 4811, + "endMs": 4826 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4681, + "headersMs": 4833, + "endMs": 4839 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4721, + "headersMs": 4873, + "endMs": 4884 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4747, + "headersMs": 4899, + "endMs": 4915 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4777, + "headersMs": 4928, + "endMs": 4932 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4823, + "headersMs": 4974, + "endMs": 4978 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4828, + "headersMs": 4978, + "endMs": 4983 + }, + { + "url": "http://127.0.0.1:4913/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4841, + "headersMs": 5005, + "endMs": 5026 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4886, + "headersMs": 5036, + "endMs": 5059 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4917, + "headersMs": 5069, + "endMs": 5073 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4935, + "headersMs": 5086, + "endMs": 5090 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4980, + "headersMs": 5132, + "endMs": 5162 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 4986, + "headersMs": 5136, + "endMs": 5139 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5028, + "headersMs": 5179, + "endMs": 5183 + }, + { + "url": "http://127.0.0.1:4913/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5062, + "headersMs": 5216, + "endMs": 5221 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5074, + "headersMs": 5226, + "endMs": 5230 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5092, + "headersMs": 5244, + "endMs": 5248 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5141, + "headersMs": 5292, + "endMs": 5314 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5165, + "headersMs": 5315, + "endMs": 5321 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5185, + "headersMs": 5337, + "endMs": 5360 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5223, + "headersMs": 5374, + "endMs": 5380 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5232, + "headersMs": 5382, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5250, + "headersMs": 5401, + "endMs": 5411 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5316, + "headersMs": 5470, + "endMs": 5486 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5322, + "headersMs": 5473, + "endMs": 5495 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5362, + "headersMs": 5513, + "endMs": 5681 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5383, + "headersMs": 5533, + "endMs": 5559 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5400, + "headersMs": 5553, + "endMs": 5574 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5413, + "headersMs": 5563, + "endMs": 5659 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5488, + "headersMs": 5642, + "endMs": 5644 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 115, + "startMs": 5690, + "headersMs": 5841, + "endMs": 5886 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5889, + "headersMs": 6040, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:4913/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6717, + "headersMs": 6872, + "endMs": 6879 + }, + { + "url": "http://127.0.0.1:4913/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6717, + "headersMs": 6873, + "endMs": 6876 + }, + { + "url": "http://127.0.0.1:4913/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6717, + "headersMs": 6880, + "endMs": 6891 + }, + { + "url": "http://127.0.0.1:4913/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6717, + "headersMs": 6882, + "endMs": 6883 + }, + { + "url": "http://127.0.0.1:4913/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6717, + "headersMs": 6894, + "endMs": 6914 + }, + { + "url": "http://127.0.0.1:4913/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6717, + "headersMs": 6897, + "endMs": 6904 + }, + { + "url": "http://127.0.0.1:4913/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6879, + "headersMs": 7034, + "endMs": 7041 + }, + { + "url": "http://127.0.0.1:4913/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6881, + "headersMs": 7039, + "endMs": 7046 + }, + { + "url": "http://127.0.0.1:4913/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6885, + "headersMs": 7041, + "endMs": 7047 + }, + { + "url": "http://127.0.0.1:4913/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6893, + "headersMs": 7047, + "endMs": 7055 + }, + { + "url": "http://127.0.0.1:4913/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6906, + "headersMs": 7069, + "endMs": 7093 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6916, + "headersMs": 7069, + "endMs": 7178 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7043, + "headersMs": 7195, + "endMs": 7331 + }, + { + "url": "http://127.0.0.1:4913/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7048, + "headersMs": 7207, + "endMs": 7224 + }, + { + "url": "http://127.0.0.1:4913/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7048, + "headersMs": 7210, + "endMs": 7215 + }, + { + "url": "http://127.0.0.1:4913/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7057, + "headersMs": 7212, + "endMs": 7216 + }, + { + "url": "http://127.0.0.1:4913/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7095, + "headersMs": 7250, + "endMs": 7252 + }, + { + "url": "http://127.0.0.1:4913/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7180, + "headersMs": 7335, + "endMs": 7341 + }, + { + "url": "http://127.0.0.1:4913/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7219, + "headersMs": 7377, + "endMs": 7390 + }, + { + "url": "http://127.0.0.1:4913/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7219, + "headersMs": 7383, + "endMs": 7392 + }, + { + "url": "http://127.0.0.1:4913/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7226, + "headersMs": 7395, + "endMs": 7417 + }, + { + "url": "http://127.0.0.1:4913/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7254, + "headersMs": 7409, + "endMs": 7413 + }, + { + "url": "http://127.0.0.1:4913/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7334, + "headersMs": 7489, + "endMs": 7497 + }, + { + "url": "http://127.0.0.1:4913/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7343, + "headersMs": 7502, + "endMs": 7516 + }, + { + "url": "http://127.0.0.1:4913/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7392, + "headersMs": 7549, + "endMs": 7556 + }, + { + "url": "http://127.0.0.1:4913/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7394, + "headersMs": 7551, + "endMs": 7556 + }, + { + "url": "http://127.0.0.1:4913/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7415, + "headersMs": 7568, + "endMs": 7580 + }, + { + "url": "http://127.0.0.1:4913/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7419, + "headersMs": 7583, + "endMs": 7604 + }, + { + "url": "http://127.0.0.1:4913/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7500, + "headersMs": 7660, + "endMs": 7677 + }, + { + "url": "http://127.0.0.1:4913/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7518, + "headersMs": 7698, + "endMs": 7743 + }, + { + "url": "http://127.0.0.1:4913/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7558, + "headersMs": 7718, + "endMs": 7732 + }, + { + "url": "http://127.0.0.1:4913/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7558, + "headersMs": 7731, + "endMs": 7753 + }, + { + "url": "http://127.0.0.1:4913/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7582, + "headersMs": 7743, + "endMs": 7755 + }, + { + "url": "http://127.0.0.1:4913/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7606, + "headersMs": 7765, + "endMs": 7779 + }, + { + "url": "http://127.0.0.1:4913/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7679, + "headersMs": 7869, + "endMs": 7908 + }, + { + "url": "http://127.0.0.1:4913/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7734, + "headersMs": 7912, + "endMs": 7940 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7746, + "headersMs": 7920, + "endMs": 7928 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7755, + "headersMs": 7926, + "endMs": 7932 + }, + { + "url": "http://127.0.0.1:4913/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7757, + "headersMs": 7958, + "endMs": 7988 + }, + { + "url": "http://127.0.0.1:4913/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7783, + "headersMs": 8151, + "endMs": 8376 + }, + { + "url": "http://127.0.0.1:4913/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7911, + "headersMs": 8160, + "endMs": 8173 + }, + { + "url": "http://127.0.0.1:4913/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7930, + "headersMs": 8164, + "endMs": 8171 + }, + { + "url": "http://127.0.0.1:4913/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7934, + "headersMs": 8186, + "endMs": 8222 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 313, + "responseStart": 483, + "end": 484, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 313, + "responseStart": 492, + "end": 492, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 313, + "responseStart": 677, + "end": 677, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 313, + "responseStart": 694, + "end": 695, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 313, + "responseStart": 729, + "end": 729, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 313, + "responseStart": 821, + "end": 822, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "bytes": 983, + "start": 314, + "responseStart": 804, + "end": 804, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 314, + "responseStart": 840, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 314, + "responseStart": 856, + "end": 856, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 314, + "responseStart": 888, + "end": 888, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 314, + "responseStart": 975, + "end": 975, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 314, + "responseStart": 979, + "end": 979, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 314, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 315, + "responseStart": 1013, + "end": 1014, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 315, + "responseStart": 1044, + "end": 1044, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 315, + "responseStart": 1064, + "end": 1065, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 315, + "responseStart": 1134, + "end": 1134, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 315, + "responseStart": 1150, + "end": 1150, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 315, + "responseStart": 1164, + "end": 1164, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 315, + "responseStart": 1190, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 316, + "responseStart": 1207, + "end": 1207, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 316, + "responseStart": 1232, + "end": 1233, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 316, + "responseStart": 1297, + "end": 1298, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 316, + "responseStart": 1308, + "end": 1309, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 316, + "responseStart": 1332, + "end": 1332, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 316, + "responseStart": 1365, + "end": 1366, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 316, + "responseStart": 1383, + "end": 1383, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 316, + "responseStart": 1390, + "end": 1390, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 316, + "responseStart": 1474, + "end": 1474, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 317, + "responseStart": 1486, + "end": 1486, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 317, + "responseStart": 1489, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 317, + "responseStart": 1526, + "end": 1527, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 317, + "responseStart": 1552, + "end": 1552, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 317, + "responseStart": 1571, + "end": 1572, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 317, + "responseStart": 1635, + "end": 1635, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 317, + "responseStart": 1644, + "end": 1645, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 317, + "responseStart": 1645, + "end": 1645, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 318, + "responseStart": 1685, + "end": 1685, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 318, + "responseStart": 1711, + "end": 1711, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 318, + "responseStart": 1744, + "end": 1745, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 318, + "responseStart": 1826, + "end": 1826, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 318, + "responseStart": 1912, + "end": 1912, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 318, + "responseStart": 1974, + "end": 1975, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "bytes": 118521, + "start": 318, + "responseStart": 2753, + "end": 3021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 496, + "responseStart": 2466, + "end": 2467, + "initiator": "link" + } + ], + "waterfalls": [ + { + "fcp": 2505, + "requests": [ + { + "url": "http://127.0.0.1:4913/?v=benchmedia01", + "status": 200, + "bytes": 14032, + "index": 1, + "startMs": 18, + "headersMs": 235, + "endMs": 309 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 316, + "headersMs": 470, + "endMs": 854 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 471, + "endMs": 645 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 4, + "startMs": 318, + "headersMs": 480, + "endMs": 495 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 5, + "startMs": 318, + "headersMs": 483, + "endMs": 486 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 6, + "startMs": 319, + "headersMs": 657, + "endMs": 824 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 7, + "startMs": 319, + "headersMs": 674, + "endMs": 697 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 9, + "startMs": 496, + "headersMs": 678, + "endMs": 680 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 8, + "startMs": 487, + "headersMs": 703, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 10, + "startMs": 646, + "headersMs": 802, + "endMs": 807 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 11, + "startMs": 680, + "headersMs": 838, + "endMs": 843 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 12, + "startMs": 698, + "headersMs": 853, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 13, + "startMs": 733, + "headersMs": 887, + "endMs": 891 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 14, + "startMs": 807, + "headersMs": 968, + "endMs": 977 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 15, + "startMs": 826, + "headersMs": 979, + "endMs": 981 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 16, + "startMs": 843, + "headersMs": 997, + "endMs": 998 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 17, + "startMs": 855, + "headersMs": 1009, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 18, + "startMs": 859, + "headersMs": 1024, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 19, + "startMs": 891, + "headersMs": 1051, + "endMs": 1067 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 20, + "startMs": 978, + "headersMs": 1133, + "endMs": 1137 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 21, + "startMs": 982, + "headersMs": 1140, + "endMs": 1153 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 22, + "startMs": 999, + "headersMs": 1158, + "endMs": 1167 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 23, + "startMs": 1017, + "headersMs": 1176, + "endMs": 1193 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 24, + "startMs": 1048, + "headersMs": 1203, + "endMs": 1210 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 25, + "startMs": 1068, + "headersMs": 1224, + "endMs": 1235 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 26, + "startMs": 1138, + "headersMs": 1293, + "endMs": 1300 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 27, + "startMs": 1154, + "headersMs": 1307, + "endMs": 1311 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 28, + "startMs": 1168, + "headersMs": 1325, + "endMs": 1334 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 29, + "startMs": 1194, + "headersMs": 1359, + "endMs": 1385 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 30, + "startMs": 1210, + "headersMs": 1365, + "endMs": 1368 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 31, + "startMs": 1236, + "headersMs": 1389, + "endMs": 1393 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 32, + "startMs": 1301, + "headersMs": 1462, + "endMs": 1477 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 33, + "startMs": 1312, + "headersMs": 1473, + "endMs": 1489 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 34, + "startMs": 1335, + "headersMs": 1489, + "endMs": 1492 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 35, + "startMs": 1369, + "headersMs": 1525, + "endMs": 1529 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 36, + "startMs": 1386, + "headersMs": 1544, + "endMs": 1555 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 37, + "startMs": 1393, + "headersMs": 1555, + "endMs": 1574 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 38, + "startMs": 1478, + "headersMs": 1634, + "endMs": 1637 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 39, + "startMs": 1489, + "headersMs": 1643, + "endMs": 1648 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 40, + "startMs": 1493, + "headersMs": 1645, + "endMs": 1647 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 41, + "startMs": 1530, + "headersMs": 1684, + "endMs": 1688 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 42, + "startMs": 1556, + "headersMs": 1709, + "endMs": 1714 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 43, + "startMs": 1575, + "headersMs": 1734, + "endMs": 1747 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 44, + "startMs": 1638, + "headersMs": 1805, + "endMs": 1828 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 45, + "startMs": 1648, + "headersMs": 1880, + "endMs": 1977 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 46, + "startMs": 1649, + "headersMs": 1892, + "endMs": 1915 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 47, + "startMs": 1689, + "headersMs": 2427, + "endMs": 3023 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 48, + "startMs": 1715, + "headersMs": 2448, + "endMs": 2469 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1748, + "headersMs": 2452, + "endMs": 2456 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3063, + "headersMs": 3217, + "endMs": 3219 + }, + { + "url": "http://127.0.0.1:4913/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3079, + "headersMs": 3230, + "endMs": 3232 + }, + { + "url": "http://127.0.0.1:4913/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3080, + "headersMs": 3237, + "endMs": 3239 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 53, + "startMs": 3086, + "headersMs": 3268, + "endMs": 3313 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3242, + "headersMs": 3396, + "endMs": 3398 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3320, + "headersMs": 3474, + "endMs": 3483 + }, + { + "url": "http://127.0.0.1:4913/api/manifest", + "status": 200, + "bytes": 3738, + "index": 56, + "startMs": 3489, + "headersMs": 3658, + "endMs": 3676 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3702, + "headersMs": 3854, + "endMs": 4446 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3702, + "headersMs": 3854, + "endMs": 3864 + }, + { + "url": "http://127.0.0.1:4913/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3868 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3866 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3702, + "headersMs": 3862, + "endMs": 3868 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3866, + "headersMs": 4019, + "endMs": 4022 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3868, + "headersMs": 4020, + "endMs": 4023 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3868, + "headersMs": 4020, + "endMs": 4025 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3870, + "headersMs": 4020, + "endMs": 4038 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3870, + "headersMs": 4020, + "endMs": 4031 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4024, + "headersMs": 4178, + "endMs": 4182 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4025, + "headersMs": 4178, + "endMs": 4190 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4026, + "headersMs": 4178, + "endMs": 4185 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4032, + "headersMs": 4184, + "endMs": 4196 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4040, + "headersMs": 4191, + "endMs": 4344 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4183, + "headersMs": 4336, + "endMs": 4719 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4187, + "headersMs": 4337, + "endMs": 4435 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4191, + "headersMs": 4343, + "endMs": 4517 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4197, + "headersMs": 4349, + "endMs": 4408 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4347, + "headersMs": 4499, + "endMs": 4656 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4410, + "headersMs": 4563, + "endMs": 4566 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4437, + "headersMs": 4589, + "endMs": 4597 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4451, + "headersMs": 4601, + "endMs": 4616 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4519, + "headersMs": 4671, + "endMs": 4679 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4568, + "headersMs": 4721, + "endMs": 4745 + }, + { + "url": "http://127.0.0.1:4913/index.html?v=340ad0883d", + "status": 200, + "bytes": 14032, + "index": 83, + "startMs": 4599, + "headersMs": 4750, + "endMs": 4820 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4619, + "headersMs": 4773, + "endMs": 4775 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4658, + "headersMs": 4811, + "endMs": 4826 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4681, + "headersMs": 4833, + "endMs": 4839 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4721, + "headersMs": 4873, + "endMs": 4884 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4747, + "headersMs": 4899, + "endMs": 4915 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4777, + "headersMs": 4928, + "endMs": 4932 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4823, + "headersMs": 4974, + "endMs": 4978 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4828, + "headersMs": 4978, + "endMs": 4983 + }, + { + "url": "http://127.0.0.1:4913/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4841, + "headersMs": 5005, + "endMs": 5026 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4886, + "headersMs": 5036, + "endMs": 5059 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4917, + "headersMs": 5069, + "endMs": 5073 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4935, + "headersMs": 5086, + "endMs": 5090 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4980, + "headersMs": 5132, + "endMs": 5162 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 4986, + "headersMs": 5136, + "endMs": 5139 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5028, + "headersMs": 5179, + "endMs": 5183 + }, + { + "url": "http://127.0.0.1:4913/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5062, + "headersMs": 5216, + "endMs": 5221 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5074, + "headersMs": 5226, + "endMs": 5230 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5092, + "headersMs": 5244, + "endMs": 5248 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5141, + "headersMs": 5292, + "endMs": 5314 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5165, + "headersMs": 5315, + "endMs": 5321 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5185, + "headersMs": 5337, + "endMs": 5360 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5223, + "headersMs": 5374, + "endMs": 5380 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5232, + "headersMs": 5382, + "endMs": 5398 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5250, + "headersMs": 5401, + "endMs": 5411 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5316, + "headersMs": 5470, + "endMs": 5486 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5322, + "headersMs": 5473, + "endMs": 5495 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5362, + "headersMs": 5513, + "endMs": 5681 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5383, + "headersMs": 5533, + "endMs": 5559 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5400, + "headersMs": 5553, + "endMs": 5574 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5413, + "headersMs": 5563, + "endMs": 5659 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5488, + "headersMs": 5642, + "endMs": 5644 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 115, + "startMs": 5690, + "headersMs": 5841, + "endMs": 5886 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5889, + "headersMs": 6040, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:4913/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6717, + "headersMs": 6872, + "endMs": 6879 + }, + { + "url": "http://127.0.0.1:4913/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6717, + "headersMs": 6873, + "endMs": 6876 + }, + { + "url": "http://127.0.0.1:4913/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6717, + "headersMs": 6880, + "endMs": 6891 + }, + { + "url": "http://127.0.0.1:4913/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6717, + "headersMs": 6882, + "endMs": 6883 + }, + { + "url": "http://127.0.0.1:4913/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6717, + "headersMs": 6894, + "endMs": 6914 + }, + { + "url": "http://127.0.0.1:4913/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6717, + "headersMs": 6897, + "endMs": 6904 + }, + { + "url": "http://127.0.0.1:4913/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6879, + "headersMs": 7034, + "endMs": 7041 + }, + { + "url": "http://127.0.0.1:4913/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6881, + "headersMs": 7039, + "endMs": 7046 + }, + { + "url": "http://127.0.0.1:4913/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6885, + "headersMs": 7041, + "endMs": 7047 + }, + { + "url": "http://127.0.0.1:4913/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6893, + "headersMs": 7047, + "endMs": 7055 + }, + { + "url": "http://127.0.0.1:4913/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6906, + "headersMs": 7069, + "endMs": 7093 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6916, + "headersMs": 7069, + "endMs": 7178 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7043, + "headersMs": 7195, + "endMs": 7331 + }, + { + "url": "http://127.0.0.1:4913/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7048, + "headersMs": 7207, + "endMs": 7224 + }, + { + "url": "http://127.0.0.1:4913/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7048, + "headersMs": 7210, + "endMs": 7215 + }, + { + "url": "http://127.0.0.1:4913/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7057, + "headersMs": 7212, + "endMs": 7216 + }, + { + "url": "http://127.0.0.1:4913/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7095, + "headersMs": 7250, + "endMs": 7252 + }, + { + "url": "http://127.0.0.1:4913/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7180, + "headersMs": 7335, + "endMs": 7341 + }, + { + "url": "http://127.0.0.1:4913/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7219, + "headersMs": 7377, + "endMs": 7390 + }, + { + "url": "http://127.0.0.1:4913/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7219, + "headersMs": 7383, + "endMs": 7392 + }, + { + "url": "http://127.0.0.1:4913/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7226, + "headersMs": 7395, + "endMs": 7417 + }, + { + "url": "http://127.0.0.1:4913/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7254, + "headersMs": 7409, + "endMs": 7413 + }, + { + "url": "http://127.0.0.1:4913/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7334, + "headersMs": 7489, + "endMs": 7497 + }, + { + "url": "http://127.0.0.1:4913/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7343, + "headersMs": 7502, + "endMs": 7516 + }, + { + "url": "http://127.0.0.1:4913/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7392, + "headersMs": 7549, + "endMs": 7556 + }, + { + "url": "http://127.0.0.1:4913/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7394, + "headersMs": 7551, + "endMs": 7556 + }, + { + "url": "http://127.0.0.1:4913/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7415, + "headersMs": 7568, + "endMs": 7580 + }, + { + "url": "http://127.0.0.1:4913/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7419, + "headersMs": 7583, + "endMs": 7604 + }, + { + "url": "http://127.0.0.1:4913/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7500, + "headersMs": 7660, + "endMs": 7677 + }, + { + "url": "http://127.0.0.1:4913/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7518, + "headersMs": 7698, + "endMs": 7743 + }, + { + "url": "http://127.0.0.1:4913/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7558, + "headersMs": 7718, + "endMs": 7732 + }, + { + "url": "http://127.0.0.1:4913/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7558, + "headersMs": 7731, + "endMs": 7753 + }, + { + "url": "http://127.0.0.1:4913/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7582, + "headersMs": 7743, + "endMs": 7755 + }, + { + "url": "http://127.0.0.1:4913/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7606, + "headersMs": 7765, + "endMs": 7779 + }, + { + "url": "http://127.0.0.1:4913/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7679, + "headersMs": 7869, + "endMs": 7908 + }, + { + "url": "http://127.0.0.1:4913/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7734, + "headersMs": 7912, + "endMs": 7940 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7746, + "headersMs": 7920, + "endMs": 7928 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7755, + "headersMs": 7926, + "endMs": 7932 + }, + { + "url": "http://127.0.0.1:4913/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7757, + "headersMs": 7958, + "endMs": 7988 + }, + { + "url": "http://127.0.0.1:4913/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7783, + "headersMs": 8151, + "endMs": 8376 + }, + { + "url": "http://127.0.0.1:4913/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7911, + "headersMs": 8160, + "endMs": 8173 + }, + { + "url": "http://127.0.0.1:4913/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7930, + "headersMs": 8164, + "endMs": 8171 + }, + { + "url": "http://127.0.0.1:4913/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7934, + "headersMs": 8186, + "endMs": 8222 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 313, + "responseStart": 483, + "end": 484, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 313, + "responseStart": 492, + "end": 492, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 313, + "responseStart": 677, + "end": 677, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 313, + "responseStart": 694, + "end": 695, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 313, + "responseStart": 729, + "end": 729, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 313, + "responseStart": 821, + "end": 822, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "bytes": 983, + "start": 314, + "responseStart": 804, + "end": 804, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 314, + "responseStart": 840, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 314, + "responseStart": 856, + "end": 856, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 314, + "responseStart": 888, + "end": 888, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 314, + "responseStart": 975, + "end": 975, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 314, + "responseStart": 979, + "end": 979, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 314, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 315, + "responseStart": 1013, + "end": 1014, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 315, + "responseStart": 1044, + "end": 1044, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 315, + "responseStart": 1064, + "end": 1065, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 315, + "responseStart": 1134, + "end": 1134, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 315, + "responseStart": 1150, + "end": 1150, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 315, + "responseStart": 1164, + "end": 1164, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 315, + "responseStart": 1190, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 316, + "responseStart": 1207, + "end": 1207, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 316, + "responseStart": 1232, + "end": 1233, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 316, + "responseStart": 1297, + "end": 1298, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 316, + "responseStart": 1308, + "end": 1309, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 316, + "responseStart": 1332, + "end": 1332, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 316, + "responseStart": 1365, + "end": 1366, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 316, + "responseStart": 1383, + "end": 1383, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 316, + "responseStart": 1390, + "end": 1390, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 316, + "responseStart": 1474, + "end": 1474, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 317, + "responseStart": 1486, + "end": 1486, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 317, + "responseStart": 1489, + "end": 1490, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 317, + "responseStart": 1526, + "end": 1527, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 317, + "responseStart": 1552, + "end": 1552, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 317, + "responseStart": 1571, + "end": 1572, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 317, + "responseStart": 1635, + "end": 1635, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 317, + "responseStart": 1644, + "end": 1645, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 317, + "responseStart": 1645, + "end": 1645, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 318, + "responseStart": 1685, + "end": 1685, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 318, + "responseStart": 1711, + "end": 1711, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 318, + "responseStart": 1744, + "end": 1745, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 318, + "responseStart": 1826, + "end": 1826, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 318, + "responseStart": 1912, + "end": 1912, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 318, + "responseStart": 1974, + "end": 1975, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "bytes": 118521, + "start": 318, + "responseStart": 2753, + "end": 3021, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 496, + "responseStart": 2466, + "end": 2467, + "initiator": "link" + } + ] + }, + { + "fcp": 1745, + "requests": [ + { + "url": "http://127.0.0.1:4913/?v=benchmedia01", + "status": 200, + "bytes": 14032, + "index": 160, + "startMs": 18, + "headersMs": 174, + "endMs": 246 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 161, + "startMs": 253, + "headersMs": 405, + "endMs": 789 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 162, + "startMs": 253, + "headersMs": 406, + "endMs": 580 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 163, + "startMs": 254, + "headersMs": 406, + "endMs": 422 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 164, + "startMs": 254, + "headersMs": 406, + "endMs": 408 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 165, + "startMs": 254, + "headersMs": 407, + "endMs": 573 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 166, + "startMs": 254, + "headersMs": 407, + "endMs": 429 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 167, + "startMs": 409, + "headersMs": 561, + "endMs": 591 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 168, + "startMs": 423, + "headersMs": 575, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 169, + "startMs": 430, + "headersMs": 581, + "endMs": 585 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 170, + "startMs": 575, + "headersMs": 729, + "endMs": 735 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 171, + "startMs": 577, + "headersMs": 729, + "endMs": 735 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 172, + "startMs": 580, + "headersMs": 732, + "endMs": 735 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 173, + "startMs": 586, + "headersMs": 737, + "endMs": 745 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 174, + "startMs": 592, + "headersMs": 742, + "endMs": 745 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 175, + "startMs": 736, + "headersMs": 887, + "endMs": 890 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 176, + "startMs": 737, + "headersMs": 888, + "endMs": 894 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 177, + "startMs": 737, + "headersMs": 888, + "endMs": 910 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 178, + "startMs": 745, + "headersMs": 896, + "endMs": 910 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 179, + "startMs": 746, + "headersMs": 896, + "endMs": 900 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 180, + "startMs": 789, + "headersMs": 942, + "endMs": 955 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 181, + "startMs": 891, + "headersMs": 1043, + "endMs": 1052 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 182, + "startMs": 894, + "headersMs": 1046, + "endMs": 1061 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 183, + "startMs": 900, + "headersMs": 1052, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 184, + "startMs": 911, + "headersMs": 1062, + "endMs": 1072 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 185, + "startMs": 911, + "headersMs": 1062, + "endMs": 1070 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 186, + "startMs": 956, + "headersMs": 1111, + "endMs": 1115 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 187, + "startMs": 1053, + "headersMs": 1205, + "endMs": 1215 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 188, + "startMs": 1060, + "headersMs": 1211, + "endMs": 1237 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 189, + "startMs": 1062, + "headersMs": 1213, + "endMs": 1217 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 190, + "startMs": 1070, + "headersMs": 1224, + "endMs": 1228 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 191, + "startMs": 1073, + "headersMs": 1224, + "endMs": 1238 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 192, + "startMs": 1116, + "headersMs": 1268, + "endMs": 1284 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 193, + "startMs": 1215, + "headersMs": 1366, + "endMs": 1370 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 194, + "startMs": 1217, + "headersMs": 1368, + "endMs": 1373 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 195, + "startMs": 1228, + "headersMs": 1379, + "endMs": 1390 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 196, + "startMs": 1237, + "headersMs": 1388, + "endMs": 1406 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 197, + "startMs": 1239, + "headersMs": 1389, + "endMs": 1394 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 198, + "startMs": 1286, + "headersMs": 1438, + "endMs": 1444 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 199, + "startMs": 1370, + "headersMs": 1522, + "endMs": 1524 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 200, + "startMs": 1374, + "headersMs": 1524, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 201, + "startMs": 1391, + "headersMs": 1541, + "endMs": 1545 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 202, + "startMs": 1394, + "headersMs": 1545, + "endMs": 1559 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 203, + "startMs": 1407, + "headersMs": 1559, + "endMs": 1582 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 204, + "startMs": 1444, + "headersMs": 1596, + "endMs": 1692 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 205, + "startMs": 1525, + "headersMs": 1678, + "endMs": 1700 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 206, + "startMs": 1528, + "headersMs": 1679, + "endMs": 2275 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 207, + "startMs": 1546, + "headersMs": 1697, + "endMs": 1718 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 208, + "startMs": 1559, + "headersMs": 1710, + "endMs": 1714 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 209, + "startMs": 2315, + "headersMs": 2467, + "endMs": 2469 + }, + { + "url": "http://127.0.0.1:4913/api/version", + "status": 200, + "bytes": 62, + "index": 210, + "startMs": 2331, + "headersMs": 2483, + "endMs": 2484 + }, + { + "url": "http://127.0.0.1:4913/api/user/sync", + "status": 200, + "bytes": 11, + "index": 211, + "startMs": 2332, + "headersMs": 2484, + "endMs": 2486 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 212, + "startMs": 2336, + "headersMs": 2487, + "endMs": 2532 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 213, + "startMs": 2490, + "headersMs": 2645, + "endMs": 2647 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 214, + "startMs": 2540, + "headersMs": 2691, + "endMs": 2701 + }, + { + "url": "http://127.0.0.1:4913/api/manifest", + "status": 200, + "bytes": 3738, + "index": 215, + "startMs": 2705, + "headersMs": 2857, + "endMs": 2876 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 216, + "startMs": 2899, + "headersMs": 3051, + "endMs": 3645 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 217, + "startMs": 2900, + "headersMs": 3051, + "endMs": 3061 + }, + { + "url": "http://127.0.0.1:4913/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 218, + "startMs": 2900, + "headersMs": 3052, + "endMs": 3057 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 219, + "startMs": 2900, + "headersMs": 3052, + "endMs": 3056 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 220, + "startMs": 2900, + "headersMs": 3052, + "endMs": 3054 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 221, + "startMs": 2900, + "headersMs": 3052, + "endMs": 3058 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 222, + "startMs": 3056, + "headersMs": 3208, + "endMs": 3212 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 223, + "startMs": 3057, + "headersMs": 3208, + "endMs": 3212 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 224, + "startMs": 3059, + "headersMs": 3212, + "endMs": 3217 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 225, + "startMs": 3060, + "headersMs": 3213, + "endMs": 3230 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 226, + "startMs": 3063, + "headersMs": 3213, + "endMs": 3222 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 227, + "startMs": 3214, + "headersMs": 3366, + "endMs": 3371 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 228, + "startMs": 3214, + "headersMs": 3366, + "endMs": 3378 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 229, + "startMs": 3218, + "headersMs": 3369, + "endMs": 3374 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 230, + "startMs": 3224, + "headersMs": 3374, + "endMs": 3387 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 231, + "startMs": 3232, + "headersMs": 3383, + "endMs": 3537 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 232, + "startMs": 3373, + "headersMs": 3524, + "endMs": 3908 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 233, + "startMs": 3376, + "headersMs": 3525, + "endMs": 3623 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 234, + "startMs": 3381, + "headersMs": 3531, + "endMs": 3705 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 235, + "startMs": 3388, + "headersMs": 3542, + "endMs": 3602 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 236, + "startMs": 3540, + "headersMs": 3693, + "endMs": 3850 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 237, + "startMs": 3604, + "headersMs": 3756, + "endMs": 3758 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 238, + "startMs": 3625, + "headersMs": 3777, + "endMs": 3786 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 239, + "startMs": 3650, + "headersMs": 3801, + "endMs": 3816 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 240, + "startMs": 3707, + "headersMs": 3859, + "endMs": 3867 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 241, + "startMs": 3760, + "headersMs": 3911, + "endMs": 3935 + }, + { + "url": "http://127.0.0.1:4913/index.html?v=340ad0883d", + "status": 200, + "bytes": 14032, + "index": 242, + "startMs": 3788, + "headersMs": 3939, + "endMs": 4010 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 243, + "startMs": 3819, + "headersMs": 3971, + "endMs": 3972 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 244, + "startMs": 3852, + "headersMs": 4003, + "endMs": 4018 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 245, + "startMs": 3869, + "headersMs": 4020, + "endMs": 4027 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 246, + "startMs": 3910, + "headersMs": 4061, + "endMs": 4072 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 247, + "startMs": 3937, + "headersMs": 4088, + "endMs": 4104 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 248, + "startMs": 3974, + "headersMs": 4126, + "endMs": 4130 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 249, + "startMs": 4013, + "headersMs": 4165, + "endMs": 4169 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 250, + "startMs": 4020, + "headersMs": 4171, + "endMs": 4175 + }, + { + "url": "http://127.0.0.1:4913/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 251, + "startMs": 4030, + "headersMs": 4180, + "endMs": 4201 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 252, + "startMs": 4074, + "headersMs": 4227, + "endMs": 4249 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 253, + "startMs": 4108, + "headersMs": 4258, + "endMs": 4262 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 254, + "startMs": 4131, + "headersMs": 4283, + "endMs": 4287 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 255, + "startMs": 4171, + "headersMs": 4323, + "endMs": 4354 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 256, + "startMs": 4177, + "headersMs": 4329, + "endMs": 4330 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 257, + "startMs": 4203, + "headersMs": 4354, + "endMs": 4358 + }, + { + "url": "http://127.0.0.1:4913/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 258, + "startMs": 4251, + "headersMs": 4404, + "endMs": 4407 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 259, + "startMs": 4263, + "headersMs": 4414, + "endMs": 4418 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 260, + "startMs": 4289, + "headersMs": 4441, + "endMs": 4445 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 261, + "startMs": 4332, + "headersMs": 4484, + "endMs": 4506 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 262, + "startMs": 4356, + "headersMs": 4507, + "endMs": 4512 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 263, + "startMs": 4359, + "headersMs": 4510, + "endMs": 4533 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 264, + "startMs": 4409, + "headersMs": 4561, + "endMs": 4567 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 265, + "startMs": 4420, + "headersMs": 4571, + "endMs": 4586 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 266, + "startMs": 4447, + "headersMs": 4599, + "endMs": 4607 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 267, + "startMs": 4509, + "headersMs": 4662, + "endMs": 4679 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 268, + "startMs": 4514, + "headersMs": 4664, + "endMs": 4686 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 269, + "startMs": 4535, + "headersMs": 4687, + "endMs": 4855 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 270, + "startMs": 4569, + "headersMs": 4720, + "endMs": 4744 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 271, + "startMs": 4588, + "headersMs": 4739, + "endMs": 4760 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 272, + "startMs": 4609, + "headersMs": 4761, + "endMs": 4857 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 273, + "startMs": 4681, + "headersMs": 4833, + "endMs": 4836 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 274, + "startMs": 4864, + "headersMs": 5016, + "endMs": 5061 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 275, + "startMs": 5063, + "headersMs": 5216, + "endMs": 5225 + }, + { + "url": "http://127.0.0.1:4913/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 276, + "startMs": 5891, + "headersMs": 6044, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:4913/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 277, + "startMs": 5892, + "headersMs": 6044, + "endMs": 6046 + }, + { + "url": "http://127.0.0.1:4913/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 278, + "startMs": 5892, + "headersMs": 6044, + "endMs": 6055 + }, + { + "url": "http://127.0.0.1:4913/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 279, + "startMs": 5892, + "headersMs": 6044, + "endMs": 6046 + }, + { + "url": "http://127.0.0.1:4913/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 280, + "startMs": 5892, + "headersMs": 6044, + "endMs": 6065 + }, + { + "url": "http://127.0.0.1:4913/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 281, + "startMs": 5892, + "headersMs": 6044, + "endMs": 6050 + }, + { + "url": "http://127.0.0.1:4913/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 282, + "startMs": 6048, + "headersMs": 6200, + "endMs": 6207 + }, + { + "url": "http://127.0.0.1:4913/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 283, + "startMs": 6048, + "headersMs": 6200, + "endMs": 6207 + }, + { + "url": "http://127.0.0.1:4913/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 284, + "startMs": 6052, + "headersMs": 6203, + "endMs": 6209 + }, + { + "url": "http://127.0.0.1:4913/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 285, + "startMs": 6052, + "headersMs": 6203, + "endMs": 6210 + }, + { + "url": "http://127.0.0.1:4913/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 286, + "startMs": 6056, + "headersMs": 6207, + "endMs": 6231 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 287, + "startMs": 6068, + "headersMs": 6219, + "endMs": 6328 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 288, + "startMs": 6209, + "headersMs": 6361, + "endMs": 6497 + }, + { + "url": "http://127.0.0.1:4913/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 289, + "startMs": 6209, + "headersMs": 6361, + "endMs": 6378 + }, + { + "url": "http://127.0.0.1:4913/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 290, + "startMs": 6210, + "headersMs": 6361, + "endMs": 6366 + }, + { + "url": "http://127.0.0.1:4913/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 291, + "startMs": 6212, + "headersMs": 6361, + "endMs": 6365 + }, + { + "url": "http://127.0.0.1:4913/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 292, + "startMs": 6233, + "headersMs": 6383, + "endMs": 6385 + }, + { + "url": "http://127.0.0.1:4913/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 293, + "startMs": 6330, + "headersMs": 6482, + "endMs": 6487 + }, + { + "url": "http://127.0.0.1:4913/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 294, + "startMs": 6368, + "headersMs": 6519, + "endMs": 6531 + }, + { + "url": "http://127.0.0.1:4913/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 295, + "startMs": 6369, + "headersMs": 6520, + "endMs": 6530 + }, + { + "url": "http://127.0.0.1:4913/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 296, + "startMs": 6380, + "headersMs": 6531, + "endMs": 6554 + }, + { + "url": "http://127.0.0.1:4913/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 297, + "startMs": 6387, + "headersMs": 6538, + "endMs": 6543 + }, + { + "url": "http://127.0.0.1:4913/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 298, + "startMs": 6490, + "headersMs": 6642, + "endMs": 6650 + }, + { + "url": "http://127.0.0.1:4913/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 299, + "startMs": 6499, + "headersMs": 6650, + "endMs": 6664 + }, + { + "url": "http://127.0.0.1:4913/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 300, + "startMs": 6533, + "headersMs": 6684, + "endMs": 6691 + }, + { + "url": "http://127.0.0.1:4913/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 301, + "startMs": 6533, + "headersMs": 6684, + "endMs": 6688 + }, + { + "url": "http://127.0.0.1:4913/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 302, + "startMs": 6545, + "headersMs": 6697, + "endMs": 6708 + }, + { + "url": "http://127.0.0.1:4913/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 303, + "startMs": 6555, + "headersMs": 6708, + "endMs": 6729 + }, + { + "url": "http://127.0.0.1:4913/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 304, + "startMs": 6652, + "headersMs": 6804, + "endMs": 6822 + }, + { + "url": "http://127.0.0.1:4913/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 305, + "startMs": 6666, + "headersMs": 6817, + "endMs": 6863 + }, + { + "url": "http://127.0.0.1:4913/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 306, + "startMs": 6690, + "headersMs": 6842, + "endMs": 6856 + }, + { + "url": "http://127.0.0.1:4913/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 307, + "startMs": 6693, + "headersMs": 6843, + "endMs": 6865 + }, + { + "url": "http://127.0.0.1:4913/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 308, + "startMs": 6710, + "headersMs": 6861, + "endMs": 6875 + }, + { + "url": "http://127.0.0.1:4913/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 309, + "startMs": 6731, + "headersMs": 6882, + "endMs": 6896 + }, + { + "url": "http://127.0.0.1:4913/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 310, + "startMs": 6824, + "headersMs": 6976, + "endMs": 7015 + }, + { + "url": "http://127.0.0.1:4913/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 311, + "startMs": 6858, + "headersMs": 7011, + "endMs": 7039 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 312, + "startMs": 6865, + "headersMs": 7015, + "endMs": 7023 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 313, + "startMs": 6867, + "headersMs": 7017, + "endMs": 7023 + }, + { + "url": "http://127.0.0.1:4913/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 314, + "startMs": 6877, + "headersMs": 7028, + "endMs": 7057 + }, + { + "url": "http://127.0.0.1:4913/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 315, + "startMs": 6898, + "headersMs": 7050, + "endMs": 7274 + }, + { + "url": "http://127.0.0.1:4913/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 316, + "startMs": 7018, + "headersMs": 7169, + "endMs": 7182 + }, + { + "url": "http://127.0.0.1:4913/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 317, + "startMs": 7025, + "headersMs": 7175, + "endMs": 7182 + }, + { + "url": "http://127.0.0.1:4913/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 318, + "startMs": 7025, + "headersMs": 7175, + "endMs": 7212 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 236, + "responseStart": 392, + "end": 392, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 236, + "responseStart": 405, + "end": 406, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 236, + "responseStart": 412, + "end": 413, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 236, + "responseStart": 557, + "end": 558, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 236, + "responseStart": 560, + "end": 561, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 236, + "responseStart": 574, + "end": 575, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "bytes": 983, + "start": 237, + "responseStart": 569, + "end": 569, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 237, + "responseStart": 718, + "end": 719, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 237, + "responseStart": 719, + "end": 719, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 237, + "responseStart": 719, + "end": 720, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 237, + "responseStart": 728, + "end": 728, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 237, + "responseStart": 729, + "end": 729, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 237, + "responseStart": 874, + "end": 874, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 238, + "responseStart": 877, + "end": 877, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 238, + "responseStart": 883, + "end": 883, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 238, + "responseStart": 893, + "end": 894, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 238, + "responseStart": 893, + "end": 894, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 238, + "responseStart": 938, + "end": 939, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 238, + "responseStart": 1035, + "end": 1036, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 238, + "responseStart": 1045, + "end": 1045, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 239, + "responseStart": 1043, + "end": 1043, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 239, + "responseStart": 1053, + "end": 1053, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 239, + "responseStart": 1056, + "end": 1056, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 239, + "responseStart": 1099, + "end": 1099, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 239, + "responseStart": 1198, + "end": 1198, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 239, + "responseStart": 1200, + "end": 1200, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 239, + "responseStart": 1211, + "end": 1211, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 239, + "responseStart": 1220, + "end": 1220, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 239, + "responseStart": 1222, + "end": 1222, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 240, + "responseStart": 1268, + "end": 1268, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 240, + "responseStart": 1353, + "end": 1353, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 240, + "responseStart": 1356, + "end": 1357, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 240, + "responseStart": 1373, + "end": 1374, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 240, + "responseStart": 1377, + "end": 1377, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 240, + "responseStart": 1390, + "end": 1390, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 240, + "responseStart": 1427, + "end": 1427, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 240, + "responseStart": 1508, + "end": 1508, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 241, + "responseStart": 1511, + "end": 1511, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 241, + "responseStart": 1529, + "end": 1529, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 241, + "responseStart": 1542, + "end": 1542, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 241, + "responseStart": 1565, + "end": 1566, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 241, + "responseStart": 1676, + "end": 1676, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 241, + "responseStart": 1683, + "end": 1684, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "bytes": 118521, + "start": 241, + "responseStart": 1980, + "end": 2259, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 409, + "responseStart": 1701, + "end": 1701, + "initiator": "link" + } + ] + }, + { + "fcp": 1735, + "requests": [ + { + "url": "http://127.0.0.1:4913/?v=benchmedia01", + "status": 200, + "bytes": 14032, + "index": 319, + "startMs": 17, + "headersMs": 170, + "endMs": 242 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 320, + "startMs": 251, + "headersMs": 403, + "endMs": 787 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 321, + "startMs": 252, + "headersMs": 404, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 322, + "startMs": 252, + "headersMs": 404, + "endMs": 419 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 323, + "startMs": 252, + "headersMs": 405, + "endMs": 407 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 324, + "startMs": 253, + "headersMs": 405, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 325, + "startMs": 253, + "headersMs": 405, + "endMs": 427 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 326, + "startMs": 408, + "headersMs": 559, + "endMs": 588 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 327, + "startMs": 420, + "headersMs": 573, + "endMs": 574 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 328, + "startMs": 428, + "headersMs": 579, + "endMs": 583 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 329, + "startMs": 574, + "headersMs": 725, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 330, + "startMs": 574, + "headersMs": 725, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 331, + "startMs": 577, + "headersMs": 728, + "endMs": 732 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 332, + "startMs": 584, + "headersMs": 734, + "endMs": 743 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 333, + "startMs": 589, + "headersMs": 740, + "endMs": 743 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 334, + "startMs": 732, + "headersMs": 883, + "endMs": 886 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 335, + "startMs": 732, + "headersMs": 883, + "endMs": 890 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 336, + "startMs": 732, + "headersMs": 883, + "endMs": 906 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 337, + "startMs": 743, + "headersMs": 894, + "endMs": 909 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 338, + "startMs": 744, + "headersMs": 894, + "endMs": 897 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 339, + "startMs": 788, + "headersMs": 939, + "endMs": 951 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 340, + "startMs": 886, + "headersMs": 1040, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 341, + "startMs": 891, + "headersMs": 1042, + "endMs": 1058 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 342, + "startMs": 898, + "headersMs": 1049, + "endMs": 1055 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 343, + "startMs": 907, + "headersMs": 1058, + "endMs": 1068 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 344, + "startMs": 910, + "headersMs": 1061, + "endMs": 1067 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 345, + "startMs": 952, + "headersMs": 1104, + "endMs": 1108 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 346, + "startMs": 1049, + "headersMs": 1201, + "endMs": 1211 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 347, + "startMs": 1056, + "headersMs": 1206, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 348, + "startMs": 1059, + "headersMs": 1209, + "endMs": 1212 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 349, + "startMs": 1068, + "headersMs": 1220, + "endMs": 1224 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 350, + "startMs": 1069, + "headersMs": 1220, + "endMs": 1235 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 351, + "startMs": 1109, + "headersMs": 1261, + "endMs": 1275 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 352, + "startMs": 1211, + "headersMs": 1362, + "endMs": 1366 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 353, + "startMs": 1213, + "headersMs": 1364, + "endMs": 1369 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 354, + "startMs": 1224, + "headersMs": 1375, + "endMs": 1385 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 355, + "startMs": 1231, + "headersMs": 1382, + "endMs": 1400 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 356, + "startMs": 1236, + "headersMs": 1386, + "endMs": 1390 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 357, + "startMs": 1276, + "headersMs": 1427, + "endMs": 1433 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 358, + "startMs": 1366, + "headersMs": 1518, + "endMs": 1520 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 359, + "startMs": 1369, + "headersMs": 1520, + "endMs": 1524 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 360, + "startMs": 1386, + "headersMs": 1536, + "endMs": 1541 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 361, + "startMs": 1391, + "headersMs": 1541, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 362, + "startMs": 1401, + "headersMs": 1553, + "endMs": 1576 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 363, + "startMs": 1433, + "headersMs": 1586, + "endMs": 1681 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 364, + "startMs": 1521, + "headersMs": 1673, + "endMs": 1694 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 365, + "startMs": 1524, + "headersMs": 1676, + "endMs": 2272 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 366, + "startMs": 1541, + "headersMs": 1692, + "endMs": 1713 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 367, + "startMs": 1554, + "headersMs": 1704, + "endMs": 1707 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 368, + "startMs": 2313, + "headersMs": 2465, + "endMs": 2466 + }, + { + "url": "http://127.0.0.1:4913/api/version", + "status": 200, + "bytes": 62, + "index": 369, + "startMs": 2329, + "headersMs": 2481, + "endMs": 2483 + }, + { + "url": "http://127.0.0.1:4913/api/user/sync", + "status": 200, + "bytes": 11, + "index": 370, + "startMs": 2330, + "headersMs": 2486, + "endMs": 2488 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 371, + "startMs": 2333, + "headersMs": 2486, + "endMs": 2531 + }, + { + "url": "http://127.0.0.1:4913/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 372, + "startMs": 2490, + "headersMs": 2644, + "endMs": 2645 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 373, + "startMs": 2538, + "headersMs": 2688, + "endMs": 2698 + }, + { + "url": "http://127.0.0.1:4913/api/manifest", + "status": 200, + "bytes": 3738, + "index": 374, + "startMs": 2703, + "headersMs": 2858, + "endMs": 2876 + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 375, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3645 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 376, + "startMs": 2900, + "headersMs": 3054, + "endMs": 3062 + }, + { + "url": "http://127.0.0.1:4913/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 377, + "startMs": 2900, + "headersMs": 3054, + "endMs": 3060 + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 378, + "startMs": 2900, + "headersMs": 3054, + "endMs": 3057 + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 379, + "startMs": 2901, + "headersMs": 3054, + "endMs": 3057 + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 380, + "startMs": 2901, + "headersMs": 3054, + "endMs": 3061 + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 381, + "startMs": 3059, + "headersMs": 3211, + "endMs": 3213 + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 382, + "startMs": 3060, + "headersMs": 3211, + "endMs": 3215 + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 383, + "startMs": 3061, + "headersMs": 3212, + "endMs": 3215 + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 384, + "startMs": 3062, + "headersMs": 3213, + "endMs": 3232 + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 385, + "startMs": 3064, + "headersMs": 3214, + "endMs": 3224 + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 386, + "startMs": 3215, + "headersMs": 3367, + "endMs": 3370 + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 387, + "startMs": 3217, + "headersMs": 3367, + "endMs": 3380 + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 388, + "startMs": 3217, + "headersMs": 3367, + "endMs": 3374 + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 389, + "startMs": 3226, + "headersMs": 3376, + "endMs": 3388 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 390, + "startMs": 3234, + "headersMs": 3386, + "endMs": 3540 + }, + { + "url": "http://127.0.0.1:4913/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 391, + "startMs": 3374, + "headersMs": 3526, + "endMs": 3910 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 392, + "startMs": 3376, + "headersMs": 3526, + "endMs": 3623 + }, + { + "url": "http://127.0.0.1:4913/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 393, + "startMs": 3383, + "headersMs": 3534, + "endMs": 3707 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 394, + "startMs": 3390, + "headersMs": 3541, + "endMs": 3600 + }, + { + "url": "http://127.0.0.1:4913/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 395, + "startMs": 3543, + "headersMs": 3694, + "endMs": 3852 + }, + { + "url": "http://127.0.0.1:4913/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 396, + "startMs": 3603, + "headersMs": 3754, + "endMs": 3756 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 397, + "startMs": 3625, + "headersMs": 3777, + "endMs": 3785 + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 398, + "startMs": 3651, + "headersMs": 3802, + "endMs": 3817 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 399, + "startMs": 3709, + "headersMs": 3860, + "endMs": 3869 + }, + { + "url": "http://127.0.0.1:4913/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 400, + "startMs": 3758, + "headersMs": 3911, + "endMs": 3934 + }, + { + "url": "http://127.0.0.1:4913/index.html?v=340ad0883d", + "status": 200, + "bytes": 14032, + "index": 401, + "startMs": 3788, + "headersMs": 3939, + "endMs": 4009 + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 402, + "startMs": 3819, + "headersMs": 3971, + "endMs": 3972 + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 403, + "startMs": 3854, + "headersMs": 4005, + "endMs": 4021 + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 404, + "startMs": 3870, + "headersMs": 4022, + "endMs": 4027 + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 405, + "startMs": 3912, + "headersMs": 4064, + "endMs": 4075 + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 406, + "startMs": 3938, + "headersMs": 4088, + "endMs": 4104 + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 407, + "startMs": 3974, + "headersMs": 4126, + "endMs": 4129 + }, + { + "url": "http://127.0.0.1:4913/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 408, + "startMs": 4012, + "headersMs": 4164, + "endMs": 4167 + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 409, + "startMs": 4023, + "headersMs": 4174, + "endMs": 4179 + }, + { + "url": "http://127.0.0.1:4913/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 410, + "startMs": 4028, + "headersMs": 4179, + "endMs": 4200 + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 411, + "startMs": 4077, + "headersMs": 4229, + "endMs": 4252 + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 4106, + "headersMs": 4257, + "endMs": 4260 + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 413, + "startMs": 4131, + "headersMs": 4283, + "endMs": 4288 + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 414, + "startMs": 4170, + "headersMs": 4321, + "endMs": 4351 + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 415, + "startMs": 4181, + "headersMs": 4332, + "endMs": 4335 + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 416, + "startMs": 4201, + "headersMs": 4352, + "endMs": 4356 + }, + { + "url": "http://127.0.0.1:4913/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 417, + "startMs": 4254, + "headersMs": 4406, + "endMs": 4411 + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 418, + "startMs": 4262, + "headersMs": 4413, + "endMs": 4417 + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 419, + "startMs": 4291, + "headersMs": 4442, + "endMs": 4447 + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 420, + "startMs": 4338, + "headersMs": 4491, + "endMs": 4513 + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 421, + "startMs": 4353, + "headersMs": 4504, + "endMs": 4508 + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 422, + "startMs": 4358, + "headersMs": 4509, + "endMs": 4532 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 423, + "startMs": 4413, + "headersMs": 4564, + "endMs": 4569 + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 424, + "startMs": 4418, + "headersMs": 4569, + "endMs": 4585 + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 425, + "startMs": 4449, + "headersMs": 4599, + "endMs": 4608 + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 426, + "startMs": 4510, + "headersMs": 4662, + "endMs": 4679 + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 427, + "startMs": 4515, + "headersMs": 4665, + "endMs": 4688 + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 428, + "startMs": 4535, + "headersMs": 4686, + "endMs": 4853 + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 429, + "startMs": 4571, + "headersMs": 4723, + "endMs": 4749 + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 430, + "startMs": 4587, + "headersMs": 4739, + "endMs": 4758 + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 431, + "startMs": 4610, + "headersMs": 4762, + "endMs": 4857 + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 432, + "startMs": 4682, + "headersMs": 4833, + "endMs": 4835 + }, + { + "url": "http://127.0.0.1:4913/sw.js", + "status": 200, + "bytes": 8989, + "index": 433, + "startMs": 4865, + "headersMs": 5018, + "endMs": 5064 + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 434, + "startMs": 5066, + "headersMs": 5218, + "endMs": 5227 + }, + { + "url": "http://127.0.0.1:4913/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 435, + "startMs": 5890, + "headersMs": 6042, + "endMs": 6049 + }, + { + "url": "http://127.0.0.1:4913/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 436, + "startMs": 5890, + "headersMs": 6042, + "endMs": 6044 + }, + { + "url": "http://127.0.0.1:4913/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 437, + "startMs": 5890, + "headersMs": 6042, + "endMs": 6052 + }, + { + "url": "http://127.0.0.1:4913/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 438, + "startMs": 5890, + "headersMs": 6042, + "endMs": 6044 + }, + { + "url": "http://127.0.0.1:4913/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 439, + "startMs": 5890, + "headersMs": 6043, + "endMs": 6064 + }, + { + "url": "http://127.0.0.1:4913/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 440, + "startMs": 5890, + "headersMs": 6043, + "endMs": 6049 + }, + { + "url": "http://127.0.0.1:4913/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 441, + "startMs": 6047, + "headersMs": 6198, + "endMs": 6204 + }, + { + "url": "http://127.0.0.1:4913/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 442, + "startMs": 6047, + "headersMs": 6199, + "endMs": 6206 + }, + { + "url": "http://127.0.0.1:4913/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 443, + "startMs": 6051, + "headersMs": 6202, + "endMs": 6207 + }, + { + "url": "http://127.0.0.1:4913/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 444, + "startMs": 6051, + "headersMs": 6202, + "endMs": 6210 + }, + { + "url": "http://127.0.0.1:4913/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 445, + "startMs": 6053, + "headersMs": 6204, + "endMs": 6227 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 446, + "startMs": 6066, + "headersMs": 6216, + "endMs": 6325 + }, + { + "url": "http://127.0.0.1:4913/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 447, + "startMs": 6207, + "headersMs": 6358, + "endMs": 6494 + }, + { + "url": "http://127.0.0.1:4913/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 448, + "startMs": 6208, + "headersMs": 6359, + "endMs": 6375 + }, + { + "url": "http://127.0.0.1:4913/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 449, + "startMs": 6208, + "headersMs": 6359, + "endMs": 6364 + }, + { + "url": "http://127.0.0.1:4913/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 450, + "startMs": 6211, + "headersMs": 6362, + "endMs": 6366 + }, + { + "url": "http://127.0.0.1:4913/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 451, + "startMs": 6229, + "headersMs": 6380, + "endMs": 6382 + }, + { + "url": "http://127.0.0.1:4913/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 452, + "startMs": 6327, + "headersMs": 6480, + "endMs": 6485 + }, + { + "url": "http://127.0.0.1:4913/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 453, + "startMs": 6366, + "headersMs": 6517, + "endMs": 6530 + }, + { + "url": "http://127.0.0.1:4913/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 454, + "startMs": 6367, + "headersMs": 6518, + "endMs": 6527 + }, + { + "url": "http://127.0.0.1:4913/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 455, + "startMs": 6377, + "headersMs": 6528, + "endMs": 6549 + }, + { + "url": "http://127.0.0.1:4913/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 456, + "startMs": 6383, + "headersMs": 6534, + "endMs": 6539 + }, + { + "url": "http://127.0.0.1:4913/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 457, + "startMs": 6487, + "headersMs": 6639, + "endMs": 6647 + }, + { + "url": "http://127.0.0.1:4913/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 458, + "startMs": 6497, + "headersMs": 6649, + "endMs": 6662 + }, + { + "url": "http://127.0.0.1:4913/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 459, + "startMs": 6530, + "headersMs": 6681, + "endMs": 6689 + }, + { + "url": "http://127.0.0.1:4913/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 460, + "startMs": 6531, + "headersMs": 6681, + "endMs": 6686 + }, + { + "url": "http://127.0.0.1:4913/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 461, + "startMs": 6541, + "headersMs": 6692, + "endMs": 6703 + }, + { + "url": "http://127.0.0.1:4913/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 462, + "startMs": 6551, + "headersMs": 6703, + "endMs": 6723 + }, + { + "url": "http://127.0.0.1:4913/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 463, + "startMs": 6649, + "headersMs": 6801, + "endMs": 6817 + }, + { + "url": "http://127.0.0.1:4913/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 464, + "startMs": 6663, + "headersMs": 6815, + "endMs": 6861 + }, + { + "url": "http://127.0.0.1:4913/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 465, + "startMs": 6687, + "headersMs": 6839, + "endMs": 6854 + }, + { + "url": "http://127.0.0.1:4913/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 466, + "startMs": 6690, + "headersMs": 6840, + "endMs": 6862 + }, + { + "url": "http://127.0.0.1:4913/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 467, + "startMs": 6705, + "headersMs": 6855, + "endMs": 6869 + }, + { + "url": "http://127.0.0.1:4913/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 468, + "startMs": 6725, + "headersMs": 6876, + "endMs": 6890 + }, + { + "url": "http://127.0.0.1:4913/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 469, + "startMs": 6819, + "headersMs": 6973, + "endMs": 7011 + }, + { + "url": "http://127.0.0.1:4913/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 470, + "startMs": 6856, + "headersMs": 7008, + "endMs": 7036 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 471, + "startMs": 6863, + "headersMs": 7013, + "endMs": 7022 + }, + { + "url": "http://127.0.0.1:4913/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 472, + "startMs": 6863, + "headersMs": 7013, + "endMs": 7019 + }, + { + "url": "http://127.0.0.1:4913/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 473, + "startMs": 6870, + "headersMs": 7021, + "endMs": 7050 + }, + { + "url": "http://127.0.0.1:4913/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 474, + "startMs": 6892, + "headersMs": 7042, + "endMs": 7267 + }, + { + "url": "http://127.0.0.1:4913/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 475, + "startMs": 7013, + "headersMs": 7166, + "endMs": 7178 + }, + { + "url": "http://127.0.0.1:4913/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 476, + "startMs": 7020, + "headersMs": 7171, + "endMs": 7177 + }, + { + "url": "http://127.0.0.1:4913/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 477, + "startMs": 7024, + "headersMs": 7174, + "endMs": 7212 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4913/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 234, + "responseStart": 390, + "end": 390, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 234, + "responseStart": 403, + "end": 403, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 235, + "responseStart": 411, + "end": 411, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 235, + "responseStart": 556, + "end": 556, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 235, + "responseStart": 557, + "end": 557, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/recommendations.css?v=055101368d", + "bytes": 983, + "start": 235, + "responseStart": 567, + "end": 567, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 235, + "responseStart": 571, + "end": 572, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 236, + "responseStart": 714, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 236, + "responseStart": 714, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 236, + "responseStart": 715, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 236, + "responseStart": 726, + "end": 726, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 236, + "responseStart": 726, + "end": 727, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 236, + "responseStart": 869, + "end": 869, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4913/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 237, + "responseStart": 873, + "end": 874, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 237, + "responseStart": 881, + "end": 881, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 237, + "responseStart": 889, + "end": 890, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 237, + "responseStart": 892, + "end": 893, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 237, + "responseStart": 935, + "end": 935, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 237, + "responseStart": 1031, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 237, + "responseStart": 1041, + "end": 1042, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 238, + "responseStart": 1038, + "end": 1039, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 238, + "responseStart": 1051, + "end": 1051, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 238, + "responseStart": 1051, + "end": 1052, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 238, + "responseStart": 1092, + "end": 1092, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 238, + "responseStart": 1194, + "end": 1194, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 238, + "responseStart": 1196, + "end": 1196, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 238, + "responseStart": 1207, + "end": 1207, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 238, + "responseStart": 1213, + "end": 1214, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 238, + "responseStart": 1218, + "end": 1219, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 238, + "responseStart": 1259, + "end": 1259, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 239, + "responseStart": 1349, + "end": 1349, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 239, + "responseStart": 1352, + "end": 1352, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 239, + "responseStart": 1368, + "end": 1369, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 239, + "responseStart": 1373, + "end": 1374, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 239, + "responseStart": 1383, + "end": 1383, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 239, + "responseStart": 1416, + "end": 1416, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 239, + "responseStart": 1504, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 239, + "responseStart": 1507, + "end": 1507, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 240, + "responseStart": 1524, + "end": 1524, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 240, + "responseStart": 1536, + "end": 1537, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 240, + "responseStart": 1560, + "end": 1560, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 240, + "responseStart": 1665, + "end": 1665, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 240, + "responseStart": 1678, + "end": 1678, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/app.js?v=f485286cbc", + "bytes": 118521, + "start": 240, + "responseStart": 1988, + "end": 2257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4913/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 408, + "responseStart": 1696, + "end": 1697, + "initiator": "link" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-preload-css.json b/perf/results/phase6-preload-css.json new file mode 100644 index 0000000..24815e8 --- /dev/null +++ b/perf/results/phase6-preload-css.json @@ -0,0 +1,7338 @@ +{ + "date": "2026-10-08T00:42:10.310Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-preload-css", + "sourceCommit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "frontendBuildTag": "e5d94327c887", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159, + 159, + 159 + ] + }, + "wireBytes": { + "median": 1097032, + "min": 1097032, + "max": 1097032, + "values": [ + 1097032, + 1097032, + 1097032 + ] + }, + "fcp": { + "median": 909, + "min": 904, + "max": 1034, + "values": [ + 1034, + 904, + 909 + ] + }, + "lcp": { + "median": 986, + "min": 983, + "max": 1110, + "values": [ + 1110, + 983, + 986 + ] + }, + "domContentLoaded": { + "median": 2332, + "min": 2330, + "max": 3122, + "values": [ + 3122, + 2332, + 2330 + ] + }, + "bootDone": { + "median": 2337, + "min": 2334, + "max": 3129, + "values": [ + 3129, + 2337, + 2334 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31527, + "min": 31508, + "max": 32322, + "values": [ + 32322, + 31508, + 31527 + ] + }, + "swInstallBytes": { + "median": 1097032, + "min": 1097032, + "max": 1097032, + "values": [ + 1097032, + 1097032, + 1097032 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28086, + "js": 556711, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5079, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5241/?v=benchmedia01", + "status": 200, + "bytes": 14043, + "index": 1, + "startMs": 18, + "headersMs": 234, + "endMs": 308 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 315, + "headersMs": 468, + "endMs": 851 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 469, + "endMs": 644 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 317, + "headersMs": 491, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 5, + "startMs": 318, + "headersMs": 500, + "endMs": 515 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 322, + "headersMs": 682, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 320, + "headersMs": 691, + "endMs": 693 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 516, + "headersMs": 733, + "endMs": 763 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 513, + "headersMs": 760, + "endMs": 783 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 645, + "headersMs": 797, + "endMs": 799 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 694, + "headersMs": 851, + "endMs": 855 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 764, + "headersMs": 922, + "endMs": 928 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 784, + "headersMs": 939, + "endMs": 946 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 800, + "headersMs": 954, + "endMs": 957 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 853, + "headersMs": 1011, + "endMs": 1020 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 853, + "headersMs": 1012, + "endMs": 1014 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 856, + "headersMs": 1014, + "endMs": 1017 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 929, + "headersMs": 1089, + "endMs": 1096 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 947, + "headersMs": 1114, + "endMs": 1137 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 958, + "headersMs": 1127, + "endMs": 1143 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 1015, + "headersMs": 1169, + "endMs": 1173 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1017, + "headersMs": 1176, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1020, + "headersMs": 1180, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1096, + "headersMs": 1259, + "endMs": 1277 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1138, + "headersMs": 1293, + "endMs": 1300 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1143, + "headersMs": 1300, + "endMs": 1312 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1174, + "headersMs": 1329, + "endMs": 1336 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1190, + "headersMs": 1344, + "endMs": 1348 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1190, + "headersMs": 1350, + "endMs": 1359 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1277, + "headersMs": 1445, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1300, + "headersMs": 1453, + "endMs": 1457 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1313, + "headersMs": 1468, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1337, + "headersMs": 1498, + "endMs": 1512 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1349, + "headersMs": 1512, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1360, + "headersMs": 1515, + "endMs": 1519 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1457, + "headersMs": 1614, + "endMs": 1619 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1471, + "headersMs": 1630, + "endMs": 1641 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1472, + "headersMs": 1641, + "endMs": 1660 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1513, + "headersMs": 1667, + "endMs": 1671 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1519, + "headersMs": 1675, + "endMs": 1680 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1528, + "headersMs": 1681, + "endMs": 1684 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1620, + "headersMs": 1775, + "endMs": 1778 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1642, + "headersMs": 1796, + "endMs": 1801 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1661, + "headersMs": 1819, + "endMs": 1833 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1672, + "headersMs": 1838, + "endMs": 1861 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1681, + "headersMs": 1918, + "endMs": 2015 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1685, + "headersMs": 1933, + "endMs": 1955 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1779, + "headersMs": 2482, + "endMs": 3076 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1801, + "headersMs": 2487, + "endMs": 2490 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3120, + "headersMs": 3274, + "endMs": 3277 + }, + { + "url": "http://127.0.0.1:5241/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3138, + "headersMs": 3290, + "endMs": 3291 + }, + { + "url": "http://127.0.0.1:5241/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3139, + "headersMs": 3296, + "endMs": 3297 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 53, + "startMs": 3146, + "headersMs": 3331, + "endMs": 3376 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3300, + "headersMs": 3452, + "endMs": 3454 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3384, + "headersMs": 3537, + "endMs": 3547 + }, + { + "url": "http://127.0.0.1:5241/api/manifest", + "status": 200, + "bytes": 3738, + "index": 56, + "startMs": 3552, + "headersMs": 3722, + "endMs": 3741 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3766, + "headersMs": 3920, + "endMs": 4512 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3767, + "headersMs": 3920, + "endMs": 3929 + }, + { + "url": "http://127.0.0.1:5241/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3767, + "headersMs": 3928, + "endMs": 3934 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3934 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3932 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3935 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3932, + "headersMs": 4083, + "endMs": 4086 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3934, + "headersMs": 4084, + "endMs": 4087 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3935, + "headersMs": 4086, + "endMs": 4090 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3935, + "headersMs": 4086, + "endMs": 4105 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3937, + "headersMs": 4088, + "endMs": 4098 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4088, + "headersMs": 4241, + "endMs": 4246 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4089, + "headersMs": 4241, + "endMs": 4253 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4092, + "headersMs": 4242, + "endMs": 4248 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4099, + "headersMs": 4251, + "endMs": 4264 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4107, + "headersMs": 4258, + "endMs": 4411 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4248, + "headersMs": 4401, + "endMs": 4785 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4251, + "headersMs": 4402, + "endMs": 4501 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4255, + "headersMs": 4405, + "endMs": 4579 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4265, + "headersMs": 4416, + "endMs": 4475 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4415, + "headersMs": 4567, + "endMs": 4725 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4477, + "headersMs": 4628, + "endMs": 4631 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4503, + "headersMs": 4656, + "endMs": 4664 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4516, + "headersMs": 4669, + "endMs": 4684 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4582, + "headersMs": 4734, + "endMs": 4743 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4633, + "headersMs": 4785, + "endMs": 4809 + }, + { + "url": "http://127.0.0.1:5241/index.html?v=1cd3a1c30d", + "status": 200, + "bytes": 14043, + "index": 83, + "startMs": 4666, + "headersMs": 4818, + "endMs": 4889 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4686, + "headersMs": 4838, + "endMs": 4839 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4728, + "headersMs": 4880, + "endMs": 4895 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4744, + "headersMs": 4896, + "endMs": 4902 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4787, + "headersMs": 4938, + "endMs": 4949 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4812, + "headersMs": 4964, + "endMs": 4980 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4841, + "headersMs": 4992, + "endMs": 4996 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4891, + "headersMs": 5043, + "endMs": 5047 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4899, + "headersMs": 5050, + "endMs": 5055 + }, + { + "url": "http://127.0.0.1:5241/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4905, + "headersMs": 5068, + "endMs": 5089 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4951, + "headersMs": 5104, + "endMs": 5127 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4983, + "headersMs": 5134, + "endMs": 5137 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4998, + "headersMs": 5150, + "endMs": 5154 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 5049, + "headersMs": 5202, + "endMs": 5232 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5057, + "headersMs": 5208, + "endMs": 5210 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5093, + "headersMs": 5245, + "endMs": 5248 + }, + { + "url": "http://127.0.0.1:5241/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5130, + "headersMs": 5284, + "endMs": 5288 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5138, + "headersMs": 5288, + "endMs": 5292 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5156, + "headersMs": 5308, + "endMs": 5312 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5212, + "headersMs": 5364, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5235, + "headersMs": 5386, + "endMs": 5392 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5251, + "headersMs": 5402, + "endMs": 5424 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5290, + "headersMs": 5442, + "endMs": 5447 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5293, + "headersMs": 5445, + "endMs": 5461 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5314, + "headersMs": 5465, + "endMs": 5473 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5388, + "headersMs": 5540, + "endMs": 5557 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5393, + "headersMs": 5543, + "endMs": 5565 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5426, + "headersMs": 5578, + "endMs": 5746 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5450, + "headersMs": 5601, + "endMs": 5627 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5463, + "headersMs": 5614, + "endMs": 5634 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5476, + "headersMs": 5628, + "endMs": 5724 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5560, + "headersMs": 5712, + "endMs": 5715 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 115, + "startMs": 5756, + "headersMs": 5907, + "endMs": 5952 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5954, + "headersMs": 6106, + "endMs": 6116 + }, + { + "url": "http://127.0.0.1:5241/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6788, + "headersMs": 6944, + "endMs": 6951 + }, + { + "url": "http://127.0.0.1:5241/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6788, + "headersMs": 6945, + "endMs": 6948 + }, + { + "url": "http://127.0.0.1:5241/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6788, + "headersMs": 6951, + "endMs": 6961 + }, + { + "url": "http://127.0.0.1:5241/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6788, + "headersMs": 6952, + "endMs": 6954 + }, + { + "url": "http://127.0.0.1:5241/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6788, + "headersMs": 6965, + "endMs": 6987 + }, + { + "url": "http://127.0.0.1:5241/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6788, + "headersMs": 6969, + "endMs": 6975 + }, + { + "url": "http://127.0.0.1:5241/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6950, + "headersMs": 7106, + "endMs": 7113 + }, + { + "url": "http://127.0.0.1:5241/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6953, + "headersMs": 7111, + "endMs": 7118 + }, + { + "url": "http://127.0.0.1:5241/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6955, + "headersMs": 7114, + "endMs": 7120 + }, + { + "url": "http://127.0.0.1:5241/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6963, + "headersMs": 7119, + "endMs": 7126 + }, + { + "url": "http://127.0.0.1:5241/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6978, + "headersMs": 7142, + "endMs": 7166 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6990, + "headersMs": 7142, + "endMs": 7251 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7116, + "headersMs": 7268, + "endMs": 7405 + }, + { + "url": "http://127.0.0.1:5241/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7120, + "headersMs": 7280, + "endMs": 7297 + }, + { + "url": "http://127.0.0.1:5241/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7121, + "headersMs": 7283, + "endMs": 7289 + }, + { + "url": "http://127.0.0.1:5241/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7128, + "headersMs": 7285, + "endMs": 7289 + }, + { + "url": "http://127.0.0.1:5241/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7168, + "headersMs": 7321, + "endMs": 7323 + }, + { + "url": "http://127.0.0.1:5241/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7254, + "headersMs": 7409, + "endMs": 7414 + }, + { + "url": "http://127.0.0.1:5241/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7290, + "headersMs": 7449, + "endMs": 7462 + }, + { + "url": "http://127.0.0.1:5241/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7291, + "headersMs": 7455, + "endMs": 7465 + }, + { + "url": "http://127.0.0.1:5241/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7299, + "headersMs": 7473, + "endMs": 7496 + }, + { + "url": "http://127.0.0.1:5241/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7325, + "headersMs": 7479, + "endMs": 7485 + }, + { + "url": "http://127.0.0.1:5241/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7407, + "headersMs": 7564, + "endMs": 7571 + }, + { + "url": "http://127.0.0.1:5241/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7416, + "headersMs": 7576, + "endMs": 7590 + }, + { + "url": "http://127.0.0.1:5241/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7465, + "headersMs": 7621, + "endMs": 7628 + }, + { + "url": "http://127.0.0.1:5241/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7467, + "headersMs": 7624, + "endMs": 7629 + }, + { + "url": "http://127.0.0.1:5241/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7487, + "headersMs": 7640, + "endMs": 7652 + }, + { + "url": "http://127.0.0.1:5241/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7498, + "headersMs": 7663, + "endMs": 7685 + }, + { + "url": "http://127.0.0.1:5241/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7573, + "headersMs": 7735, + "endMs": 7752 + }, + { + "url": "http://127.0.0.1:5241/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7592, + "headersMs": 7772, + "endMs": 7817 + }, + { + "url": "http://127.0.0.1:5241/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7631, + "headersMs": 7792, + "endMs": 7806 + }, + { + "url": "http://127.0.0.1:5241/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7631, + "headersMs": 7806, + "endMs": 7828 + }, + { + "url": "http://127.0.0.1:5241/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7654, + "headersMs": 7817, + "endMs": 7830 + }, + { + "url": "http://127.0.0.1:5241/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7688, + "headersMs": 7846, + "endMs": 7860 + }, + { + "url": "http://127.0.0.1:5241/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7755, + "headersMs": 7948, + "endMs": 7987 + }, + { + "url": "http://127.0.0.1:5241/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7809, + "headersMs": 7987, + "endMs": 8015 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7819, + "headersMs": 7996, + "endMs": 8005 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7830, + "headersMs": 8003, + "endMs": 8008 + }, + { + "url": "http://127.0.0.1:5241/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7832, + "headersMs": 8035, + "endMs": 8065 + }, + { + "url": "http://127.0.0.1:5241/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7863, + "headersMs": 8235, + "endMs": 8460 + }, + { + "url": "http://127.0.0.1:5241/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7991, + "headersMs": 8245, + "endMs": 8258 + }, + { + "url": "http://127.0.0.1:5241/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 8007, + "headersMs": 8249, + "endMs": 8255 + }, + { + "url": "http://127.0.0.1:5241/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 8010, + "headersMs": 8271, + "endMs": 8310 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 300, + "responseStart": 497, + "end": 497, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 300, + "responseStart": 500, + "end": 500, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 300, + "responseStart": 678, + "end": 679, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 748, + "end": 749, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 768, + "end": 768, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 301, + "responseStart": 784, + "end": 784, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 835, + "end": 837, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 840, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 301, + "responseStart": 913, + "end": 914, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 301, + "responseStart": 931, + "end": 931, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 942, + "end": 942, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 999, + "end": 1000, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 1002, + "end": 1002, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 1004, + "end": 1005, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 302, + "responseStart": 1080, + "end": 1081, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 302, + "responseStart": 1122, + "end": 1122, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1128, + "end": 1128, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1158, + "end": 1158, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1173, + "end": 1174, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 303, + "responseStart": 1174, + "end": 1174, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 303, + "responseStart": 1261, + "end": 1262, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 303, + "responseStart": 1284, + "end": 1285, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1297, + "end": 1297, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1321, + "end": 1321, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1333, + "end": 1333, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1344, + "end": 1344, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1441, + "end": 1442, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 304, + "responseStart": 1456, + "end": 1456, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1455, + "end": 1456, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 304, + "responseStart": 1497, + "end": 1498, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 305, + "responseStart": 1503, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 305, + "responseStart": 1512, + "end": 1513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 305, + "responseStart": 1603, + "end": 1604, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1626, + "end": 1626, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1645, + "end": 1646, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 305, + "responseStart": 1656, + "end": 1656, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 305, + "responseStart": 1665, + "end": 1666, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 305, + "responseStart": 1669, + "end": 1669, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 306, + "responseStart": 1763, + "end": 1763, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 306, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 306, + "responseStart": 1818, + "end": 1818, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 306, + "responseStart": 1846, + "end": 1846, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 306, + "responseStart": 1939, + "end": 1940, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 306, + "responseStart": 2000, + "end": 2000, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "bytes": 118521, + "start": 306, + "responseStart": 2736, + "end": 3062, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1034, + "requests": [ + { + "url": "http://127.0.0.1:5241/?v=benchmedia01", + "status": 200, + "bytes": 14043, + "index": 1, + "startMs": 18, + "headersMs": 234, + "endMs": 308 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 315, + "headersMs": 468, + "endMs": 851 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 469, + "endMs": 644 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 317, + "headersMs": 491, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 5, + "startMs": 318, + "headersMs": 500, + "endMs": 515 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 322, + "headersMs": 682, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 320, + "headersMs": 691, + "endMs": 693 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 516, + "headersMs": 733, + "endMs": 763 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 513, + "headersMs": 760, + "endMs": 783 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 645, + "headersMs": 797, + "endMs": 799 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 694, + "headersMs": 851, + "endMs": 855 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 764, + "headersMs": 922, + "endMs": 928 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 784, + "headersMs": 939, + "endMs": 946 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 800, + "headersMs": 954, + "endMs": 957 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 853, + "headersMs": 1011, + "endMs": 1020 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 853, + "headersMs": 1012, + "endMs": 1014 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 856, + "headersMs": 1014, + "endMs": 1017 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 929, + "headersMs": 1089, + "endMs": 1096 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 947, + "headersMs": 1114, + "endMs": 1137 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 958, + "headersMs": 1127, + "endMs": 1143 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 1015, + "headersMs": 1169, + "endMs": 1173 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1017, + "headersMs": 1176, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1020, + "headersMs": 1180, + "endMs": 1189 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1096, + "headersMs": 1259, + "endMs": 1277 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1138, + "headersMs": 1293, + "endMs": 1300 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1143, + "headersMs": 1300, + "endMs": 1312 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1174, + "headersMs": 1329, + "endMs": 1336 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1190, + "headersMs": 1344, + "endMs": 1348 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1190, + "headersMs": 1350, + "endMs": 1359 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1277, + "headersMs": 1445, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1300, + "headersMs": 1453, + "endMs": 1457 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1313, + "headersMs": 1468, + "endMs": 1471 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1337, + "headersMs": 1498, + "endMs": 1512 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1349, + "headersMs": 1512, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1360, + "headersMs": 1515, + "endMs": 1519 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1457, + "headersMs": 1614, + "endMs": 1619 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1471, + "headersMs": 1630, + "endMs": 1641 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1472, + "headersMs": 1641, + "endMs": 1660 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1513, + "headersMs": 1667, + "endMs": 1671 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1519, + "headersMs": 1675, + "endMs": 1680 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1528, + "headersMs": 1681, + "endMs": 1684 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1620, + "headersMs": 1775, + "endMs": 1778 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1642, + "headersMs": 1796, + "endMs": 1801 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1661, + "headersMs": 1819, + "endMs": 1833 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1672, + "headersMs": 1838, + "endMs": 1861 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1681, + "headersMs": 1918, + "endMs": 2015 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1685, + "headersMs": 1933, + "endMs": 1955 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1779, + "headersMs": 2482, + "endMs": 3076 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1801, + "headersMs": 2487, + "endMs": 2490 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3120, + "headersMs": 3274, + "endMs": 3277 + }, + { + "url": "http://127.0.0.1:5241/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3138, + "headersMs": 3290, + "endMs": 3291 + }, + { + "url": "http://127.0.0.1:5241/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3139, + "headersMs": 3296, + "endMs": 3297 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 53, + "startMs": 3146, + "headersMs": 3331, + "endMs": 3376 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3300, + "headersMs": 3452, + "endMs": 3454 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3384, + "headersMs": 3537, + "endMs": 3547 + }, + { + "url": "http://127.0.0.1:5241/api/manifest", + "status": 200, + "bytes": 3738, + "index": 56, + "startMs": 3552, + "headersMs": 3722, + "endMs": 3741 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3766, + "headersMs": 3920, + "endMs": 4512 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3767, + "headersMs": 3920, + "endMs": 3929 + }, + { + "url": "http://127.0.0.1:5241/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3767, + "headersMs": 3928, + "endMs": 3934 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3934 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3932 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3767, + "headersMs": 3929, + "endMs": 3935 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3932, + "headersMs": 4083, + "endMs": 4086 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3934, + "headersMs": 4084, + "endMs": 4087 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3935, + "headersMs": 4086, + "endMs": 4090 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3935, + "headersMs": 4086, + "endMs": 4105 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3937, + "headersMs": 4088, + "endMs": 4098 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4088, + "headersMs": 4241, + "endMs": 4246 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4089, + "headersMs": 4241, + "endMs": 4253 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4092, + "headersMs": 4242, + "endMs": 4248 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4099, + "headersMs": 4251, + "endMs": 4264 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4107, + "headersMs": 4258, + "endMs": 4411 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4248, + "headersMs": 4401, + "endMs": 4785 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4251, + "headersMs": 4402, + "endMs": 4501 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4255, + "headersMs": 4405, + "endMs": 4579 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4265, + "headersMs": 4416, + "endMs": 4475 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4415, + "headersMs": 4567, + "endMs": 4725 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4477, + "headersMs": 4628, + "endMs": 4631 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4503, + "headersMs": 4656, + "endMs": 4664 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4516, + "headersMs": 4669, + "endMs": 4684 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4582, + "headersMs": 4734, + "endMs": 4743 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4633, + "headersMs": 4785, + "endMs": 4809 + }, + { + "url": "http://127.0.0.1:5241/index.html?v=1cd3a1c30d", + "status": 200, + "bytes": 14043, + "index": 83, + "startMs": 4666, + "headersMs": 4818, + "endMs": 4889 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4686, + "headersMs": 4838, + "endMs": 4839 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4728, + "headersMs": 4880, + "endMs": 4895 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4744, + "headersMs": 4896, + "endMs": 4902 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4787, + "headersMs": 4938, + "endMs": 4949 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4812, + "headersMs": 4964, + "endMs": 4980 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4841, + "headersMs": 4992, + "endMs": 4996 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4891, + "headersMs": 5043, + "endMs": 5047 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4899, + "headersMs": 5050, + "endMs": 5055 + }, + { + "url": "http://127.0.0.1:5241/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4905, + "headersMs": 5068, + "endMs": 5089 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4951, + "headersMs": 5104, + "endMs": 5127 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4983, + "headersMs": 5134, + "endMs": 5137 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4998, + "headersMs": 5150, + "endMs": 5154 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 5049, + "headersMs": 5202, + "endMs": 5232 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5057, + "headersMs": 5208, + "endMs": 5210 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5093, + "headersMs": 5245, + "endMs": 5248 + }, + { + "url": "http://127.0.0.1:5241/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5130, + "headersMs": 5284, + "endMs": 5288 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5138, + "headersMs": 5288, + "endMs": 5292 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5156, + "headersMs": 5308, + "endMs": 5312 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5212, + "headersMs": 5364, + "endMs": 5386 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5235, + "headersMs": 5386, + "endMs": 5392 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5251, + "headersMs": 5402, + "endMs": 5424 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5290, + "headersMs": 5442, + "endMs": 5447 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5293, + "headersMs": 5445, + "endMs": 5461 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5314, + "headersMs": 5465, + "endMs": 5473 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5388, + "headersMs": 5540, + "endMs": 5557 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5393, + "headersMs": 5543, + "endMs": 5565 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5426, + "headersMs": 5578, + "endMs": 5746 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5450, + "headersMs": 5601, + "endMs": 5627 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5463, + "headersMs": 5614, + "endMs": 5634 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5476, + "headersMs": 5628, + "endMs": 5724 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5560, + "headersMs": 5712, + "endMs": 5715 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 115, + "startMs": 5756, + "headersMs": 5907, + "endMs": 5952 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5954, + "headersMs": 6106, + "endMs": 6116 + }, + { + "url": "http://127.0.0.1:5241/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 6788, + "headersMs": 6944, + "endMs": 6951 + }, + { + "url": "http://127.0.0.1:5241/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 6788, + "headersMs": 6945, + "endMs": 6948 + }, + { + "url": "http://127.0.0.1:5241/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 6788, + "headersMs": 6951, + "endMs": 6961 + }, + { + "url": "http://127.0.0.1:5241/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 6788, + "headersMs": 6952, + "endMs": 6954 + }, + { + "url": "http://127.0.0.1:5241/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 6788, + "headersMs": 6965, + "endMs": 6987 + }, + { + "url": "http://127.0.0.1:5241/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 6788, + "headersMs": 6969, + "endMs": 6975 + }, + { + "url": "http://127.0.0.1:5241/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6950, + "headersMs": 7106, + "endMs": 7113 + }, + { + "url": "http://127.0.0.1:5241/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6953, + "headersMs": 7111, + "endMs": 7118 + }, + { + "url": "http://127.0.0.1:5241/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6955, + "headersMs": 7114, + "endMs": 7120 + }, + { + "url": "http://127.0.0.1:5241/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6963, + "headersMs": 7119, + "endMs": 7126 + }, + { + "url": "http://127.0.0.1:5241/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6978, + "headersMs": 7142, + "endMs": 7166 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6990, + "headersMs": 7142, + "endMs": 7251 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 7116, + "headersMs": 7268, + "endMs": 7405 + }, + { + "url": "http://127.0.0.1:5241/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 7120, + "headersMs": 7280, + "endMs": 7297 + }, + { + "url": "http://127.0.0.1:5241/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 7121, + "headersMs": 7283, + "endMs": 7289 + }, + { + "url": "http://127.0.0.1:5241/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 7128, + "headersMs": 7285, + "endMs": 7289 + }, + { + "url": "http://127.0.0.1:5241/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 7168, + "headersMs": 7321, + "endMs": 7323 + }, + { + "url": "http://127.0.0.1:5241/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 7254, + "headersMs": 7409, + "endMs": 7414 + }, + { + "url": "http://127.0.0.1:5241/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 7290, + "headersMs": 7449, + "endMs": 7462 + }, + { + "url": "http://127.0.0.1:5241/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 7291, + "headersMs": 7455, + "endMs": 7465 + }, + { + "url": "http://127.0.0.1:5241/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 7299, + "headersMs": 7473, + "endMs": 7496 + }, + { + "url": "http://127.0.0.1:5241/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 7325, + "headersMs": 7479, + "endMs": 7485 + }, + { + "url": "http://127.0.0.1:5241/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 7407, + "headersMs": 7564, + "endMs": 7571 + }, + { + "url": "http://127.0.0.1:5241/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 7416, + "headersMs": 7576, + "endMs": 7590 + }, + { + "url": "http://127.0.0.1:5241/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 7465, + "headersMs": 7621, + "endMs": 7628 + }, + { + "url": "http://127.0.0.1:5241/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 7467, + "headersMs": 7624, + "endMs": 7629 + }, + { + "url": "http://127.0.0.1:5241/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 7487, + "headersMs": 7640, + "endMs": 7652 + }, + { + "url": "http://127.0.0.1:5241/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 7498, + "headersMs": 7663, + "endMs": 7685 + }, + { + "url": "http://127.0.0.1:5241/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 7573, + "headersMs": 7735, + "endMs": 7752 + }, + { + "url": "http://127.0.0.1:5241/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 7592, + "headersMs": 7772, + "endMs": 7817 + }, + { + "url": "http://127.0.0.1:5241/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 7631, + "headersMs": 7792, + "endMs": 7806 + }, + { + "url": "http://127.0.0.1:5241/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 7631, + "headersMs": 7806, + "endMs": 7828 + }, + { + "url": "http://127.0.0.1:5241/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 7654, + "headersMs": 7817, + "endMs": 7830 + }, + { + "url": "http://127.0.0.1:5241/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 7688, + "headersMs": 7846, + "endMs": 7860 + }, + { + "url": "http://127.0.0.1:5241/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 7755, + "headersMs": 7948, + "endMs": 7987 + }, + { + "url": "http://127.0.0.1:5241/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 7809, + "headersMs": 7987, + "endMs": 8015 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 7819, + "headersMs": 7996, + "endMs": 8005 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 7830, + "headersMs": 8003, + "endMs": 8008 + }, + { + "url": "http://127.0.0.1:5241/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 7832, + "headersMs": 8035, + "endMs": 8065 + }, + { + "url": "http://127.0.0.1:5241/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 7863, + "headersMs": 8235, + "endMs": 8460 + }, + { + "url": "http://127.0.0.1:5241/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7991, + "headersMs": 8245, + "endMs": 8258 + }, + { + "url": "http://127.0.0.1:5241/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 8007, + "headersMs": 8249, + "endMs": 8255 + }, + { + "url": "http://127.0.0.1:5241/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 8010, + "headersMs": 8271, + "endMs": 8310 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 300, + "responseStart": 497, + "end": 497, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 300, + "responseStart": 500, + "end": 500, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 300, + "responseStart": 678, + "end": 679, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 748, + "end": 749, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 768, + "end": 768, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 301, + "responseStart": 784, + "end": 784, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 835, + "end": 837, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 840, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 301, + "responseStart": 913, + "end": 914, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 301, + "responseStart": 931, + "end": 931, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 942, + "end": 942, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 999, + "end": 1000, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 1002, + "end": 1002, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 1004, + "end": 1005, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 302, + "responseStart": 1080, + "end": 1081, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 302, + "responseStart": 1122, + "end": 1122, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1128, + "end": 1128, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1158, + "end": 1158, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1173, + "end": 1174, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 303, + "responseStart": 1174, + "end": 1174, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 303, + "responseStart": 1261, + "end": 1262, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 303, + "responseStart": 1284, + "end": 1285, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1297, + "end": 1297, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1321, + "end": 1321, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1333, + "end": 1333, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1344, + "end": 1344, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1441, + "end": 1442, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 304, + "responseStart": 1456, + "end": 1456, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1455, + "end": 1456, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 304, + "responseStart": 1497, + "end": 1498, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 305, + "responseStart": 1503, + "end": 1504, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 305, + "responseStart": 1512, + "end": 1513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 305, + "responseStart": 1603, + "end": 1604, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1626, + "end": 1626, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1645, + "end": 1646, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 305, + "responseStart": 1656, + "end": 1656, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 305, + "responseStart": 1665, + "end": 1666, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 305, + "responseStart": 1669, + "end": 1669, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 306, + "responseStart": 1763, + "end": 1763, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 306, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 306, + "responseStart": 1818, + "end": 1818, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 306, + "responseStart": 1846, + "end": 1846, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 306, + "responseStart": 1939, + "end": 1940, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 306, + "responseStart": 2000, + "end": 2000, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "bytes": 118521, + "start": 306, + "responseStart": 2736, + "end": 3062, + "initiator": "script" + } + ] + }, + { + "fcp": 904, + "requests": [ + { + "url": "http://127.0.0.1:5241/?v=benchmedia01", + "status": 200, + "bytes": 14043, + "index": 160, + "startMs": 17, + "headersMs": 170, + "endMs": 242 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 161, + "startMs": 249, + "headersMs": 401, + "endMs": 785 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 162, + "startMs": 250, + "headersMs": 402, + "endMs": 576 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 163, + "startMs": 250, + "headersMs": 402, + "endMs": 423 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 164, + "startMs": 251, + "headersMs": 403, + "endMs": 418 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 165, + "startMs": 251, + "headersMs": 403, + "endMs": 405 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 166, + "startMs": 251, + "headersMs": 403, + "endMs": 571 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 167, + "startMs": 406, + "headersMs": 558, + "endMs": 580 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 168, + "startMs": 419, + "headersMs": 570, + "endMs": 600 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 169, + "startMs": 424, + "headersMs": 574, + "endMs": 576 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 170, + "startMs": 572, + "headersMs": 725, + "endMs": 730 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 171, + "startMs": 576, + "headersMs": 728, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 172, + "startMs": 577, + "headersMs": 728, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 173, + "startMs": 581, + "headersMs": 733, + "endMs": 736 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 174, + "startMs": 602, + "headersMs": 753, + "endMs": 762 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 175, + "startMs": 731, + "headersMs": 883, + "endMs": 886 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 176, + "startMs": 734, + "headersMs": 886, + "endMs": 888 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 177, + "startMs": 735, + "headersMs": 886, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 178, + "startMs": 736, + "headersMs": 889, + "endMs": 911 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 179, + "startMs": 763, + "headersMs": 914, + "endMs": 930 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 180, + "startMs": 786, + "headersMs": 937, + "endMs": 941 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 181, + "startMs": 887, + "headersMs": 1039, + "endMs": 1051 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 182, + "startMs": 889, + "headersMs": 1039, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 183, + "startMs": 893, + "headersMs": 1043, + "endMs": 1060 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 184, + "startMs": 912, + "headersMs": 1062, + "endMs": 1069 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 185, + "startMs": 931, + "headersMs": 1084, + "endMs": 1094 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 186, + "startMs": 942, + "headersMs": 1093, + "endMs": 1100 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 187, + "startMs": 1049, + "headersMs": 1201, + "endMs": 1205 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 188, + "startMs": 1052, + "headersMs": 1202, + "endMs": 1212 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 189, + "startMs": 1061, + "headersMs": 1213, + "endMs": 1238 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 190, + "startMs": 1071, + "headersMs": 1222, + "endMs": 1225 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 191, + "startMs": 1095, + "headersMs": 1246, + "endMs": 1249 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 192, + "startMs": 1100, + "headersMs": 1252, + "endMs": 1266 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 193, + "startMs": 1206, + "headersMs": 1359, + "endMs": 1375 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 194, + "startMs": 1213, + "headersMs": 1364, + "endMs": 1367 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 195, + "startMs": 1226, + "headersMs": 1378, + "endMs": 1382 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 196, + "startMs": 1239, + "headersMs": 1390, + "endMs": 1401 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 197, + "startMs": 1250, + "headersMs": 1401, + "endMs": 1419 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 198, + "startMs": 1267, + "headersMs": 1419, + "endMs": 1423 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 199, + "startMs": 1368, + "headersMs": 1522, + "endMs": 1527 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 200, + "startMs": 1375, + "headersMs": 1525, + "endMs": 1528 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 201, + "startMs": 1383, + "headersMs": 1533, + "endMs": 1537 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 202, + "startMs": 1401, + "headersMs": 1553, + "endMs": 1557 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 203, + "startMs": 1420, + "headersMs": 1571, + "endMs": 1584 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 204, + "startMs": 1423, + "headersMs": 1575, + "endMs": 1597 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 205, + "startMs": 1529, + "headersMs": 1683, + "endMs": 1780 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 206, + "startMs": 1529, + "headersMs": 1683, + "endMs": 1704 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 207, + "startMs": 1538, + "headersMs": 1689, + "endMs": 2292 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 208, + "startMs": 1558, + "headersMs": 1709, + "endMs": 1712 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 209, + "startMs": 2333, + "headersMs": 2485, + "endMs": 2486 + }, + { + "url": "http://127.0.0.1:5241/api/version", + "status": 200, + "bytes": 62, + "index": 210, + "startMs": 2349, + "headersMs": 2500, + "endMs": 2502 + }, + { + "url": "http://127.0.0.1:5241/api/user/sync", + "status": 200, + "bytes": 11, + "index": 211, + "startMs": 2350, + "headersMs": 2506, + "endMs": 2507 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 212, + "startMs": 2354, + "headersMs": 2506, + "endMs": 2550 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 213, + "startMs": 2509, + "headersMs": 2662, + "endMs": 2663 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 214, + "startMs": 2557, + "headersMs": 2708, + "endMs": 2718 + }, + { + "url": "http://127.0.0.1:5241/api/manifest", + "status": 200, + "bytes": 3738, + "index": 215, + "startMs": 2722, + "headersMs": 2877, + "endMs": 2897 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 216, + "startMs": 2921, + "headersMs": 3073, + "endMs": 3665 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 217, + "startMs": 2921, + "headersMs": 3073, + "endMs": 3082 + }, + { + "url": "http://127.0.0.1:5241/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 218, + "startMs": 2921, + "headersMs": 3073, + "endMs": 3080 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 219, + "startMs": 2921, + "headersMs": 3074, + "endMs": 3078 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 220, + "startMs": 2921, + "headersMs": 3074, + "endMs": 3077 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 221, + "startMs": 2921, + "headersMs": 3074, + "endMs": 3080 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 222, + "startMs": 3080, + "headersMs": 3236, + "endMs": 3238 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 223, + "startMs": 3080, + "headersMs": 3236, + "endMs": 3240 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 224, + "startMs": 3082, + "headersMs": 3237, + "endMs": 3240 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 225, + "startMs": 3082, + "headersMs": 3237, + "endMs": 3255 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 226, + "startMs": 3083, + "headersMs": 3237, + "endMs": 3247 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 227, + "startMs": 3241, + "headersMs": 3394, + "endMs": 3398 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 228, + "startMs": 3242, + "headersMs": 3394, + "endMs": 3406 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 229, + "startMs": 3242, + "headersMs": 3394, + "endMs": 3401 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 230, + "startMs": 3249, + "headersMs": 3400, + "endMs": 3413 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 231, + "startMs": 3257, + "headersMs": 3409, + "endMs": 3562 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 232, + "startMs": 3401, + "headersMs": 3553, + "endMs": 3936 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 233, + "startMs": 3403, + "headersMs": 3553, + "endMs": 3652 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 234, + "startMs": 3408, + "headersMs": 3559, + "endMs": 3733 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 235, + "startMs": 3414, + "headersMs": 3565, + "endMs": 3623 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 236, + "startMs": 3564, + "headersMs": 3716, + "endMs": 3873 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 237, + "startMs": 3626, + "headersMs": 3779, + "endMs": 3783 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 238, + "startMs": 3654, + "headersMs": 3806, + "endMs": 3815 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 239, + "startMs": 3672, + "headersMs": 3824, + "endMs": 3838 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 240, + "startMs": 3735, + "headersMs": 3886, + "endMs": 3895 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 241, + "startMs": 3785, + "headersMs": 3936, + "endMs": 3960 + }, + { + "url": "http://127.0.0.1:5241/index.html?v=1cd3a1c30d", + "status": 200, + "bytes": 14043, + "index": 242, + "startMs": 3818, + "headersMs": 3970, + "endMs": 4040 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 243, + "startMs": 3841, + "headersMs": 3993, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 244, + "startMs": 3876, + "headersMs": 4027, + "endMs": 4043 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 245, + "startMs": 3897, + "headersMs": 4048, + "endMs": 4054 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 246, + "startMs": 3938, + "headersMs": 4089, + "endMs": 4100 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 247, + "startMs": 3962, + "headersMs": 4113, + "endMs": 4129 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 248, + "startMs": 3996, + "headersMs": 4147, + "endMs": 4151 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 249, + "startMs": 4044, + "headersMs": 4196, + "endMs": 4200 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 250, + "startMs": 4045, + "headersMs": 4196, + "endMs": 4201 + }, + { + "url": "http://127.0.0.1:5241/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 251, + "startMs": 4056, + "headersMs": 4207, + "endMs": 4228 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 252, + "startMs": 4102, + "headersMs": 4253, + "endMs": 4276 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 253, + "startMs": 4131, + "headersMs": 4282, + "endMs": 4286 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 254, + "startMs": 4153, + "headersMs": 4304, + "endMs": 4308 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 255, + "startMs": 4202, + "headersMs": 4353, + "endMs": 4384 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 256, + "startMs": 4202, + "headersMs": 4354, + "endMs": 4356 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 257, + "startMs": 4230, + "headersMs": 4383, + "endMs": 4386 + }, + { + "url": "http://127.0.0.1:5241/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 258, + "startMs": 4279, + "headersMs": 4430, + "endMs": 4435 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 259, + "startMs": 4287, + "headersMs": 4438, + "endMs": 4442 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 260, + "startMs": 4310, + "headersMs": 4462, + "endMs": 4467 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 261, + "startMs": 4358, + "headersMs": 4509, + "endMs": 4531 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 262, + "startMs": 4387, + "headersMs": 4537, + "endMs": 4543 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 263, + "startMs": 4387, + "headersMs": 4538, + "endMs": 4560 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 264, + "startMs": 4438, + "headersMs": 4589, + "endMs": 4595 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 265, + "startMs": 4443, + "headersMs": 4595, + "endMs": 4611 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 266, + "startMs": 4469, + "headersMs": 4621, + "endMs": 4630 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 267, + "startMs": 4533, + "headersMs": 4686, + "endMs": 4702 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 268, + "startMs": 4545, + "headersMs": 4696, + "endMs": 4718 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 269, + "startMs": 4562, + "headersMs": 4712, + "endMs": 4879 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 270, + "startMs": 4597, + "headersMs": 4749, + "endMs": 4775 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 271, + "startMs": 4613, + "headersMs": 4764, + "endMs": 4784 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 272, + "startMs": 4632, + "headersMs": 4784, + "endMs": 4879 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 273, + "startMs": 4704, + "headersMs": 4855, + "endMs": 4858 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 274, + "startMs": 4889, + "headersMs": 5041, + "endMs": 5086 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 275, + "startMs": 5089, + "headersMs": 5243, + "endMs": 5253 + }, + { + "url": "http://127.0.0.1:5241/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 276, + "startMs": 5916, + "headersMs": 6068, + "endMs": 6077 + }, + { + "url": "http://127.0.0.1:5241/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 277, + "startMs": 5916, + "headersMs": 6069, + "endMs": 6072 + }, + { + "url": "http://127.0.0.1:5241/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 278, + "startMs": 5916, + "headersMs": 6069, + "endMs": 6080 + }, + { + "url": "http://127.0.0.1:5241/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 279, + "startMs": 5916, + "headersMs": 6069, + "endMs": 6070 + }, + { + "url": "http://127.0.0.1:5241/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 280, + "startMs": 5917, + "headersMs": 6069, + "endMs": 6091 + }, + { + "url": "http://127.0.0.1:5241/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 281, + "startMs": 5917, + "headersMs": 6069, + "endMs": 6075 + }, + { + "url": "http://127.0.0.1:5241/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 282, + "startMs": 6072, + "headersMs": 6223, + "endMs": 6229 + }, + { + "url": "http://127.0.0.1:5241/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 283, + "startMs": 6073, + "headersMs": 6223, + "endMs": 6231 + }, + { + "url": "http://127.0.0.1:5241/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 284, + "startMs": 6077, + "headersMs": 6227, + "endMs": 6232 + }, + { + "url": "http://127.0.0.1:5241/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 285, + "startMs": 6078, + "headersMs": 6229, + "endMs": 6236 + }, + { + "url": "http://127.0.0.1:5241/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 286, + "startMs": 6081, + "headersMs": 6231, + "endMs": 6255 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 287, + "startMs": 6093, + "headersMs": 6244, + "endMs": 6352 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 288, + "startMs": 6231, + "headersMs": 6382, + "endMs": 6519 + }, + { + "url": "http://127.0.0.1:5241/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 289, + "startMs": 6232, + "headersMs": 6383, + "endMs": 6400 + }, + { + "url": "http://127.0.0.1:5241/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 290, + "startMs": 6234, + "headersMs": 6384, + "endMs": 6391 + }, + { + "url": "http://127.0.0.1:5241/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 291, + "startMs": 6237, + "headersMs": 6387, + "endMs": 6391 + }, + { + "url": "http://127.0.0.1:5241/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 292, + "startMs": 6257, + "headersMs": 6408, + "endMs": 6410 + }, + { + "url": "http://127.0.0.1:5241/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 293, + "startMs": 6355, + "headersMs": 6508, + "endMs": 6514 + }, + { + "url": "http://127.0.0.1:5241/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 294, + "startMs": 6393, + "headersMs": 6544, + "endMs": 6558 + }, + { + "url": "http://127.0.0.1:5241/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 295, + "startMs": 6393, + "headersMs": 6545, + "endMs": 6555 + }, + { + "url": "http://127.0.0.1:5241/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 296, + "startMs": 6402, + "headersMs": 6554, + "endMs": 6576 + }, + { + "url": "http://127.0.0.1:5241/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 297, + "startMs": 6412, + "headersMs": 6563, + "endMs": 6568 + }, + { + "url": "http://127.0.0.1:5241/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 298, + "startMs": 6517, + "headersMs": 6668, + "endMs": 6676 + }, + { + "url": "http://127.0.0.1:5241/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 299, + "startMs": 6521, + "headersMs": 6671, + "endMs": 6686 + }, + { + "url": "http://127.0.0.1:5241/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 300, + "startMs": 6557, + "headersMs": 6709, + "endMs": 6716 + }, + { + "url": "http://127.0.0.1:5241/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 301, + "startMs": 6559, + "headersMs": 6709, + "endMs": 6713 + }, + { + "url": "http://127.0.0.1:5241/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 302, + "startMs": 6570, + "headersMs": 6721, + "endMs": 6733 + }, + { + "url": "http://127.0.0.1:5241/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 303, + "startMs": 6578, + "headersMs": 6729, + "endMs": 6749 + }, + { + "url": "http://127.0.0.1:5241/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 304, + "startMs": 6678, + "headersMs": 6832, + "endMs": 6849 + }, + { + "url": "http://127.0.0.1:5241/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 305, + "startMs": 6687, + "headersMs": 6838, + "endMs": 6883 + }, + { + "url": "http://127.0.0.1:5241/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 306, + "startMs": 6715, + "headersMs": 6866, + "endMs": 6882 + }, + { + "url": "http://127.0.0.1:5241/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 307, + "startMs": 6718, + "headersMs": 6868, + "endMs": 6889 + }, + { + "url": "http://127.0.0.1:5241/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 308, + "startMs": 6735, + "headersMs": 6887, + "endMs": 6900 + }, + { + "url": "http://127.0.0.1:5241/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 309, + "startMs": 6751, + "headersMs": 6901, + "endMs": 6915 + }, + { + "url": "http://127.0.0.1:5241/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 310, + "startMs": 6852, + "headersMs": 7003, + "endMs": 7042 + }, + { + "url": "http://127.0.0.1:5241/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 311, + "startMs": 6884, + "headersMs": 7035, + "endMs": 7063 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 312, + "startMs": 6885, + "headersMs": 7036, + "endMs": 7044 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 313, + "startMs": 6891, + "headersMs": 7042, + "endMs": 7047 + }, + { + "url": "http://127.0.0.1:5241/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 314, + "startMs": 6902, + "headersMs": 7055, + "endMs": 7084 + }, + { + "url": "http://127.0.0.1:5241/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 315, + "startMs": 6916, + "headersMs": 7068, + "endMs": 7295 + }, + { + "url": "http://127.0.0.1:5241/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 316, + "startMs": 7045, + "headersMs": 7197, + "endMs": 7209 + }, + { + "url": "http://127.0.0.1:5241/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 317, + "startMs": 7046, + "headersMs": 7197, + "endMs": 7204 + }, + { + "url": "http://127.0.0.1:5241/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 318, + "startMs": 7049, + "headersMs": 7199, + "endMs": 7236 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 233, + "responseStart": 389, + "end": 389, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 233, + "responseStart": 402, + "end": 402, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 233, + "responseStart": 407, + "end": 408, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 234, + "responseStart": 555, + "end": 556, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 234, + "responseStart": 560, + "end": 560, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 234, + "responseStart": 564, + "end": 564, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 234, + "responseStart": 584, + "end": 585, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "bytes": 983, + "start": 234, + "responseStart": 714, + "end": 714, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 234, + "responseStart": 718, + "end": 718, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 234, + "responseStart": 718, + "end": 718, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 234, + "responseStart": 720, + "end": 720, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 234, + "responseStart": 746, + "end": 746, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 234, + "responseStart": 870, + "end": 870, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 234, + "responseStart": 872, + "end": 872, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 235, + "responseStart": 876, + "end": 876, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 235, + "responseStart": 895, + "end": 896, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 236, + "responseStart": 914, + "end": 915, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 236, + "responseStart": 925, + "end": 925, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 236, + "responseStart": 1032, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 236, + "responseStart": 1035, + "end": 1036, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 236, + "responseStart": 1044, + "end": 1044, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 236, + "responseStart": 1053, + "end": 1054, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 236, + "responseStart": 1078, + "end": 1079, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 236, + "responseStart": 1084, + "end": 1084, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 237, + "responseStart": 1189, + "end": 1189, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 237, + "responseStart": 1196, + "end": 1196, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 237, + "responseStart": 1209, + "end": 1210, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 237, + "responseStart": 1222, + "end": 1223, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 237, + "responseStart": 1233, + "end": 1234, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 237, + "responseStart": 1250, + "end": 1251, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 237, + "responseStart": 1351, + "end": 1352, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 237, + "responseStart": 1359, + "end": 1359, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 238, + "responseStart": 1366, + "end": 1366, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 238, + "responseStart": 1385, + "end": 1385, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 238, + "responseStart": 1403, + "end": 1404, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 238, + "responseStart": 1407, + "end": 1407, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 238, + "responseStart": 1512, + "end": 1512, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 238, + "responseStart": 1512, + "end": 1513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 238, + "responseStart": 1521, + "end": 1521, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 238, + "responseStart": 1541, + "end": 1542, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 238, + "responseStart": 1567, + "end": 1568, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 238, + "responseStart": 1581, + "end": 1581, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 238, + "responseStart": 1688, + "end": 1689, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 238, + "responseStart": 1764, + "end": 1765, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "bytes": 118521, + "start": 239, + "responseStart": 1947, + "end": 2277, + "initiator": "script" + } + ] + }, + { + "fcp": 909, + "requests": [ + { + "url": "http://127.0.0.1:5241/?v=benchmedia01", + "status": 200, + "bytes": 14043, + "index": 319, + "startMs": 19, + "headersMs": 172, + "endMs": 244 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 320, + "startMs": 251, + "headersMs": 407, + "endMs": 791 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 321, + "startMs": 251, + "headersMs": 408, + "endMs": 582 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 322, + "startMs": 251, + "headersMs": 408, + "endMs": 428 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 323, + "startMs": 252, + "headersMs": 408, + "endMs": 424 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 324, + "startMs": 252, + "headersMs": 408, + "endMs": 411 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 325, + "startMs": 253, + "headersMs": 409, + "endMs": 576 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 326, + "startMs": 412, + "headersMs": 565, + "endMs": 587 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 327, + "startMs": 425, + "headersMs": 578, + "endMs": 608 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 328, + "startMs": 429, + "headersMs": 580, + "endMs": 582 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 329, + "startMs": 578, + "headersMs": 730, + "endMs": 735 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 330, + "startMs": 582, + "headersMs": 733, + "endMs": 738 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 331, + "startMs": 583, + "headersMs": 733, + "endMs": 738 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 332, + "startMs": 588, + "headersMs": 739, + "endMs": 743 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 333, + "startMs": 609, + "headersMs": 760, + "endMs": 769 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 334, + "startMs": 736, + "headersMs": 888, + "endMs": 890 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 335, + "startMs": 739, + "headersMs": 890, + "endMs": 893 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 336, + "startMs": 739, + "headersMs": 890, + "endMs": 897 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 337, + "startMs": 743, + "headersMs": 893, + "endMs": 916 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 338, + "startMs": 770, + "headersMs": 922, + "endMs": 938 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 339, + "startMs": 792, + "headersMs": 942, + "endMs": 946 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 340, + "startMs": 891, + "headersMs": 1042, + "endMs": 1054 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 341, + "startMs": 893, + "headersMs": 1043, + "endMs": 1051 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 342, + "startMs": 897, + "headersMs": 1048, + "endMs": 1064 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 343, + "startMs": 917, + "headersMs": 1068, + "endMs": 1074 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 344, + "startMs": 939, + "headersMs": 1091, + "endMs": 1101 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 345, + "startMs": 947, + "headersMs": 1098, + "endMs": 1104 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 346, + "startMs": 1052, + "headersMs": 1204, + "endMs": 1208 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 347, + "startMs": 1055, + "headersMs": 1206, + "endMs": 1216 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 348, + "startMs": 1065, + "headersMs": 1216, + "endMs": 1242 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 349, + "startMs": 1075, + "headersMs": 1226, + "endMs": 1230 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 350, + "startMs": 1102, + "headersMs": 1253, + "endMs": 1257 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 351, + "startMs": 1105, + "headersMs": 1255, + "endMs": 1269 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 352, + "startMs": 1209, + "headersMs": 1363, + "endMs": 1378 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 353, + "startMs": 1217, + "headersMs": 1368, + "endMs": 1371 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 354, + "startMs": 1230, + "headersMs": 1380, + "endMs": 1384 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 355, + "startMs": 1242, + "headersMs": 1393, + "endMs": 1404 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 356, + "startMs": 1257, + "headersMs": 1408, + "endMs": 1427 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 357, + "startMs": 1270, + "headersMs": 1421, + "endMs": 1425 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 358, + "startMs": 1372, + "headersMs": 1526, + "endMs": 1531 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 359, + "startMs": 1379, + "headersMs": 1530, + "endMs": 1532 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 360, + "startMs": 1385, + "headersMs": 1536, + "endMs": 1540 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 361, + "startMs": 1405, + "headersMs": 1557, + "endMs": 1562 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 362, + "startMs": 1426, + "headersMs": 1577, + "endMs": 1589 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 363, + "startMs": 1427, + "headersMs": 1578, + "endMs": 1600 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 364, + "startMs": 1532, + "headersMs": 1686, + "endMs": 1784 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 365, + "startMs": 1533, + "headersMs": 1686, + "endMs": 1708 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 366, + "startMs": 1540, + "headersMs": 1691, + "endMs": 2287 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 367, + "startMs": 1563, + "headersMs": 1714, + "endMs": 1716 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 368, + "startMs": 2333, + "headersMs": 2487, + "endMs": 2489 + }, + { + "url": "http://127.0.0.1:5241/api/version", + "status": 200, + "bytes": 62, + "index": 369, + "startMs": 2348, + "headersMs": 2500, + "endMs": 2501 + }, + { + "url": "http://127.0.0.1:5241/api/user/sync", + "status": 200, + "bytes": 11, + "index": 370, + "startMs": 2349, + "headersMs": 2501, + "endMs": 2503 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 371, + "startMs": 2353, + "headersMs": 2507, + "endMs": 2552 + }, + { + "url": "http://127.0.0.1:5241/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 372, + "startMs": 2506, + "headersMs": 2658, + "endMs": 2660 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 373, + "startMs": 2559, + "headersMs": 2711, + "endMs": 2720 + }, + { + "url": "http://127.0.0.1:5241/api/manifest", + "status": 200, + "bytes": 3738, + "index": 374, + "startMs": 2725, + "headersMs": 2877, + "endMs": 2896 + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 375, + "startMs": 2922, + "headersMs": 3077, + "endMs": 3669 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 376, + "startMs": 2923, + "headersMs": 3077, + "endMs": 3086 + }, + { + "url": "http://127.0.0.1:5241/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 377, + "startMs": 2923, + "headersMs": 3077, + "endMs": 3083 + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 378, + "startMs": 2923, + "headersMs": 3077, + "endMs": 3081 + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 379, + "startMs": 2923, + "headersMs": 3077, + "endMs": 3081 + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 380, + "startMs": 2923, + "headersMs": 3077, + "endMs": 3083 + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 381, + "startMs": 3083, + "headersMs": 3236, + "endMs": 3239 + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 382, + "startMs": 3083, + "headersMs": 3236, + "endMs": 3239 + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 383, + "startMs": 3085, + "headersMs": 3236, + "endMs": 3240 + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 384, + "startMs": 3085, + "headersMs": 3236, + "endMs": 3254 + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 385, + "startMs": 3088, + "headersMs": 3239, + "endMs": 3249 + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 386, + "startMs": 3241, + "headersMs": 3396, + "endMs": 3400 + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 387, + "startMs": 3241, + "headersMs": 3397, + "endMs": 3408 + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 388, + "startMs": 3242, + "headersMs": 3397, + "endMs": 3403 + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 389, + "startMs": 3251, + "headersMs": 3404, + "endMs": 3416 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 390, + "startMs": 3256, + "headersMs": 3407, + "endMs": 3560 + }, + { + "url": "http://127.0.0.1:5241/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 391, + "startMs": 3403, + "headersMs": 3555, + "endMs": 3939 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 392, + "startMs": 3405, + "headersMs": 3556, + "endMs": 3655 + }, + { + "url": "http://127.0.0.1:5241/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 393, + "startMs": 3410, + "headersMs": 3561, + "endMs": 3735 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 394, + "startMs": 3418, + "headersMs": 3572, + "endMs": 3632 + }, + { + "url": "http://127.0.0.1:5241/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 395, + "startMs": 3564, + "headersMs": 3715, + "endMs": 3873 + }, + { + "url": "http://127.0.0.1:5241/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 396, + "startMs": 3634, + "headersMs": 3785, + "endMs": 3787 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 397, + "startMs": 3657, + "headersMs": 3808, + "endMs": 3817 + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 398, + "startMs": 3674, + "headersMs": 3825, + "endMs": 3840 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 399, + "startMs": 3738, + "headersMs": 3890, + "endMs": 3898 + }, + { + "url": "http://127.0.0.1:5241/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 400, + "startMs": 3789, + "headersMs": 3941, + "endMs": 3964 + }, + { + "url": "http://127.0.0.1:5241/index.html?v=1cd3a1c30d", + "status": 200, + "bytes": 14043, + "index": 401, + "startMs": 3820, + "headersMs": 3972, + "endMs": 4042 + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 402, + "startMs": 3842, + "headersMs": 3993, + "endMs": 3994 + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 403, + "startMs": 3875, + "headersMs": 4027, + "endMs": 4042 + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 404, + "startMs": 3900, + "headersMs": 4051, + "endMs": 4058 + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 405, + "startMs": 3942, + "headersMs": 4093, + "endMs": 4104 + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 406, + "startMs": 3966, + "headersMs": 4117, + "endMs": 4133 + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 407, + "startMs": 3997, + "headersMs": 4148, + "endMs": 4152 + }, + { + "url": "http://127.0.0.1:5241/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 408, + "startMs": 4045, + "headersMs": 4197, + "endMs": 4200 + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 409, + "startMs": 4045, + "headersMs": 4197, + "endMs": 4202 + }, + { + "url": "http://127.0.0.1:5241/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 410, + "startMs": 4059, + "headersMs": 4211, + "endMs": 4232 + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 411, + "startMs": 4106, + "headersMs": 4258, + "endMs": 4280 + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 4135, + "headersMs": 4286, + "endMs": 4289 + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 413, + "startMs": 4154, + "headersMs": 4305, + "endMs": 4310 + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 414, + "startMs": 4202, + "headersMs": 4354, + "endMs": 4384 + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 415, + "startMs": 4204, + "headersMs": 4354, + "endMs": 4357 + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 416, + "startMs": 4234, + "headersMs": 4385, + "endMs": 4389 + }, + { + "url": "http://127.0.0.1:5241/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 417, + "startMs": 4283, + "headersMs": 4434, + "endMs": 4439 + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 418, + "startMs": 4291, + "headersMs": 4442, + "endMs": 4445 + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 419, + "startMs": 4313, + "headersMs": 4465, + "endMs": 4469 + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 420, + "startMs": 4360, + "headersMs": 4512, + "endMs": 4534 + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 421, + "startMs": 4386, + "headersMs": 4537, + "endMs": 4542 + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 422, + "startMs": 4391, + "headersMs": 4542, + "endMs": 4565 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 423, + "startMs": 4441, + "headersMs": 4593, + "endMs": 4598 + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 424, + "startMs": 4447, + "headersMs": 4598, + "endMs": 4614 + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 425, + "startMs": 4471, + "headersMs": 4622, + "endMs": 4631 + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 426, + "startMs": 4536, + "headersMs": 4688, + "endMs": 4704 + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 427, + "startMs": 4544, + "headersMs": 4695, + "endMs": 4717 + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 428, + "startMs": 4567, + "headersMs": 4717, + "endMs": 4885 + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 429, + "startMs": 4600, + "headersMs": 4752, + "endMs": 4778 + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 430, + "startMs": 4616, + "headersMs": 4767, + "endMs": 4787 + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 431, + "startMs": 4632, + "headersMs": 4783, + "endMs": 4879 + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 432, + "startMs": 4707, + "headersMs": 4859, + "endMs": 4861 + }, + { + "url": "http://127.0.0.1:5241/sw.js", + "status": 200, + "bytes": 8991, + "index": 433, + "startMs": 4896, + "headersMs": 5048, + "endMs": 5093 + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 434, + "startMs": 5095, + "headersMs": 5248, + "endMs": 5258 + }, + { + "url": "http://127.0.0.1:5241/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 435, + "startMs": 5924, + "headersMs": 6077, + "endMs": 6084 + }, + { + "url": "http://127.0.0.1:5241/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 436, + "startMs": 5924, + "headersMs": 6077, + "endMs": 6079 + }, + { + "url": "http://127.0.0.1:5241/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 437, + "startMs": 5924, + "headersMs": 6077, + "endMs": 6087 + }, + { + "url": "http://127.0.0.1:5241/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 438, + "startMs": 5924, + "headersMs": 6077, + "endMs": 6078 + }, + { + "url": "http://127.0.0.1:5241/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 439, + "startMs": 5924, + "headersMs": 6077, + "endMs": 6098 + }, + { + "url": "http://127.0.0.1:5241/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 440, + "startMs": 5924, + "headersMs": 6078, + "endMs": 6084 + }, + { + "url": "http://127.0.0.1:5241/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 441, + "startMs": 6080, + "headersMs": 6233, + "endMs": 6240 + }, + { + "url": "http://127.0.0.1:5241/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 442, + "startMs": 6081, + "headersMs": 6233, + "endMs": 6240 + }, + { + "url": "http://127.0.0.1:5241/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 443, + "startMs": 6086, + "headersMs": 6238, + "endMs": 6243 + }, + { + "url": "http://127.0.0.1:5241/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 444, + "startMs": 6086, + "headersMs": 6238, + "endMs": 6245 + }, + { + "url": "http://127.0.0.1:5241/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 445, + "startMs": 6089, + "headersMs": 6240, + "endMs": 6264 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 446, + "startMs": 6100, + "headersMs": 6253, + "endMs": 6361 + }, + { + "url": "http://127.0.0.1:5241/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 447, + "startMs": 6243, + "headersMs": 6394, + "endMs": 6531 + }, + { + "url": "http://127.0.0.1:5241/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 448, + "startMs": 6244, + "headersMs": 6394, + "endMs": 6410 + }, + { + "url": "http://127.0.0.1:5241/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 449, + "startMs": 6245, + "headersMs": 6396, + "endMs": 6401 + }, + { + "url": "http://127.0.0.1:5241/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 450, + "startMs": 6247, + "headersMs": 6397, + "endMs": 6401 + }, + { + "url": "http://127.0.0.1:5241/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 451, + "startMs": 6267, + "headersMs": 6418, + "endMs": 6421 + }, + { + "url": "http://127.0.0.1:5241/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 452, + "startMs": 6364, + "headersMs": 6515, + "endMs": 6521 + }, + { + "url": "http://127.0.0.1:5241/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 453, + "startMs": 6403, + "headersMs": 6554, + "endMs": 6567 + }, + { + "url": "http://127.0.0.1:5241/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 454, + "startMs": 6403, + "headersMs": 6554, + "endMs": 6565 + }, + { + "url": "http://127.0.0.1:5241/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 455, + "startMs": 6412, + "headersMs": 6563, + "endMs": 6585 + }, + { + "url": "http://127.0.0.1:5241/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 456, + "startMs": 6423, + "headersMs": 6574, + "endMs": 6579 + }, + { + "url": "http://127.0.0.1:5241/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 457, + "startMs": 6523, + "headersMs": 6674, + "endMs": 6681 + }, + { + "url": "http://127.0.0.1:5241/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 458, + "startMs": 6533, + "headersMs": 6684, + "endMs": 6698 + }, + { + "url": "http://127.0.0.1:5241/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 459, + "startMs": 6566, + "headersMs": 6717, + "endMs": 6724 + }, + { + "url": "http://127.0.0.1:5241/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 460, + "startMs": 6568, + "headersMs": 6719, + "endMs": 6724 + }, + { + "url": "http://127.0.0.1:5241/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 461, + "startMs": 6582, + "headersMs": 6733, + "endMs": 6746 + }, + { + "url": "http://127.0.0.1:5241/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 462, + "startMs": 6587, + "headersMs": 6737, + "endMs": 6758 + }, + { + "url": "http://127.0.0.1:5241/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 463, + "startMs": 6684, + "headersMs": 6836, + "endMs": 6853 + }, + { + "url": "http://127.0.0.1:5241/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 464, + "startMs": 6700, + "headersMs": 6851, + "endMs": 6896 + }, + { + "url": "http://127.0.0.1:5241/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 465, + "startMs": 6727, + "headersMs": 6877, + "endMs": 6892 + }, + { + "url": "http://127.0.0.1:5241/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 466, + "startMs": 6727, + "headersMs": 6877, + "endMs": 6898 + }, + { + "url": "http://127.0.0.1:5241/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 467, + "startMs": 6748, + "headersMs": 6899, + "endMs": 6912 + }, + { + "url": "http://127.0.0.1:5241/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 468, + "startMs": 6760, + "headersMs": 6911, + "endMs": 6924 + }, + { + "url": "http://127.0.0.1:5241/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 469, + "startMs": 6856, + "headersMs": 7006, + "endMs": 7046 + }, + { + "url": "http://127.0.0.1:5241/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 470, + "startMs": 6895, + "headersMs": 7047, + "endMs": 7074 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 471, + "startMs": 6898, + "headersMs": 7049, + "endMs": 7057 + }, + { + "url": "http://127.0.0.1:5241/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 472, + "startMs": 6900, + "headersMs": 7051, + "endMs": 7055 + }, + { + "url": "http://127.0.0.1:5241/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 473, + "startMs": 6914, + "headersMs": 7065, + "endMs": 7095 + }, + { + "url": "http://127.0.0.1:5241/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 474, + "startMs": 6926, + "headersMs": 7077, + "endMs": 7302 + }, + { + "url": "http://127.0.0.1:5241/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 475, + "startMs": 7049, + "headersMs": 7200, + "endMs": 7213 + }, + { + "url": "http://127.0.0.1:5241/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 476, + "startMs": 7057, + "headersMs": 7211, + "endMs": 7217 + }, + { + "url": "http://127.0.0.1:5241/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 477, + "startMs": 7059, + "headersMs": 7211, + "endMs": 7249 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5241/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 233, + "responseStart": 393, + "end": 394, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 233, + "responseStart": 406, + "end": 406, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 233, + "responseStart": 410, + "end": 411, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 233, + "responseStart": 558, + "end": 559, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 234, + "responseStart": 564, + "end": 564, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 234, + "responseStart": 569, + "end": 569, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 234, + "responseStart": 590, + "end": 590, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/recommendations.css?v=055101368d", + "bytes": 983, + "start": 234, + "responseStart": 717, + "end": 717, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 234, + "responseStart": 720, + "end": 720, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 234, + "responseStart": 720, + "end": 721, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 235, + "responseStart": 725, + "end": 725, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 235, + "responseStart": 751, + "end": 752, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 235, + "responseStart": 872, + "end": 873, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 235, + "responseStart": 875, + "end": 875, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5241/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 235, + "responseStart": 879, + "end": 879, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 236, + "responseStart": 898, + "end": 898, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 236, + "responseStart": 920, + "end": 920, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 236, + "responseStart": 928, + "end": 928, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 236, + "responseStart": 1033, + "end": 1034, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 236, + "responseStart": 1036, + "end": 1037, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 236, + "responseStart": 1046, + "end": 1046, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 236, + "responseStart": 1056, + "end": 1057, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 236, + "responseStart": 1083, + "end": 1084, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 236, + "responseStart": 1086, + "end": 1086, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 237, + "responseStart": 1190, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 237, + "responseStart": 1198, + "end": 1198, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 237, + "responseStart": 1212, + "end": 1212, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 237, + "responseStart": 1224, + "end": 1224, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 237, + "responseStart": 1239, + "end": 1239, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 237, + "responseStart": 1251, + "end": 1252, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 237, + "responseStart": 1353, + "end": 1353, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 237, + "responseStart": 1360, + "end": 1361, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 237, + "responseStart": 1366, + "end": 1367, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 238, + "responseStart": 1386, + "end": 1386, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 238, + "responseStart": 1408, + "end": 1408, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 238, + "responseStart": 1408, + "end": 1409, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 238, + "responseStart": 1513, + "end": 1514, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 238, + "responseStart": 1514, + "end": 1515, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 238, + "responseStart": 1522, + "end": 1522, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 238, + "responseStart": 1544, + "end": 1544, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 238, + "responseStart": 1571, + "end": 1572, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 238, + "responseStart": 1582, + "end": 1583, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 238, + "responseStart": 1766, + "end": 1767, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 239, + "responseStart": 1690, + "end": 1690, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5241/app.js?v=f485286cbc", + "bytes": 118521, + "start": 239, + "responseStart": 2000, + "end": 2270, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-static-css.json b/perf/results/phase6-static-css.json new file mode 100644 index 0000000..cc6fce2 --- /dev/null +++ b/perf/results/phase6-static-css.json @@ -0,0 +1,7338 @@ +{ + "date": "2026-10-08T00:38:07.271Z", + "frontendCommit": null, + "sourceRoot": "/home/josh/development/personal/ytplayer-codex/wt-assets/perf/.tmp/phase6-static-css", + "sourceCommit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "frontendBuildTag": "33459dd71241", + "commit": "af6aabc3b7fcc9e43ac8378dce55a0fdb3250506", + "runsConfigured": 3, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159, + 159, + 159 + ] + }, + "wireBytes": { + "median": 1097051, + "min": 1097051, + "max": 1097051, + "values": [ + 1097051, + 1097051, + 1097051 + ] + }, + "fcp": { + "median": 898, + "min": 896, + "max": 1024, + "values": [ + 1024, + 896, + 898 + ] + }, + "lcp": { + "median": 974, + "min": 973, + "max": 1100, + "values": [ + 1100, + 974, + 973 + ] + }, + "domContentLoaded": { + "median": 2327, + "min": 2313, + "max": 3095, + "values": [ + 3095, + 2327, + 2313 + ] + }, + "bootDone": { + "median": 2332, + "min": 2318, + "max": 3102, + "values": [ + 3102, + 2332, + 2318 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0, + 0, + 0 + ] + }, + "longTasks": [ + [], + [], + [] + ], + "swInstallDuration": { + "median": 31525, + "min": 31524, + "max": 32333, + "values": [ + 32333, + 31524, + 31525 + ] + }, + "swInstallBytes": { + "median": 1097051, + "min": 1097051, + "max": 1097051, + "values": [ + 1097051, + 1097051, + 1097051 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null, + null, + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28100, + "js": 556715, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5080, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:4381/?v=benchmedia01", + "status": 200, + "bytes": 14050, + "index": 1, + "startMs": 19, + "headersMs": 237, + "endMs": 310 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 317, + "headersMs": 474, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 318, + "headersMs": 475, + "endMs": 651 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 319, + "headersMs": 495, + "endMs": 517 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 5, + "startMs": 319, + "headersMs": 503, + "endMs": 520 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 320, + "headersMs": 507, + "endMs": 510 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 320, + "headersMs": 687, + "endMs": 855 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 520, + "headersMs": 692, + "endMs": 694 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 518, + "headersMs": 718, + "endMs": 749 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 511, + "headersMs": 737, + "endMs": 760 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 652, + "headersMs": 807, + "endMs": 812 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 695, + "headersMs": 851, + "endMs": 856 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 750, + "headersMs": 904, + "endMs": 909 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 761, + "headersMs": 916, + "endMs": 919 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 812, + "headersMs": 971, + "endMs": 979 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 857, + "headersMs": 1010, + "endMs": 1012 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 857, + "headersMs": 1012, + "endMs": 1014 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 859, + "headersMs": 1015, + "endMs": 1022 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 910, + "headersMs": 1078, + "endMs": 1101 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 920, + "headersMs": 1088, + "endMs": 1103 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 980, + "headersMs": 1134, + "endMs": 1138 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1013, + "headersMs": 1171, + "endMs": 1183 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1015, + "headersMs": 1175, + "endMs": 1183 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1023, + "headersMs": 1186, + "endMs": 1202 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1102, + "headersMs": 1258, + "endMs": 1265 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1104, + "headersMs": 1263, + "endMs": 1273 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1139, + "headersMs": 1295, + "endMs": 1301 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1184, + "headersMs": 1338, + "endMs": 1343 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1184, + "headersMs": 1345, + "endMs": 1354 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1203, + "headersMs": 1371, + "endMs": 1397 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1265, + "headersMs": 1420, + "endMs": 1423 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1274, + "headersMs": 1427, + "endMs": 1430 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1302, + "headersMs": 1463, + "endMs": 1477 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1344, + "headersMs": 1506, + "endMs": 1522 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1355, + "headersMs": 1508, + "endMs": 1511 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1398, + "headersMs": 1553, + "endMs": 1558 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1424, + "headersMs": 1581, + "endMs": 1592 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1431, + "headersMs": 1594, + "endMs": 1613 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1479, + "headersMs": 1633, + "endMs": 1638 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1512, + "headersMs": 1667, + "endMs": 1673 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1522, + "headersMs": 1675, + "endMs": 1677 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1559, + "headersMs": 1714, + "endMs": 1718 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1593, + "headersMs": 1747, + "endMs": 1752 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1614, + "headersMs": 1772, + "endMs": 1785 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1639, + "headersMs": 1804, + "endMs": 1826 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1674, + "headersMs": 1901, + "endMs": 1997 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1677, + "headersMs": 1913, + "endMs": 1935 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1719, + "headersMs": 2456, + "endMs": 3054 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1753, + "headersMs": 2464, + "endMs": 2467 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3096, + "headersMs": 3249, + "endMs": 3251 + }, + { + "url": "http://127.0.0.1:4381/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3113, + "headersMs": 3264, + "endMs": 3266 + }, + { + "url": "http://127.0.0.1:4381/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3114, + "headersMs": 3271, + "endMs": 3273 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 53, + "startMs": 3120, + "headersMs": 3304, + "endMs": 3349 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3276, + "headersMs": 3429, + "endMs": 3431 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3356, + "headersMs": 3507, + "endMs": 3517 + }, + { + "url": "http://127.0.0.1:4381/api/manifest", + "status": 200, + "bytes": 3739, + "index": 56, + "startMs": 3523, + "headersMs": 3689, + "endMs": 3707 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3731, + "headersMs": 3883, + "endMs": 4476 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3731, + "headersMs": 3883, + "endMs": 3892 + }, + { + "url": "http://127.0.0.1:4381/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3731, + "headersMs": 3891, + "endMs": 3897 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3731, + "headersMs": 3891, + "endMs": 3896 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3732, + "headersMs": 3891, + "endMs": 3894 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3732, + "headersMs": 3891, + "endMs": 3899 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3894, + "headersMs": 4046, + "endMs": 4050 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3896, + "headersMs": 4047, + "endMs": 4052 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3897, + "headersMs": 4048, + "endMs": 4052 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3899, + "headersMs": 4053, + "endMs": 4072 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3900, + "headersMs": 4053, + "endMs": 4064 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4052, + "headersMs": 4204, + "endMs": 4208 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4053, + "headersMs": 4204, + "endMs": 4217 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4053, + "headersMs": 4204, + "endMs": 4212 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4066, + "headersMs": 4217, + "endMs": 4229 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4073, + "headersMs": 4224, + "endMs": 4378 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4211, + "headersMs": 4363, + "endMs": 4749 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4213, + "headersMs": 4363, + "endMs": 4460 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4218, + "headersMs": 4369, + "endMs": 4544 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4231, + "headersMs": 4382, + "endMs": 4441 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4380, + "headersMs": 4532, + "endMs": 4691 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4443, + "headersMs": 4595, + "endMs": 4597 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4462, + "headersMs": 4614, + "endMs": 4622 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4480, + "headersMs": 4632, + "endMs": 4647 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4546, + "headersMs": 4698, + "endMs": 4706 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4599, + "headersMs": 4750, + "endMs": 4774 + }, + { + "url": "http://127.0.0.1:4381/index.html?v=b033bf779d", + "status": 200, + "bytes": 14050, + "index": 83, + "startMs": 4624, + "headersMs": 4775, + "endMs": 4846 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4649, + "headersMs": 4800, + "endMs": 4802 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4693, + "headersMs": 4844, + "endMs": 4859 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4708, + "headersMs": 4859, + "endMs": 4865 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4751, + "headersMs": 4902, + "endMs": 4913 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4776, + "headersMs": 4927, + "endMs": 4943 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4804, + "headersMs": 4955, + "endMs": 4958 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4848, + "headersMs": 5000, + "endMs": 5003 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4861, + "headersMs": 5012, + "endMs": 5018 + }, + { + "url": "http://127.0.0.1:4381/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4867, + "headersMs": 5031, + "endMs": 5052 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4915, + "headersMs": 5067, + "endMs": 5090 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4946, + "headersMs": 5097, + "endMs": 5100 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4960, + "headersMs": 5111, + "endMs": 5116 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 5005, + "headersMs": 5157, + "endMs": 5187 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5020, + "headersMs": 5171, + "endMs": 5173 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5054, + "headersMs": 5204, + "endMs": 5208 + }, + { + "url": "http://127.0.0.1:4381/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5092, + "headersMs": 5246, + "endMs": 5251 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5102, + "headersMs": 5252, + "endMs": 5256 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5118, + "headersMs": 5269, + "endMs": 5273 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5175, + "headersMs": 5327, + "endMs": 5348 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5188, + "headersMs": 5340, + "endMs": 5346 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5210, + "headersMs": 5361, + "endMs": 5384 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5252, + "headersMs": 5404, + "endMs": 5409 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5258, + "headersMs": 5411, + "endMs": 5426 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5275, + "headersMs": 5426, + "endMs": 5434 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5348, + "headersMs": 5499, + "endMs": 5515 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5350, + "headersMs": 5501, + "endMs": 5523 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5386, + "headersMs": 5537, + "endMs": 4894 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5411, + "headersMs": 4752, + "endMs": 4778 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5428, + "headersMs": 4768, + "endMs": 4790 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5436, + "headersMs": 4777, + "endMs": 4872 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5518, + "headersMs": 4859, + "endMs": 4862 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 115, + "startMs": 4903, + "headersMs": 5054, + "endMs": 5099 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5101, + "headersMs": 5254, + "endMs": 5264 + }, + { + "url": "http://127.0.0.1:4381/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 5928, + "headersMs": 6084, + "endMs": 6091 + }, + { + "url": "http://127.0.0.1:4381/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 5928, + "headersMs": 6085, + "endMs": 6087 + }, + { + "url": "http://127.0.0.1:4381/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 5928, + "headersMs": 6091, + "endMs": 6101 + }, + { + "url": "http://127.0.0.1:4381/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 5928, + "headersMs": 6092, + "endMs": 6094 + }, + { + "url": "http://127.0.0.1:4381/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 5928, + "headersMs": 6107, + "endMs": 6129 + }, + { + "url": "http://127.0.0.1:4381/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 5928, + "headersMs": 6111, + "endMs": 6118 + }, + { + "url": "http://127.0.0.1:4381/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6089, + "headersMs": 6245, + "endMs": 6251 + }, + { + "url": "http://127.0.0.1:4381/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6094, + "headersMs": 6249, + "endMs": 6256 + }, + { + "url": "http://127.0.0.1:4381/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6096, + "headersMs": 6252, + "endMs": 6257 + }, + { + "url": "http://127.0.0.1:4381/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6102, + "headersMs": 6257, + "endMs": 6265 + }, + { + "url": "http://127.0.0.1:4381/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6120, + "headersMs": 6283, + "endMs": 6307 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6131, + "headersMs": 6284, + "endMs": 6393 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 6253, + "headersMs": 6405, + "endMs": 6543 + }, + { + "url": "http://127.0.0.1:4381/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 6258, + "headersMs": 6419, + "endMs": 6436 + }, + { + "url": "http://127.0.0.1:4381/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 6259, + "headersMs": 6422, + "endMs": 6427 + }, + { + "url": "http://127.0.0.1:4381/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 6266, + "headersMs": 6424, + "endMs": 6427 + }, + { + "url": "http://127.0.0.1:4381/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 6310, + "headersMs": 6464, + "endMs": 6466 + }, + { + "url": "http://127.0.0.1:4381/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 6395, + "headersMs": 6550, + "endMs": 6556 + }, + { + "url": "http://127.0.0.1:4381/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 6429, + "headersMs": 6587, + "endMs": 6600 + }, + { + "url": "http://127.0.0.1:4381/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 6429, + "headersMs": 6592, + "endMs": 6602 + }, + { + "url": "http://127.0.0.1:4381/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 6438, + "headersMs": 6607, + "endMs": 6630 + }, + { + "url": "http://127.0.0.1:4381/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 6468, + "headersMs": 6622, + "endMs": 6628 + }, + { + "url": "http://127.0.0.1:4381/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 6546, + "headersMs": 6702, + "endMs": 6709 + }, + { + "url": "http://127.0.0.1:4381/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 6558, + "headersMs": 6718, + "endMs": 6732 + }, + { + "url": "http://127.0.0.1:4381/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 6603, + "headersMs": 6758, + "endMs": 6766 + }, + { + "url": "http://127.0.0.1:4381/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 6604, + "headersMs": 6761, + "endMs": 6766 + }, + { + "url": "http://127.0.0.1:4381/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 6630, + "headersMs": 6781, + "endMs": 6794 + }, + { + "url": "http://127.0.0.1:4381/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 6632, + "headersMs": 6795, + "endMs": 6816 + }, + { + "url": "http://127.0.0.1:4381/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 6712, + "headersMs": 6873, + "endMs": 6890 + }, + { + "url": "http://127.0.0.1:4381/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 6734, + "headersMs": 6912, + "endMs": 6959 + }, + { + "url": "http://127.0.0.1:4381/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 6769, + "headersMs": 6928, + "endMs": 6942 + }, + { + "url": "http://127.0.0.1:4381/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 6769, + "headersMs": 6940, + "endMs": 6961 + }, + { + "url": "http://127.0.0.1:4381/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 6796, + "headersMs": 6954, + "endMs": 6968 + }, + { + "url": "http://127.0.0.1:4381/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 6818, + "headersMs": 6976, + "endMs": 6990 + }, + { + "url": "http://127.0.0.1:4381/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 6892, + "headersMs": 7082, + "endMs": 7120 + }, + { + "url": "http://127.0.0.1:4381/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 6944, + "headersMs": 7122, + "endMs": 7149 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 6961, + "headersMs": 7129, + "endMs": 7138 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 6962, + "headersMs": 7136, + "endMs": 7141 + }, + { + "url": "http://127.0.0.1:4381/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 6969, + "headersMs": 7167, + "endMs": 7197 + }, + { + "url": "http://127.0.0.1:4381/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 6992, + "headersMs": 7361, + "endMs": 7586 + }, + { + "url": "http://127.0.0.1:4381/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7122, + "headersMs": 7370, + "endMs": 7383 + }, + { + "url": "http://127.0.0.1:4381/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7140, + "headersMs": 7374, + "endMs": 7381 + }, + { + "url": "http://127.0.0.1:4381/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7142, + "headersMs": 7397, + "endMs": 7435 + } + ], + "initialJsCss": { + "median": 255200, + "min": 255200, + "max": 255200, + "values": [ + 255200, + 255200, + 255200 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 300, + "responseStart": 500, + "end": 500, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 301, + "responseStart": 493, + "end": 493, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 301, + "responseStart": 503, + "end": 503, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 301, + "responseStart": 677, + "end": 678, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 732, + "end": 732, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 743, + "end": 744, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 795, + "end": 795, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 301, + "responseStart": 839, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 838, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 301, + "responseStart": 892, + "end": 893, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 903, + "end": 903, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 962, + "end": 962, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 303, + "responseStart": 1005, + "end": 1006, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 303, + "responseStart": 1084, + "end": 1084, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1086, + "end": 1086, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1121, + "end": 1121, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1166, + "end": 1167, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 304, + "responseStart": 1167, + "end": 1167, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 304, + "responseStart": 1185, + "end": 1185, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 304, + "responseStart": 1248, + "end": 1248, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1256, + "end": 1256, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1284, + "end": 1285, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1326, + "end": 1326, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1337, + "end": 1338, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1380, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1406, + "end": 1407, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 305, + "responseStart": 1413, + "end": 1414, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 305, + "responseStart": 1460, + "end": 1461, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 305, + "responseStart": 1494, + "end": 1495, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 305, + "responseStart": 1505, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 305, + "responseStart": 1541, + "end": 1541, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1575, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1596, + "end": 1597, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 306, + "responseStart": 1621, + "end": 1621, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 306, + "responseStart": 1656, + "end": 1656, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 306, + "responseStart": 1660, + "end": 1660, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 306, + "responseStart": 1701, + "end": 1701, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 306, + "responseStart": 1735, + "end": 1735, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 306, + "responseStart": 1768, + "end": 1769, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 306, + "responseStart": 1809, + "end": 1810, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 306, + "responseStart": 1918, + "end": 1918, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 306, + "responseStart": 1980, + "end": 1981, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "bytes": 118521, + "start": 307, + "responseStart": 2770, + "end": 3038, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1024, + "requests": [ + { + "url": "http://127.0.0.1:4381/?v=benchmedia01", + "status": 200, + "bytes": 14050, + "index": 1, + "startMs": 19, + "headersMs": 237, + "endMs": 310 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 317, + "headersMs": 474, + "endMs": 859 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 318, + "headersMs": 475, + "endMs": 651 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 319, + "headersMs": 495, + "endMs": 517 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 5, + "startMs": 319, + "headersMs": 503, + "endMs": 520 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 320, + "headersMs": 507, + "endMs": 510 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 320, + "headersMs": 687, + "endMs": 855 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 520, + "headersMs": 692, + "endMs": 694 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 518, + "headersMs": 718, + "endMs": 749 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 511, + "headersMs": 737, + "endMs": 760 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 652, + "headersMs": 807, + "endMs": 812 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 695, + "headersMs": 851, + "endMs": 856 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 750, + "headersMs": 904, + "endMs": 909 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 761, + "headersMs": 916, + "endMs": 919 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 812, + "headersMs": 971, + "endMs": 979 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 857, + "headersMs": 1010, + "endMs": 1012 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 857, + "headersMs": 1012, + "endMs": 1014 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 859, + "headersMs": 1015, + "endMs": 1022 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 910, + "headersMs": 1078, + "endMs": 1101 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 920, + "headersMs": 1088, + "endMs": 1103 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 980, + "headersMs": 1134, + "endMs": 1138 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1013, + "headersMs": 1171, + "endMs": 1183 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1015, + "headersMs": 1175, + "endMs": 1183 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1023, + "headersMs": 1186, + "endMs": 1202 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1102, + "headersMs": 1258, + "endMs": 1265 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1104, + "headersMs": 1263, + "endMs": 1273 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1139, + "headersMs": 1295, + "endMs": 1301 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1184, + "headersMs": 1338, + "endMs": 1343 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1184, + "headersMs": 1345, + "endMs": 1354 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1203, + "headersMs": 1371, + "endMs": 1397 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1265, + "headersMs": 1420, + "endMs": 1423 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1274, + "headersMs": 1427, + "endMs": 1430 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1302, + "headersMs": 1463, + "endMs": 1477 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1344, + "headersMs": 1506, + "endMs": 1522 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1355, + "headersMs": 1508, + "endMs": 1511 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1398, + "headersMs": 1553, + "endMs": 1558 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1424, + "headersMs": 1581, + "endMs": 1592 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1431, + "headersMs": 1594, + "endMs": 1613 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1479, + "headersMs": 1633, + "endMs": 1638 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1512, + "headersMs": 1667, + "endMs": 1673 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1522, + "headersMs": 1675, + "endMs": 1677 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1559, + "headersMs": 1714, + "endMs": 1718 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1593, + "headersMs": 1747, + "endMs": 1752 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1614, + "headersMs": 1772, + "endMs": 1785 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1639, + "headersMs": 1804, + "endMs": 1826 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1674, + "headersMs": 1901, + "endMs": 1997 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1677, + "headersMs": 1913, + "endMs": 1935 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1719, + "headersMs": 2456, + "endMs": 3054 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1753, + "headersMs": 2464, + "endMs": 2467 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3096, + "headersMs": 3249, + "endMs": 3251 + }, + { + "url": "http://127.0.0.1:4381/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3113, + "headersMs": 3264, + "endMs": 3266 + }, + { + "url": "http://127.0.0.1:4381/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3114, + "headersMs": 3271, + "endMs": 3273 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 53, + "startMs": 3120, + "headersMs": 3304, + "endMs": 3349 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3276, + "headersMs": 3429, + "endMs": 3431 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 55, + "startMs": 3356, + "headersMs": 3507, + "endMs": 3517 + }, + { + "url": "http://127.0.0.1:4381/api/manifest", + "status": 200, + "bytes": 3739, + "index": 56, + "startMs": 3523, + "headersMs": 3689, + "endMs": 3707 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3731, + "headersMs": 3883, + "endMs": 4476 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 58, + "startMs": 3731, + "headersMs": 3883, + "endMs": 3892 + }, + { + "url": "http://127.0.0.1:4381/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3731, + "headersMs": 3891, + "endMs": 3897 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3731, + "headersMs": 3891, + "endMs": 3896 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3732, + "headersMs": 3891, + "endMs": 3894 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3732, + "headersMs": 3891, + "endMs": 3899 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3894, + "headersMs": 4046, + "endMs": 4050 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3896, + "headersMs": 4047, + "endMs": 4052 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3897, + "headersMs": 4048, + "endMs": 4052 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3899, + "headersMs": 4053, + "endMs": 4072 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3900, + "headersMs": 4053, + "endMs": 4064 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4052, + "headersMs": 4204, + "endMs": 4208 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4053, + "headersMs": 4204, + "endMs": 4217 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4053, + "headersMs": 4204, + "endMs": 4212 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4066, + "headersMs": 4217, + "endMs": 4229 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4073, + "headersMs": 4224, + "endMs": 4378 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4211, + "headersMs": 4363, + "endMs": 4749 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4213, + "headersMs": 4363, + "endMs": 4460 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4218, + "headersMs": 4369, + "endMs": 4544 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4231, + "headersMs": 4382, + "endMs": 4441 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4380, + "headersMs": 4532, + "endMs": 4691 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4443, + "headersMs": 4595, + "endMs": 4597 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4462, + "headersMs": 4614, + "endMs": 4622 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4480, + "headersMs": 4632, + "endMs": 4647 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4546, + "headersMs": 4698, + "endMs": 4706 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4599, + "headersMs": 4750, + "endMs": 4774 + }, + { + "url": "http://127.0.0.1:4381/index.html?v=b033bf779d", + "status": 200, + "bytes": 14050, + "index": 83, + "startMs": 4624, + "headersMs": 4775, + "endMs": 4846 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4649, + "headersMs": 4800, + "endMs": 4802 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 85, + "startMs": 4693, + "headersMs": 4844, + "endMs": 4859 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4708, + "headersMs": 4859, + "endMs": 4865 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4751, + "headersMs": 4902, + "endMs": 4913 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 4776, + "headersMs": 4927, + "endMs": 4943 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 4804, + "headersMs": 4955, + "endMs": 4958 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4848, + "headersMs": 5000, + "endMs": 5003 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4861, + "headersMs": 5012, + "endMs": 5018 + }, + { + "url": "http://127.0.0.1:4381/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4867, + "headersMs": 5031, + "endMs": 5052 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4915, + "headersMs": 5067, + "endMs": 5090 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4946, + "headersMs": 5097, + "endMs": 5100 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4960, + "headersMs": 5111, + "endMs": 5116 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 5005, + "headersMs": 5157, + "endMs": 5187 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 5020, + "headersMs": 5171, + "endMs": 5173 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 5054, + "headersMs": 5204, + "endMs": 5208 + }, + { + "url": "http://127.0.0.1:4381/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 5092, + "headersMs": 5246, + "endMs": 5251 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 5102, + "headersMs": 5252, + "endMs": 5256 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 5118, + "headersMs": 5269, + "endMs": 5273 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 5175, + "headersMs": 5327, + "endMs": 5348 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 5188, + "headersMs": 5340, + "endMs": 5346 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 5210, + "headersMs": 5361, + "endMs": 5384 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 5252, + "headersMs": 5404, + "endMs": 5409 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 5258, + "headersMs": 5411, + "endMs": 5426 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 5275, + "headersMs": 5426, + "endMs": 5434 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 5348, + "headersMs": 5499, + "endMs": 5515 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 5350, + "headersMs": 5501, + "endMs": 5523 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 5386, + "headersMs": 5537, + "endMs": 4894 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 5411, + "headersMs": 4752, + "endMs": 4778 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 5428, + "headersMs": 4768, + "endMs": 4790 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 5436, + "headersMs": 4777, + "endMs": 4872 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 5518, + "headersMs": 4859, + "endMs": 4862 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 115, + "startMs": 4903, + "headersMs": 5054, + "endMs": 5099 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 116, + "startMs": 5101, + "headersMs": 5254, + "endMs": 5264 + }, + { + "url": "http://127.0.0.1:4381/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 5928, + "headersMs": 6084, + "endMs": 6091 + }, + { + "url": "http://127.0.0.1:4381/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 5928, + "headersMs": 6085, + "endMs": 6087 + }, + { + "url": "http://127.0.0.1:4381/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 5928, + "headersMs": 6091, + "endMs": 6101 + }, + { + "url": "http://127.0.0.1:4381/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 5928, + "headersMs": 6092, + "endMs": 6094 + }, + { + "url": "http://127.0.0.1:4381/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 5928, + "headersMs": 6107, + "endMs": 6129 + }, + { + "url": "http://127.0.0.1:4381/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 5928, + "headersMs": 6111, + "endMs": 6118 + }, + { + "url": "http://127.0.0.1:4381/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6089, + "headersMs": 6245, + "endMs": 6251 + }, + { + "url": "http://127.0.0.1:4381/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6094, + "headersMs": 6249, + "endMs": 6256 + }, + { + "url": "http://127.0.0.1:4381/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6096, + "headersMs": 6252, + "endMs": 6257 + }, + { + "url": "http://127.0.0.1:4381/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6102, + "headersMs": 6257, + "endMs": 6265 + }, + { + "url": "http://127.0.0.1:4381/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6120, + "headersMs": 6283, + "endMs": 6307 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6131, + "headersMs": 6284, + "endMs": 6393 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 6253, + "headersMs": 6405, + "endMs": 6543 + }, + { + "url": "http://127.0.0.1:4381/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 6258, + "headersMs": 6419, + "endMs": 6436 + }, + { + "url": "http://127.0.0.1:4381/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 6259, + "headersMs": 6422, + "endMs": 6427 + }, + { + "url": "http://127.0.0.1:4381/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 6266, + "headersMs": 6424, + "endMs": 6427 + }, + { + "url": "http://127.0.0.1:4381/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 6310, + "headersMs": 6464, + "endMs": 6466 + }, + { + "url": "http://127.0.0.1:4381/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 6395, + "headersMs": 6550, + "endMs": 6556 + }, + { + "url": "http://127.0.0.1:4381/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 6429, + "headersMs": 6587, + "endMs": 6600 + }, + { + "url": "http://127.0.0.1:4381/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 6429, + "headersMs": 6592, + "endMs": 6602 + }, + { + "url": "http://127.0.0.1:4381/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 6438, + "headersMs": 6607, + "endMs": 6630 + }, + { + "url": "http://127.0.0.1:4381/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 6468, + "headersMs": 6622, + "endMs": 6628 + }, + { + "url": "http://127.0.0.1:4381/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 6546, + "headersMs": 6702, + "endMs": 6709 + }, + { + "url": "http://127.0.0.1:4381/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 6558, + "headersMs": 6718, + "endMs": 6732 + }, + { + "url": "http://127.0.0.1:4381/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 6603, + "headersMs": 6758, + "endMs": 6766 + }, + { + "url": "http://127.0.0.1:4381/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 6604, + "headersMs": 6761, + "endMs": 6766 + }, + { + "url": "http://127.0.0.1:4381/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 6630, + "headersMs": 6781, + "endMs": 6794 + }, + { + "url": "http://127.0.0.1:4381/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 6632, + "headersMs": 6795, + "endMs": 6816 + }, + { + "url": "http://127.0.0.1:4381/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 6712, + "headersMs": 6873, + "endMs": 6890 + }, + { + "url": "http://127.0.0.1:4381/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 6734, + "headersMs": 6912, + "endMs": 6959 + }, + { + "url": "http://127.0.0.1:4381/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 6769, + "headersMs": 6928, + "endMs": 6942 + }, + { + "url": "http://127.0.0.1:4381/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 6769, + "headersMs": 6940, + "endMs": 6961 + }, + { + "url": "http://127.0.0.1:4381/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 6796, + "headersMs": 6954, + "endMs": 6968 + }, + { + "url": "http://127.0.0.1:4381/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 6818, + "headersMs": 6976, + "endMs": 6990 + }, + { + "url": "http://127.0.0.1:4381/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 6892, + "headersMs": 7082, + "endMs": 7120 + }, + { + "url": "http://127.0.0.1:4381/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 6944, + "headersMs": 7122, + "endMs": 7149 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 6961, + "headersMs": 7129, + "endMs": 7138 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 6962, + "headersMs": 7136, + "endMs": 7141 + }, + { + "url": "http://127.0.0.1:4381/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 6969, + "headersMs": 7167, + "endMs": 7197 + }, + { + "url": "http://127.0.0.1:4381/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 6992, + "headersMs": 7361, + "endMs": 7586 + }, + { + "url": "http://127.0.0.1:4381/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7122, + "headersMs": 7370, + "endMs": 7383 + }, + { + "url": "http://127.0.0.1:4381/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7140, + "headersMs": 7374, + "endMs": 7381 + }, + { + "url": "http://127.0.0.1:4381/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7142, + "headersMs": 7397, + "endMs": 7435 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 300, + "responseStart": 500, + "end": 500, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 301, + "responseStart": 493, + "end": 493, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 301, + "responseStart": 503, + "end": 503, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 301, + "responseStart": 677, + "end": 678, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 301, + "responseStart": 732, + "end": 732, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 301, + "responseStart": 743, + "end": 744, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "bytes": 983, + "start": 301, + "responseStart": 795, + "end": 795, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 301, + "responseStart": 839, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 301, + "responseStart": 838, + "end": 840, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 301, + "responseStart": 892, + "end": 893, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 302, + "responseStart": 903, + "end": 903, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 302, + "responseStart": 962, + "end": 962, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 302, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 302, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 303, + "responseStart": 1005, + "end": 1006, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 303, + "responseStart": 1084, + "end": 1084, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 303, + "responseStart": 1086, + "end": 1086, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 303, + "responseStart": 1121, + "end": 1121, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 303, + "responseStart": 1166, + "end": 1167, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 304, + "responseStart": 1167, + "end": 1167, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 304, + "responseStart": 1185, + "end": 1185, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 304, + "responseStart": 1248, + "end": 1248, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 304, + "responseStart": 1256, + "end": 1256, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 304, + "responseStart": 1284, + "end": 1285, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 304, + "responseStart": 1326, + "end": 1326, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 304, + "responseStart": 1337, + "end": 1338, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 304, + "responseStart": 1380, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 304, + "responseStart": 1406, + "end": 1407, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 305, + "responseStart": 1413, + "end": 1414, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 305, + "responseStart": 1460, + "end": 1461, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 305, + "responseStart": 1494, + "end": 1495, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 305, + "responseStart": 1505, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 305, + "responseStart": 1541, + "end": 1541, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 305, + "responseStart": 1575, + "end": 1575, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 305, + "responseStart": 1596, + "end": 1597, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 306, + "responseStart": 1621, + "end": 1621, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 306, + "responseStart": 1656, + "end": 1656, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 306, + "responseStart": 1660, + "end": 1660, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 306, + "responseStart": 1701, + "end": 1701, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 306, + "responseStart": 1735, + "end": 1735, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 306, + "responseStart": 1768, + "end": 1769, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 306, + "responseStart": 1809, + "end": 1810, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 306, + "responseStart": 1918, + "end": 1918, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 306, + "responseStart": 1980, + "end": 1981, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "bytes": 118521, + "start": 307, + "responseStart": 2770, + "end": 3038, + "initiator": "script" + } + ] + }, + { + "fcp": 896, + "requests": [ + { + "url": "http://127.0.0.1:4381/?v=benchmedia01", + "status": 200, + "bytes": 14050, + "index": 160, + "startMs": 17, + "headersMs": 170, + "endMs": 242 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 161, + "startMs": 249, + "headersMs": 404, + "endMs": 788 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 162, + "startMs": 250, + "headersMs": 404, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 163, + "startMs": 250, + "headersMs": 404, + "endMs": 425 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 164, + "startMs": 250, + "headersMs": 404, + "endMs": 420 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 165, + "startMs": 251, + "headersMs": 405, + "endMs": 407 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 166, + "startMs": 251, + "headersMs": 405, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 167, + "startMs": 408, + "headersMs": 560, + "endMs": 583 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 168, + "startMs": 421, + "headersMs": 572, + "endMs": 601 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 169, + "startMs": 426, + "headersMs": 577, + "endMs": 578 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 170, + "startMs": 574, + "headersMs": 726, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 171, + "startMs": 577, + "headersMs": 728, + "endMs": 733 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 172, + "startMs": 578, + "headersMs": 728, + "endMs": 734 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 173, + "startMs": 584, + "headersMs": 734, + "endMs": 739 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 174, + "startMs": 602, + "headersMs": 754, + "endMs": 763 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 175, + "startMs": 732, + "headersMs": 883, + "endMs": 885 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 176, + "startMs": 733, + "headersMs": 885, + "endMs": 887 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 177, + "startMs": 735, + "headersMs": 885, + "endMs": 892 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 178, + "startMs": 739, + "headersMs": 889, + "endMs": 911 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 179, + "startMs": 764, + "headersMs": 915, + "endMs": 931 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 180, + "startMs": 789, + "headersMs": 940, + "endMs": 944 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 181, + "startMs": 886, + "headersMs": 1037, + "endMs": 1048 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 182, + "startMs": 888, + "headersMs": 1038, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 183, + "startMs": 892, + "headersMs": 1043, + "endMs": 1059 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 184, + "startMs": 912, + "headersMs": 1063, + "endMs": 1069 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 185, + "startMs": 932, + "headersMs": 1084, + "endMs": 1095 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 186, + "startMs": 945, + "headersMs": 1096, + "endMs": 1103 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 187, + "startMs": 1048, + "headersMs": 1199, + "endMs": 1204 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 188, + "startMs": 1049, + "headersMs": 1199, + "endMs": 1208 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 189, + "startMs": 1060, + "headersMs": 1212, + "endMs": 1238 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 190, + "startMs": 1070, + "headersMs": 1221, + "endMs": 1225 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 191, + "startMs": 1096, + "headersMs": 1247, + "endMs": 1250 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 192, + "startMs": 1103, + "headersMs": 1255, + "endMs": 1270 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 193, + "startMs": 1205, + "headersMs": 1357, + "endMs": 1373 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 194, + "startMs": 1209, + "headersMs": 1360, + "endMs": 1363 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 195, + "startMs": 1225, + "headersMs": 1377, + "endMs": 1381 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 196, + "startMs": 1238, + "headersMs": 1389, + "endMs": 1400 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 197, + "startMs": 1251, + "headersMs": 1402, + "endMs": 1421 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 198, + "startMs": 1271, + "headersMs": 1422, + "endMs": 1427 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 199, + "startMs": 1364, + "headersMs": 1515, + "endMs": 1521 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 200, + "startMs": 1373, + "headersMs": 1524, + "endMs": 1526 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 201, + "startMs": 1382, + "headersMs": 1535, + "endMs": 1539 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 202, + "startMs": 1401, + "headersMs": 1552, + "endMs": 1557 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 203, + "startMs": 1422, + "headersMs": 1573, + "endMs": 1587 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 204, + "startMs": 1428, + "headersMs": 1578, + "endMs": 1600 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 205, + "startMs": 1521, + "headersMs": 1674, + "endMs": 1769 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 206, + "startMs": 1527, + "headersMs": 1678, + "endMs": 1699 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 207, + "startMs": 1540, + "headersMs": 1693, + "endMs": 2286 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 208, + "startMs": 1558, + "headersMs": 1709, + "endMs": 1713 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 209, + "startMs": 2329, + "headersMs": 2482, + "endMs": 2484 + }, + { + "url": "http://127.0.0.1:4381/api/version", + "status": 200, + "bytes": 62, + "index": 210, + "startMs": 2344, + "headersMs": 2496, + "endMs": 2498 + }, + { + "url": "http://127.0.0.1:4381/api/user/sync", + "status": 200, + "bytes": 11, + "index": 211, + "startMs": 2345, + "headersMs": 2498, + "endMs": 2500 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 212, + "startMs": 2349, + "headersMs": 2500, + "endMs": 2545 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 213, + "startMs": 2502, + "headersMs": 2654, + "endMs": 2655 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 214, + "startMs": 2552, + "headersMs": 2704, + "endMs": 2714 + }, + { + "url": "http://127.0.0.1:4381/api/manifest", + "status": 200, + "bytes": 3739, + "index": 215, + "startMs": 2718, + "headersMs": 2872, + "endMs": 2891 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 216, + "startMs": 2915, + "headersMs": 3067, + "endMs": 3660 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 217, + "startMs": 2915, + "headersMs": 3068, + "endMs": 3077 + }, + { + "url": "http://127.0.0.1:4381/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 218, + "startMs": 2915, + "headersMs": 3068, + "endMs": 3074 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 219, + "startMs": 2915, + "headersMs": 3068, + "endMs": 3072 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 220, + "startMs": 2916, + "headersMs": 3068, + "endMs": 3071 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 221, + "startMs": 2916, + "headersMs": 3068, + "endMs": 3074 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 222, + "startMs": 3074, + "headersMs": 3230, + "endMs": 3233 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 223, + "startMs": 3074, + "headersMs": 3230, + "endMs": 3233 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 224, + "startMs": 3076, + "headersMs": 3230, + "endMs": 3234 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 225, + "startMs": 3076, + "headersMs": 3230, + "endMs": 3248 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 226, + "startMs": 3079, + "headersMs": 3230, + "endMs": 3240 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 227, + "startMs": 3235, + "headersMs": 3387, + "endMs": 3391 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 228, + "startMs": 3235, + "headersMs": 3387, + "endMs": 3400 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 229, + "startMs": 3235, + "headersMs": 3387, + "endMs": 3393 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 230, + "startMs": 3242, + "headersMs": 3393, + "endMs": 3406 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 231, + "startMs": 3250, + "headersMs": 3403, + "endMs": 3556 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 232, + "startMs": 3393, + "headersMs": 3546, + "endMs": 3929 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 233, + "startMs": 3394, + "headersMs": 3546, + "endMs": 3644 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 234, + "startMs": 3401, + "headersMs": 3551, + "endMs": 3725 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 235, + "startMs": 3407, + "headersMs": 3558, + "endMs": 3616 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 236, + "startMs": 3558, + "headersMs": 3710, + "endMs": 3869 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 237, + "startMs": 3619, + "headersMs": 3771, + "endMs": 3774 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 238, + "startMs": 3647, + "headersMs": 3799, + "endMs": 3807 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 239, + "startMs": 3664, + "headersMs": 3815, + "endMs": 3830 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 240, + "startMs": 3727, + "headersMs": 3879, + "endMs": 3887 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 241, + "startMs": 3776, + "headersMs": 3928, + "endMs": 3953 + }, + { + "url": "http://127.0.0.1:4381/index.html?v=b033bf779d", + "status": 200, + "bytes": 14050, + "index": 242, + "startMs": 3809, + "headersMs": 3960, + "endMs": 4031 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 243, + "startMs": 3832, + "headersMs": 3985, + "endMs": 3986 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 244, + "startMs": 3873, + "headersMs": 4025, + "endMs": 4040 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 245, + "startMs": 3889, + "headersMs": 4039, + "endMs": 4046 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 246, + "startMs": 3931, + "headersMs": 4083, + "endMs": 4093 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 247, + "startMs": 3955, + "headersMs": 4106, + "endMs": 4122 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 248, + "startMs": 3988, + "headersMs": 4139, + "endMs": 4142 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 249, + "startMs": 4033, + "headersMs": 4185, + "endMs": 4189 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 250, + "startMs": 4042, + "headersMs": 4193, + "endMs": 4199 + }, + { + "url": "http://127.0.0.1:4381/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 251, + "startMs": 4048, + "headersMs": 4199, + "endMs": 4219 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 252, + "startMs": 4098, + "headersMs": 4251, + "endMs": 4274 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 253, + "startMs": 4124, + "headersMs": 4274, + "endMs": 4278 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 254, + "startMs": 4144, + "headersMs": 4295, + "endMs": 4299 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 255, + "startMs": 4191, + "headersMs": 3486, + "endMs": 3515 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 256, + "startMs": 4200, + "headersMs": 3495, + "endMs": 3498 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 257, + "startMs": 4221, + "headersMs": 3515, + "endMs": 3519 + }, + { + "url": "http://127.0.0.1:4381/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 258, + "startMs": 4276, + "headersMs": 3571, + "endMs": 3576 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 259, + "startMs": 4280, + "headersMs": 3576, + "endMs": 3579 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 260, + "startMs": 4301, + "headersMs": 3596, + "endMs": 3601 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 261, + "startMs": 3500, + "headersMs": 3651, + "endMs": 3673 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 262, + "startMs": 3518, + "headersMs": 3670, + "endMs": 3675 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 263, + "startMs": 3520, + "headersMs": 3670, + "endMs": 3694 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 264, + "startMs": 3578, + "headersMs": 3730, + "endMs": 3736 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 265, + "startMs": 3581, + "headersMs": 3731, + "endMs": 3747 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 266, + "startMs": 3603, + "headersMs": 3754, + "endMs": 3763 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 267, + "startMs": 3675, + "headersMs": 3826, + "endMs": 3843 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 268, + "startMs": 3677, + "headersMs": 3826, + "endMs": 3848 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 269, + "startMs": 3696, + "headersMs": 3847, + "endMs": 4014 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 270, + "startMs": 3738, + "headersMs": 3890, + "endMs": 3916 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 271, + "startMs": 3748, + "headersMs": 3899, + "endMs": 3920 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 272, + "startMs": 3765, + "headersMs": 3917, + "endMs": 4012 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 273, + "startMs": 3845, + "headersMs": 3996, + "endMs": 3999 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 274, + "startMs": 4024, + "headersMs": 4176, + "endMs": 4221 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 275, + "startMs": 4223, + "headersMs": 4375, + "endMs": 4384 + }, + { + "url": "http://127.0.0.1:4381/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 276, + "startMs": 5053, + "headersMs": 5205, + "endMs": 5213 + }, + { + "url": "http://127.0.0.1:4381/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 277, + "startMs": 5054, + "headersMs": 5205, + "endMs": 5207 + }, + { + "url": "http://127.0.0.1:4381/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 278, + "startMs": 5054, + "headersMs": 5206, + "endMs": 5215 + }, + { + "url": "http://127.0.0.1:4381/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 279, + "startMs": 5054, + "headersMs": 5206, + "endMs": 5207 + }, + { + "url": "http://127.0.0.1:4381/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 280, + "startMs": 5054, + "headersMs": 5206, + "endMs": 5227 + }, + { + "url": "http://127.0.0.1:4381/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 281, + "startMs": 5054, + "headersMs": 5206, + "endMs": 5213 + }, + { + "url": "http://127.0.0.1:4381/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 282, + "startMs": 5210, + "headersMs": 5362, + "endMs": 5369 + }, + { + "url": "http://127.0.0.1:4381/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 283, + "startMs": 5210, + "headersMs": 5362, + "endMs": 5369 + }, + { + "url": "http://127.0.0.1:4381/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 284, + "startMs": 5215, + "headersMs": 5366, + "endMs": 5371 + }, + { + "url": "http://127.0.0.1:4381/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 285, + "startMs": 5215, + "headersMs": 5366, + "endMs": 5373 + }, + { + "url": "http://127.0.0.1:4381/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 286, + "startMs": 5217, + "headersMs": 5367, + "endMs": 5391 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 287, + "startMs": 5229, + "headersMs": 5380, + "endMs": 5489 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 288, + "startMs": 5371, + "headersMs": 5523, + "endMs": 5660 + }, + { + "url": "http://127.0.0.1:4381/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 289, + "startMs": 5371, + "headersMs": 5523, + "endMs": 5540 + }, + { + "url": "http://127.0.0.1:4381/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 290, + "startMs": 5372, + "headersMs": 5523, + "endMs": 5528 + }, + { + "url": "http://127.0.0.1:4381/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 291, + "startMs": 5375, + "headersMs": 5526, + "endMs": 5530 + }, + { + "url": "http://127.0.0.1:4381/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 292, + "startMs": 5393, + "headersMs": 5543, + "endMs": 5546 + }, + { + "url": "http://127.0.0.1:4381/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 293, + "startMs": 5491, + "headersMs": 5643, + "endMs": 5648 + }, + { + "url": "http://127.0.0.1:4381/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 294, + "startMs": 5530, + "headersMs": 5682, + "endMs": 5694 + }, + { + "url": "http://127.0.0.1:4381/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 295, + "startMs": 5531, + "headersMs": 5682, + "endMs": 5693 + }, + { + "url": "http://127.0.0.1:4381/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 296, + "startMs": 5542, + "headersMs": 5694, + "endMs": 5717 + }, + { + "url": "http://127.0.0.1:4381/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 297, + "startMs": 5547, + "headersMs": 5698, + "endMs": 5704 + }, + { + "url": "http://127.0.0.1:4381/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 298, + "startMs": 5650, + "headersMs": 5801, + "endMs": 5809 + }, + { + "url": "http://127.0.0.1:4381/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 299, + "startMs": 5662, + "headersMs": 5813, + "endMs": 5827 + }, + { + "url": "http://127.0.0.1:4381/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 300, + "startMs": 5695, + "headersMs": 5847, + "endMs": 5854 + }, + { + "url": "http://127.0.0.1:4381/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 301, + "startMs": 5695, + "headersMs": 5847, + "endMs": 5851 + }, + { + "url": "http://127.0.0.1:4381/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 302, + "startMs": 5705, + "headersMs": 5856, + "endMs": 5869 + }, + { + "url": "http://127.0.0.1:4381/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 303, + "startMs": 5719, + "headersMs": 5870, + "endMs": 5891 + }, + { + "url": "http://127.0.0.1:4381/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 304, + "startMs": 5811, + "headersMs": 5963, + "endMs": 5980 + }, + { + "url": "http://127.0.0.1:4381/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 305, + "startMs": 5829, + "headersMs": 5982, + "endMs": 6028 + }, + { + "url": "http://127.0.0.1:4381/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 306, + "startMs": 5853, + "headersMs": 6005, + "endMs": 6019 + }, + { + "url": "http://127.0.0.1:4381/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 307, + "startMs": 5856, + "headersMs": 6007, + "endMs": 6028 + }, + { + "url": "http://127.0.0.1:4381/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 308, + "startMs": 5870, + "headersMs": 6021, + "endMs": 6034 + }, + { + "url": "http://127.0.0.1:4381/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 309, + "startMs": 5893, + "headersMs": 6044, + "endMs": 6058 + }, + { + "url": "http://127.0.0.1:4381/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 310, + "startMs": 5982, + "headersMs": 6134, + "endMs": 6173 + }, + { + "url": "http://127.0.0.1:4381/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 311, + "startMs": 6021, + "headersMs": 6173, + "endMs": 6201 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 312, + "startMs": 6030, + "headersMs": 6181, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 313, + "startMs": 6030, + "headersMs": 6181, + "endMs": 6187 + }, + { + "url": "http://127.0.0.1:4381/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 314, + "startMs": 6036, + "headersMs": 6187, + "endMs": 6217 + }, + { + "url": "http://127.0.0.1:4381/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 315, + "startMs": 6060, + "headersMs": 6210, + "endMs": 6435 + }, + { + "url": "http://127.0.0.1:4381/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 316, + "startMs": 6175, + "headersMs": 6328, + "endMs": 6340 + }, + { + "url": "http://127.0.0.1:4381/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 317, + "startMs": 6189, + "headersMs": 6340, + "endMs": 6347 + }, + { + "url": "http://127.0.0.1:4381/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 318, + "startMs": 6190, + "headersMs": 6340, + "endMs": 6377 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 232, + "responseStart": 404, + "end": 404, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 232, + "responseStart": 409, + "end": 409, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 233, + "responseStart": 391, + "end": 391, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 233, + "responseStart": 556, + "end": 557, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 233, + "responseStart": 561, + "end": 561, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 233, + "responseStart": 567, + "end": 567, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 233, + "responseStart": 585, + "end": 585, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "bytes": 983, + "start": 233, + "responseStart": 715, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 233, + "responseStart": 716, + "end": 717, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 233, + "responseStart": 717, + "end": 718, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 234, + "responseStart": 722, + "end": 722, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 234, + "responseStart": 747, + "end": 747, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 234, + "responseStart": 868, + "end": 869, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 234, + "responseStart": 871, + "end": 871, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 235, + "responseStart": 875, + "end": 875, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 235, + "responseStart": 895, + "end": 895, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 235, + "responseStart": 915, + "end": 915, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 235, + "responseStart": 928, + "end": 928, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 235, + "responseStart": 1031, + "end": 1031, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 235, + "responseStart": 1032, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 235, + "responseStart": 1043, + "end": 1043, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 235, + "responseStart": 1053, + "end": 1053, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 235, + "responseStart": 1078, + "end": 1079, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 236, + "responseStart": 1086, + "end": 1087, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 236, + "responseStart": 1187, + "end": 1188, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 236, + "responseStart": 1192, + "end": 1192, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 236, + "responseStart": 1208, + "end": 1208, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 236, + "responseStart": 1221, + "end": 1221, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 236, + "responseStart": 1234, + "end": 1234, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 236, + "responseStart": 1253, + "end": 1254, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 236, + "responseStart": 1347, + "end": 1347, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 236, + "responseStart": 1356, + "end": 1356, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 237, + "responseStart": 1365, + "end": 1365, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 237, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 237, + "responseStart": 1404, + "end": 1405, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 237, + "responseStart": 1411, + "end": 1411, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 237, + "responseStart": 1504, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 237, + "responseStart": 1510, + "end": 1510, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 237, + "responseStart": 1522, + "end": 1523, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 238, + "responseStart": 1540, + "end": 1541, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 238, + "responseStart": 1570, + "end": 1571, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 238, + "responseStart": 1583, + "end": 1584, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 238, + "responseStart": 1682, + "end": 1683, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 238, + "responseStart": 1753, + "end": 1753, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "bytes": 118521, + "start": 238, + "responseStart": 2003, + "end": 2271, + "initiator": "script" + } + ] + }, + { + "fcp": 898, + "requests": [ + { + "url": "http://127.0.0.1:4381/?v=benchmedia01", + "status": 200, + "bytes": 14050, + "index": 319, + "startMs": 16, + "headersMs": 169, + "endMs": 240 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 320, + "startMs": 247, + "headersMs": 399, + "endMs": 783 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 321, + "startMs": 248, + "headersMs": 400, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 324, + "startMs": 249, + "headersMs": 400, + "endMs": 402 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 322, + "startMs": 248, + "headersMs": 400, + "endMs": 420 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 323, + "startMs": 249, + "headersMs": 400, + "endMs": 416 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 325, + "startMs": 249, + "headersMs": 401, + "endMs": 567 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 326, + "startMs": 403, + "headersMs": 555, + "endMs": 577 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 327, + "startMs": 416, + "headersMs": 569, + "endMs": 598 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 328, + "startMs": 421, + "headersMs": 572, + "endMs": 572 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 329, + "startMs": 568, + "headersMs": 720, + "endMs": 725 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 330, + "startMs": 573, + "headersMs": 724, + "endMs": 729 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 331, + "startMs": 573, + "headersMs": 724, + "endMs": 730 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 332, + "startMs": 578, + "headersMs": 728, + "endMs": 731 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 333, + "startMs": 599, + "headersMs": 751, + "endMs": 760 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 334, + "startMs": 726, + "headersMs": 878, + "endMs": 882 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 335, + "startMs": 730, + "headersMs": 882, + "endMs": 885 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 336, + "startMs": 730, + "headersMs": 882, + "endMs": 889 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 337, + "startMs": 731, + "headersMs": 882, + "endMs": 905 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 338, + "startMs": 760, + "headersMs": 911, + "endMs": 926 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 339, + "startMs": 783, + "headersMs": 935, + "endMs": 938 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 340, + "startMs": 883, + "headersMs": 1035, + "endMs": 1047 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 341, + "startMs": 885, + "headersMs": 1036, + "endMs": 1045 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 342, + "startMs": 889, + "headersMs": 1039, + "endMs": 1055 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 343, + "startMs": 906, + "headersMs": 1056, + "endMs": 1063 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 344, + "startMs": 927, + "headersMs": 1078, + "endMs": 1089 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 345, + "startMs": 939, + "headersMs": 1089, + "endMs": 1095 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 346, + "startMs": 1046, + "headersMs": 1197, + "endMs": 1202 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 347, + "startMs": 1048, + "headersMs": 1197, + "endMs": 1207 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 348, + "startMs": 1056, + "headersMs": 1207, + "endMs": 1233 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 349, + "startMs": 1063, + "headersMs": 1216, + "endMs": 1220 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 350, + "startMs": 1090, + "headersMs": 1241, + "endMs": 1244 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 351, + "startMs": 1096, + "headersMs": 1246, + "endMs": 1261 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 352, + "startMs": 1203, + "headersMs": 1355, + "endMs": 1370 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 353, + "startMs": 1207, + "headersMs": 1357, + "endMs": 1361 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 354, + "startMs": 1221, + "headersMs": 1371, + "endMs": 1375 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 355, + "startMs": 1234, + "headersMs": 1386, + "endMs": 1396 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 356, + "startMs": 1245, + "headersMs": 1396, + "endMs": 1414 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 357, + "startMs": 1261, + "headersMs": 1413, + "endMs": 1418 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 358, + "startMs": 1361, + "headersMs": 1513, + "endMs": 1518 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 359, + "startMs": 1371, + "headersMs": 1521, + "endMs": 1524 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 360, + "startMs": 1375, + "headersMs": 1526, + "endMs": 1529 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 361, + "startMs": 1397, + "headersMs": 1548, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 362, + "startMs": 1415, + "headersMs": 1566, + "endMs": 1578 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 363, + "startMs": 1418, + "headersMs": 1569, + "endMs": 1591 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 364, + "startMs": 1519, + "headersMs": 1671, + "endMs": 1766 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 365, + "startMs": 1524, + "headersMs": 1675, + "endMs": 1696 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 366, + "startMs": 1530, + "headersMs": 1681, + "endMs": 2275 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 367, + "startMs": 1553, + "headersMs": 1705, + "endMs": 1708 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 368, + "startMs": 2314, + "headersMs": 2466, + "endMs": 2468 + }, + { + "url": "http://127.0.0.1:4381/api/version", + "status": 200, + "bytes": 62, + "index": 369, + "startMs": 2329, + "headersMs": 2481, + "endMs": 2482 + }, + { + "url": "http://127.0.0.1:4381/api/user/sync", + "status": 200, + "bytes": 11, + "index": 370, + "startMs": 2330, + "headersMs": 2482, + "endMs": 2484 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 371, + "startMs": 2334, + "headersMs": 2486, + "endMs": 2531 + }, + { + "url": "http://127.0.0.1:4381/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 372, + "startMs": 2486, + "headersMs": 2639, + "endMs": 2641 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 373, + "startMs": 2538, + "headersMs": 2690, + "endMs": 2699 + }, + { + "url": "http://127.0.0.1:4381/api/manifest", + "status": 200, + "bytes": 3739, + "index": 374, + "startMs": 2704, + "headersMs": 2858, + "endMs": 2877 + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 375, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3646 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 376, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3062 + }, + { + "url": "http://127.0.0.1:4381/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 377, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3059 + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 378, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3057 + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 379, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3057 + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 380, + "startMs": 2900, + "headersMs": 3053, + "endMs": 3059 + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 381, + "startMs": 3059, + "headersMs": 3211, + "endMs": 3214 + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 382, + "startMs": 3059, + "headersMs": 3211, + "endMs": 3214 + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 383, + "startMs": 3061, + "headersMs": 3211, + "endMs": 3216 + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 384, + "startMs": 3061, + "headersMs": 3212, + "endMs": 3230 + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 385, + "startMs": 3064, + "headersMs": 3214, + "endMs": 3225 + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 386, + "startMs": 3216, + "headersMs": 3369, + "endMs": 3373 + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 387, + "startMs": 3216, + "headersMs": 3370, + "endMs": 3382 + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 388, + "startMs": 3217, + "headersMs": 3370, + "endMs": 3376 + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 389, + "startMs": 3226, + "headersMs": 3377, + "endMs": 3390 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 390, + "startMs": 3231, + "headersMs": 3382, + "endMs": 3535 + }, + { + "url": "http://127.0.0.1:4381/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 391, + "startMs": 3375, + "headersMs": 3527, + "endMs": 3075 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 392, + "startMs": 3378, + "headersMs": 3528, + "endMs": 3626 + }, + { + "url": "http://127.0.0.1:4381/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 393, + "startMs": 3383, + "headersMs": 3534, + "endMs": 3707 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 394, + "startMs": 3392, + "headersMs": 3541, + "endMs": 3601 + }, + { + "url": "http://127.0.0.1:4381/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 395, + "startMs": 3538, + "headersMs": 3689, + "endMs": 3846 + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 396, + "startMs": 3603, + "headersMs": 3754, + "endMs": 3756 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 397, + "startMs": 3628, + "headersMs": 3780, + "endMs": 3789 + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 398, + "startMs": 3651, + "headersMs": 3802, + "endMs": 3817 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 399, + "startMs": 3710, + "headersMs": 3025, + "endMs": 3034 + }, + { + "url": "http://127.0.0.1:4381/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 400, + "startMs": 3758, + "headersMs": 3074, + "endMs": 3097 + }, + { + "url": "http://127.0.0.1:4381/index.html?v=b033bf779d", + "status": 200, + "bytes": 14050, + "index": 401, + "startMs": 3790, + "headersMs": 3106, + "endMs": 3176 + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 402, + "startMs": 3820, + "headersMs": 3135, + "endMs": 3137 + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "status": 200, + "bytes": 3021, + "index": 403, + "startMs": 3849, + "headersMs": 3165, + "endMs": 3180 + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 404, + "startMs": 3036, + "headersMs": 3187, + "endMs": 3193 + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 405, + "startMs": 3078, + "headersMs": 3229, + "endMs": 3240 + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 406, + "startMs": 3099, + "headersMs": 3250, + "endMs": 3266 + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 407, + "startMs": 3139, + "headersMs": 3290, + "endMs": 3293 + }, + { + "url": "http://127.0.0.1:4381/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 408, + "startMs": 3178, + "headersMs": 3330, + "endMs": 3333 + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 409, + "startMs": 3181, + "headersMs": 3333, + "endMs": 3338 + }, + { + "url": "http://127.0.0.1:4381/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 410, + "startMs": 3195, + "headersMs": 3345, + "endMs": 3366 + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 411, + "startMs": 3242, + "headersMs": 3393, + "endMs": 3415 + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 412, + "startMs": 3268, + "headersMs": 3418, + "endMs": 3422 + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 413, + "startMs": 3295, + "headersMs": 3446, + "endMs": 3451 + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 414, + "startMs": 3335, + "headersMs": 3486, + "endMs": 3516 + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 415, + "startMs": 3340, + "headersMs": 3491, + "endMs": 3493 + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 416, + "startMs": 3368, + "headersMs": 3520, + "endMs": 3523 + }, + { + "url": "http://127.0.0.1:4381/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 417, + "startMs": 3417, + "headersMs": 3569, + "endMs": 3574 + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 418, + "startMs": 3423, + "headersMs": 3574, + "endMs": 3577 + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 419, + "startMs": 3452, + "headersMs": 3604, + "endMs": 3609 + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 420, + "startMs": 3496, + "headersMs": 3647, + "endMs": 3670 + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 421, + "startMs": 3517, + "headersMs": 3669, + "endMs": 3676 + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 422, + "startMs": 3525, + "headersMs": 3676, + "endMs": 3699 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 423, + "startMs": 3576, + "headersMs": 3727, + "endMs": 3733 + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 424, + "startMs": 3578, + "headersMs": 3728, + "endMs": 3743 + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 425, + "startMs": 3611, + "headersMs": 3762, + "endMs": 3771 + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 426, + "startMs": 3672, + "headersMs": 3823, + "endMs": 3840 + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 427, + "startMs": 3678, + "headersMs": 3829, + "endMs": 3851 + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 428, + "startMs": 3702, + "headersMs": 3853, + "endMs": 4021 + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 429, + "startMs": 3736, + "headersMs": 3887, + "endMs": 3912 + }, + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 430, + "startMs": 3745, + "headersMs": 3896, + "endMs": 3916 + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 431, + "startMs": 3773, + "headersMs": 3924, + "endMs": 4021 + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 432, + "startMs": 3842, + "headersMs": 3993, + "endMs": 3996 + }, + { + "url": "http://127.0.0.1:4381/sw.js", + "status": 200, + "bytes": 8993, + "index": 433, + "startMs": 4031, + "headersMs": 4182, + "endMs": 4227 + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 434, + "startMs": 4229, + "headersMs": 4380, + "endMs": 4390 + }, + { + "url": "http://127.0.0.1:4381/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 435, + "startMs": 5057, + "headersMs": 5209, + "endMs": 5216 + }, + { + "url": "http://127.0.0.1:4381/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 436, + "startMs": 5058, + "headersMs": 5209, + "endMs": 5211 + }, + { + "url": "http://127.0.0.1:4381/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 437, + "startMs": 5058, + "headersMs": 5209, + "endMs": 5220 + }, + { + "url": "http://127.0.0.1:4381/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 438, + "startMs": 5058, + "headersMs": 5210, + "endMs": 5211 + }, + { + "url": "http://127.0.0.1:4381/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 439, + "startMs": 5058, + "headersMs": 5210, + "endMs": 5232 + }, + { + "url": "http://127.0.0.1:4381/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 440, + "startMs": 5058, + "headersMs": 5210, + "endMs": 5216 + }, + { + "url": "http://127.0.0.1:4381/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 441, + "startMs": 5213, + "headersMs": 5366, + "endMs": 5373 + }, + { + "url": "http://127.0.0.1:4381/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 442, + "startMs": 5214, + "headersMs": 5366, + "endMs": 5373 + }, + { + "url": "http://127.0.0.1:4381/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 443, + "startMs": 5217, + "headersMs": 5368, + "endMs": 5373 + }, + { + "url": "http://127.0.0.1:4381/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 444, + "startMs": 5218, + "headersMs": 5368, + "endMs": 5376 + }, + { + "url": "http://127.0.0.1:4381/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 445, + "startMs": 5221, + "headersMs": 5371, + "endMs": 5394 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 446, + "startMs": 5235, + "headersMs": 5386, + "endMs": 5494 + }, + { + "url": "http://127.0.0.1:4381/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 447, + "startMs": 5376, + "headersMs": 5526, + "endMs": 5664 + }, + { + "url": "http://127.0.0.1:4381/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 448, + "startMs": 5376, + "headersMs": 5527, + "endMs": 5543 + }, + { + "url": "http://127.0.0.1:4381/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 449, + "startMs": 5376, + "headersMs": 5527, + "endMs": 5532 + }, + { + "url": "http://127.0.0.1:4381/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 450, + "startMs": 5378, + "headersMs": 5528, + "endMs": 5531 + }, + { + "url": "http://127.0.0.1:4381/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 451, + "startMs": 5396, + "headersMs": 5547, + "endMs": 5549 + }, + { + "url": "http://127.0.0.1:4381/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 452, + "startMs": 5496, + "headersMs": 5650, + "endMs": 5655 + }, + { + "url": "http://127.0.0.1:4381/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 453, + "startMs": 5532, + "headersMs": 5686, + "endMs": 5698 + }, + { + "url": "http://127.0.0.1:4381/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 454, + "startMs": 5533, + "headersMs": 5686, + "endMs": 5696 + }, + { + "url": "http://127.0.0.1:4381/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 455, + "startMs": 5545, + "headersMs": 5696, + "endMs": 5718 + }, + { + "url": "http://127.0.0.1:4381/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 456, + "startMs": 5551, + "headersMs": 5701, + "endMs": 5707 + }, + { + "url": "http://127.0.0.1:4381/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 457, + "startMs": 5657, + "headersMs": 5808, + "endMs": 5816 + }, + { + "url": "http://127.0.0.1:4381/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 458, + "startMs": 5666, + "headersMs": 5816, + "endMs": 5830 + }, + { + "url": "http://127.0.0.1:4381/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 459, + "startMs": 5698, + "headersMs": 5849, + "endMs": 5857 + }, + { + "url": "http://127.0.0.1:4381/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 460, + "startMs": 5699, + "headersMs": 5850, + "endMs": 5854 + }, + { + "url": "http://127.0.0.1:4381/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 461, + "startMs": 5708, + "headersMs": 5859, + "endMs": 5872 + }, + { + "url": "http://127.0.0.1:4381/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 462, + "startMs": 5720, + "headersMs": 5870, + "endMs": 5891 + }, + { + "url": "http://127.0.0.1:4381/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 463, + "startMs": 5819, + "headersMs": 5970, + "endMs": 5988 + }, + { + "url": "http://127.0.0.1:4381/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 464, + "startMs": 5832, + "headersMs": 5982, + "endMs": 6027 + }, + { + "url": "http://127.0.0.1:4381/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 465, + "startMs": 5856, + "headersMs": 6007, + "endMs": 6021 + }, + { + "url": "http://127.0.0.1:4381/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 466, + "startMs": 5859, + "headersMs": 6009, + "endMs": 6031 + }, + { + "url": "http://127.0.0.1:4381/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 467, + "startMs": 5873, + "headersMs": 6024, + "endMs": 6038 + }, + { + "url": "http://127.0.0.1:4381/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 468, + "startMs": 5893, + "headersMs": 6044, + "endMs": 6057 + }, + { + "url": "http://127.0.0.1:4381/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 469, + "startMs": 5990, + "headersMs": 6142, + "endMs": 6181 + }, + { + "url": "http://127.0.0.1:4381/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 470, + "startMs": 6024, + "headersMs": 6175, + "endMs": 6202 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 471, + "startMs": 6029, + "headersMs": 6180, + "endMs": 6188 + }, + { + "url": "http://127.0.0.1:4381/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 472, + "startMs": 6033, + "headersMs": 6184, + "endMs": 6189 + }, + { + "url": "http://127.0.0.1:4381/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 473, + "startMs": 6040, + "headersMs": 6190, + "endMs": 6219 + }, + { + "url": "http://127.0.0.1:4381/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 474, + "startMs": 6059, + "headersMs": 6209, + "endMs": 6436 + }, + { + "url": "http://127.0.0.1:4381/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 475, + "startMs": 6184, + "headersMs": 6335, + "endMs": 6347 + }, + { + "url": "http://127.0.0.1:4381/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 476, + "startMs": 6190, + "headersMs": 6340, + "endMs": 6347 + }, + { + "url": "http://127.0.0.1:4381/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 477, + "startMs": 6191, + "headersMs": 6342, + "endMs": 6379 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4381/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 231, + "responseStart": 405, + "end": 405, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 232, + "responseStart": 387, + "end": 387, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/lazy.js?v=99caff8ebd", + "bytes": 3021, + "start": 232, + "responseStart": 400, + "end": 401, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 232, + "responseStart": 549, + "end": 552, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 232, + "responseStart": 557, + "end": 557, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 232, + "responseStart": 562, + "end": 562, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 232, + "responseStart": 583, + "end": 584, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/recommendations.css?v=055101368d", + "bytes": 983, + "start": 232, + "responseStart": 710, + "end": 711, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 232, + "responseStart": 714, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 232, + "responseStart": 714, + "end": 715, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 232, + "responseStart": 716, + "end": 716, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 232, + "responseStart": 744, + "end": 745, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 233, + "responseStart": 867, + "end": 867, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 233, + "responseStart": 869, + "end": 870, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4381/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 233, + "responseStart": 873, + "end": 874, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 233, + "responseStart": 889, + "end": 890, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 234, + "responseStart": 911, + "end": 911, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 234, + "responseStart": 923, + "end": 923, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 234, + "responseStart": 1030, + "end": 1030, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 234, + "responseStart": 1032, + "end": 1032, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 234, + "responseStart": 1040, + "end": 1040, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 234, + "responseStart": 1047, + "end": 1048, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 234, + "responseStart": 1074, + "end": 1074, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 234, + "responseStart": 1080, + "end": 1080, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 234, + "responseStart": 1187, + "end": 1187, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 234, + "responseStart": 1191, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 234, + "responseStart": 1205, + "end": 1205, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 234, + "responseStart": 1218, + "end": 1218, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 235, + "responseStart": 1229, + "end": 1229, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 235, + "responseStart": 1245, + "end": 1246, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 235, + "responseStart": 1345, + "end": 1346, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 235, + "responseStart": 1355, + "end": 1355, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 235, + "responseStart": 1360, + "end": 1360, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 235, + "responseStart": 1381, + "end": 1381, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 235, + "responseStart": 1399, + "end": 1399, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 235, + "responseStart": 1402, + "end": 1403, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 235, + "responseStart": 1503, + "end": 1503, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 236, + "responseStart": 1508, + "end": 1509, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 236, + "responseStart": 1514, + "end": 1514, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 236, + "responseStart": 1537, + "end": 1538, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 236, + "responseStart": 1563, + "end": 1563, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 236, + "responseStart": 1576, + "end": 1576, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 236, + "responseStart": 1681, + "end": 1682, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 236, + "responseStart": 1751, + "end": 1752, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4381/app.js?v=f485286cbc", + "bytes": 118521, + "start": 236, + "responseStart": 1993, + "end": 2261, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/plans/phase6-investigation.md b/plans/phase6-investigation.md new file mode 100644 index 0000000..f5e5a13 --- /dev/null +++ b/plans/phase6-investigation.md @@ -0,0 +1,53 @@ +# Phase 6 investigation + +All comparisons use the current instrumented harness with matching frontend and +server from detached worktrees beneath `perf/.tmp`. No production requests. +Command template (three fresh contexts): + +``` +node perf/baseline.mjs --runs 3 --browser webkit --profile lte --scenario cold --source-root perf/.tmp/phase6- --out perf/results/phase6-.json +``` + +| Source | Commit | LTE FCP median ms | Wire bytes | app.js positive responses/sample | +|---|---|---:|---:|---:| +| Phase 2 | 4950d3e | 1044 | 1191063 | 2 | +| Immediately before lazy layouts | d98d444 | 1032 | 1191686 | 2 | +| First lazy-layout cut | 5d6a154 | 1615 | 1106796 | 2 | +| Phase 3 tip | cd4a25a | 1646 | 1108191 | 2 | +| Phase 5 tip (same product as Phase 4) | 21c1273 | 1736 | 1097007 | 2 | +| Phase 5 + worker force-cache | scratch | 1745 | 1097006 | 2 | +| Phase 5 + parser-owned classic CSS | scratch | 898 | 1097051 | 2 | +| Phase 5 + classic preload | scratch | 909 | 1097032 | 2 | + +The adjacent-commit measurements isolate `5d6a154`, not the Phase 4 extraction. +All three FCP samples, complete proxy waterfalls, and page Resource Timing are +stored in each result. The first sample often includes startup compression cost; +it is retained in every median, not discarded. + +Phase 3 sample 2: common styles finish around 880 ms. The parser-written classic +stylesheet is discovered at 416 ms but reaches the proxy only at 1434 ms and +finishes at 1607 ms. FCP is 1646 ms. Phase 5 sample 2: classic reaches the proxy +at 1540 ms, finishes at 1711 ms, FCP is 1736 ms. Speculatively discovered body +scripts already occupy the request queue when the selected stylesheet arrives. +Phase 2 discovers its declarative styles together around 231 ms, FCP 1044 ms. + +The first service-worker request is at 2458 ms in Phase 3 and 2337 ms in Phase 5, +AFTER paint. Worker install competition does not explain this FCP regression. +Font preload URLs match the font CSS; late layout CSS is the final rendering +barrier. Making classic CSS declarative again removes the delay without changing +CSS bytes or cascade order. This scratch variant unconditionally applies classic +and is diagnostic only; the shipping fix must retain selected-layout behavior. + +The modern synchronizer already uses default fetch caching. Changing it to +force-cache has no effect: every WebKit sample still transfers app.js twice. +The page and worker cannot reuse these HTTP-cache responses in this harness. +A same-build page handoff can reuse the page HTTP cache instead. Worker validation +must check both the X-Asset-Hash header and SHA-256 of the decoded bytes. It must +strip compressed transport headers before constructing the cached Response. +Updates and legacy migration must continue through their existing worker path. + +The shipping CSS fix is a preload, not an unconditional stylesheet. Its three-run +FCP is 909 ms; the first classic request reaches the proxy at 250 ms and completes +at 423 ms. Lazy still applies only the saved layout, in the original cascade order. +Other selected layouts may speculatively download the small classic stylesheet; +it never applies or blocks their rendering. No inline script or CSP change. From e7a7cdc6b9fb69cf1426c5f94cd79371787a262a Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 08:50:51 +0800 Subject: [PATCH 46/81] Preload classic layout CSS before the blocking head loader --- frontend/index.html | 2 ++ frontend/shell-consistency.test.js | 10 ++++++++++ server/static-delivery.test.js | 5 +++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index ead66fd..682325e 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -20,6 +20,8 @@ + + diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index bbdfbff..8302dd8 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -70,6 +70,8 @@ test('only core scripts and styles remain eager; native fallback and active layo const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); const background=new Set(Object.values(groups).filter(g=>g.background).flatMap(g=>g.files)); for(const match of html.matchAll(/<(?:script\b[^>]*\bsrc|link\b[^>]*\bhref)="([^"]+)"/gi)) { + // A style preload discovers bytes without applying or blocking another layout. + if(match[0].includes('rel="preload"'))continue; const path='/'+match[1].replace(/^\//,'').split(/[?#]/)[0]; assert.ok(!background.has(path),`${path} is not eager`); } @@ -88,3 +90,11 @@ test('layout-independent visibility and transport defaults stay in eager CSS',() for(const selector of ['.stg-overlay','.deck-chips','.np-btn.done .i-save','.sleep-status .sl-ic','.ab-group','.mc-tune'])assert.ok(shared.includes(selector)); assert.ok(html.includes('href="layout-base.css"')); }); + + +test('classic first-visit style preload is discovered before the head loader without applying another layout',()=>{ + const preload=html.match(/]*rel="preload"[^>]*href="theme-classic.css"[^>]*as="style"[^>]*>/); + assert.ok(preload,'classic stylesheet has an early preload'); + assert.ok(html.indexOf(preload[0])]*rel="stylesheet"[^>]*href="theme-classic.css"/.test(html),'the selected layout remains parser-applied by the loader'); +}); diff --git a/server/static-delivery.test.js b/server/static-delivery.test.js index ed0661e..e54ab5b 100644 --- a/server/static-delivery.test.js +++ b/server/static-delivery.test.js @@ -13,7 +13,7 @@ mkdirSync(publicDir); mkdirSync(dataDir); mkdirSync(join(publicDir, 'fonts')); mkdirSync(join(publicDir, 'icons')); -writeFileSync(join(publicDir, 'index.html'), ''); +writeFileSync(join(publicDir, 'index.html'), ''); writeFileSync(join(publicDir, 'app.css'), 'body{}'); writeFileSync(join(publicDir, 'app.js'), 'window.app=true;'); writeFileSync(join(publicDir, 'root.css'), 'body{color:red}'); @@ -99,7 +99,8 @@ describe('static delivery characterization', () => { const html = await index.text(); const { buildTag, files } = await (await fetch(`${server.base}/api/manifest`)).json(); expect(html).toContain(``); - expect(html).toContain(`href="app.css?v=${files['/app.css'].h}"`); + expect(html).toContain(``); + expect(html.match(new RegExp('app\\.css\\?v='+files['/app.css'].h,'g'))).toHaveLength(2); expect(html).toContain(`src="app.js?v=${files['/app.js'].h}"`); expect(html).toContain('https://cdn.example/x.js'); expect(html).toContain(`href="/root.css?v=${files['/root.css'].h}"`); From a86fa1cebeb8e30896a1383547402f907ac05f21 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 09:04:20 +0800 Subject: [PATCH 47/81] Cache the page-owned app response before starting the worker --- frontend/app-bootstrap.js | 44 +++++++++++++++++++++++++++++ frontend/app-bootstrap.test.js | 45 ++++++++++++++++++++++++++++++ frontend/app-seams.test.js | 2 +- frontend/asset-worker.test.js | 9 ++++++ frontend/assets.json | 3 +- frontend/index.html | 6 ++-- frontend/lazy.js | 13 +++++++++ frontend/lazy.test.js | 23 +++++++++++---- frontend/shell-consistency.test.js | 11 ++++++++ frontend/sw.js | 1 + perf/README.md | 4 +++ perf/baseline.mjs | 5 +++- perf/measurement.mjs | 5 ++++ perf/measurement.test.mjs | 9 +++++- server/asset-manifest.js | 11 ++++---- server/asset-manifest.test.js | 12 ++++++++ 16 files changed, 186 insertions(+), 17 deletions(-) create mode 100644 frontend/app-bootstrap.js create mode 100644 frontend/app-bootstrap.test.js diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js new file mode 100644 index 0000000..3152544 --- /dev/null +++ b/frontend/app-bootstrap.js @@ -0,0 +1,44 @@ +/* Cache the single page-owned app response before it registers the worker. */ +(function (root) { + 'use strict'; + const doc=root.document, manifest=root.Lazy.manifest, key=root.Lazy.url('/app.js'); + let domReady=doc.readyState==='complete', appSawDom=false; + doc.addEventListener('DOMContentLoaded',()=>{domReady=true;appSawDom=typeof root.boot==='function';},{once:true}); + function execute(node) { + doc.head.append(node); + node.remove(); + delete root.Lazy.appResponse; + // app.js keeps its original DOMContentLoaded listener. Async response + // consumption can finish after that event; boot exactly once in that case. + if(domReady)root.boot(); + } + async function start() { + if(!manifest.appCache || !root.crypto?.subtle) { + await new Promise((resolve,reject)=>{ + const node=doc.createElement('script');node.src=key; + node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); + doc.head.append(node); + }); + return; + } + const expected=manifest.files['/app.js'].h; + let cache; + try { cache=await root.caches?.open('ytplayer-assets'); } catch {} + let response=await cache?.match(key); + if(!response || response.headers.get('X-Asset-Hash')!==expected)response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); + if(!response.ok || response.headers.get('X-Asset-Hash')!==expected)throw Error('Player asset hash mismatch'); + const bytes=await response.clone().arrayBuffer(); + const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); + const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); + const permission="'sha256-"+root.btoa(String.fromCharCode(...digest))+"'"; + if(hex.slice(0,10)!==expected || !doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); + // CacheStorage may share a full quota with saved music. Never remove data + // to make room; boot from these verified bytes even if caching is refused. + try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } + const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); + execute(node); + } + const ready=start(); + root.AppBootstrap={ready}; + ready.catch(error=>root.console.error('[app-cache]',error.message)); +})(typeof window!=='undefined'?window:globalThis); diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js new file mode 100644 index 0000000..912b9e0 --- /dev/null +++ b/frontend/app-bootstrap.test.js @@ -0,0 +1,45 @@ +const {test}=require('node:test'); +const assert=require('node:assert/strict'); +const {webcrypto,createHash}=require('node:crypto'); +const vm=require('node:vm'); +const {readFileSync}=require('node:fs'); +function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false}={}){ + const source='window.appRuns=(window.appRuns||0)+1; window.boot=()=>window.bootRuns=(window.bootRuns||0)+1; document.addEventListener("DOMContentLoaded",boot);',hash=createHash('sha256').update(source).digest('hex'), key='/app.js?v='+hash.slice(0,10); + const held=new Map(), appended=[],listeners={};let calls=0; + const response=()=>new Response(tampered?'bad':source,{headers:{'X-Asset-Hash':hash.slice(0,10)}}); + if(cached)held.set(key,response()); + const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,Lazy:{manifest:{appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; + const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {vm.runInContext(source,context);queueMicrotask(()=>node.onload());}}}}; + root.window=root;const context=vm.createContext(root); + vm.runInContext(readFileSync(require.resolve('./app-bootstrap.js'),'utf8'),context); + return {root,held,appended,listeners,key,calls:()=>calls,doc,response}; +} +test('cold boot caches verified app before execution so worker skips its download',async()=>{ + const f=fixture();await f.root.AppBootstrap.ready;assert.equal(f.calls(),1);assert.ok(f.held.has(f.key));assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1);assert.equal(f.appended[0].src,undefined);assert.equal(f.appended[0].removed,true); +}); +test('offline boot reads the exact cached app without network or re-evaluation',async()=>{ + const f=fixture({cached:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1); +}); +test('tampered cached bytes are rejected before execution',async()=>{ + const f=fixture({cached:true,tampered:true});await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); +}); +test('native and rollback boot use the original external classic script',async()=>{ + const f=fixture({enabled:false});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); +}); +test('boot waits for the normal DOM event when the parser has not finished',async()=>{ + const f=fixture({loading:true});await f.root.AppBootstrap.ready;assert.equal(f.root.bootRuns,undefined);for(const fn of f.listeners.DOMContentLoaded)fn();assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1); +}); +test('quota failure still executes the verified response without deleting saved data',async()=>{ + const f=fixture({quota:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),1);assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1); +}); + + +test('the early head response is consumed without a second page fetch',async()=>{ + const f=fixture();f.root.Lazy.appResponse=Promise.resolve(f.response());await f.root.AppBootstrap.ready; + assert.equal(f.calls(),0);assert.ok(f.held.has(f.key));assert.equal(f.root.appRuns,1); +}); + + +test('insecure local HTTP boot retains external execution without WebCrypto',async()=>{ + const f=fixture({insecure:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); +}); diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index ced5ccd..f17e810 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -30,7 +30,7 @@ test('Phase 4 preserves the exact player, continuity, tracking and queue bodies' test('eager shell and Settings definitions load before app state and defer reading it',()=>{ const html=readFileSync(join(__dirname,'index.html'),'utf8'); for(const file of ['shell-core.js','views-core.js','section-rail.js']) { - assert.ok(html.indexOf('src="'+file+'"'){ await Promise.all([e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}}),e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}})]); assert.equal(e.fetches.filter(url=>url==='/extra.js?v=extra').length,1); }); + + +test('page-captured app is reused on first install without a worker download',async()=>{ + const e=environment(),cache=await e.storage.open(core.CACHE); + await cache.put('/app.js?v=app',new Response('page captured app',{headers:{'X-Asset-Hash':'app'}})); + await e.dispatch('install');assert.equal(e.fetches.includes('/app.js?v=app'),false); + assert.equal(await(await cache.match('/app.js?v=app')).text(),'page captured app'); + assert.equal(e.skips.length,0);assert.equal(await core.state(cache),null); +}); diff --git a/frontend/assets.json b/frontend/assets.json index c8469f1..3ec184c 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -60,7 +60,8 @@ "/device-db.js", "/shell-core.js", "/views-core.js", - "/section-rail.js" + "/section-rail.js", + "/app-bootstrap.js" ], "background": false }, diff --git a/frontend/index.html b/frontend/index.html index 682325e..76f1ab0 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -13,13 +13,13 @@ YT Player - + @@ -674,6 +674,6 @@ - + diff --git a/frontend/lazy.js b/frontend/lazy.js index 7bb4258..6b8214b 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -122,6 +122,19 @@ for (const type of ['pointerenter', 'focus', 'touchstart']) element.addEventListener(type, () => load(name).catch(() => {}), { once: true, passive: true }); }, }; + // Own this response once. Classic-script and fetch preloads do not share + // their cached bodies in WebKit; the later bootstrap consumes this promise. + if(manifest.appCache && root.crypto?.subtle) { + api.appResponse=(async()=>{ + const key=url('/app.js'); + try { + const cache=await root.caches?.open('ytplayer-assets'), held=await cache?.match(key); + if(held?.headers.get('X-Asset-Hash')===manifest.files['/app.js']?.h && held)return held; + } catch {} + return root.fetch(key,{credentials:'same-origin'}); + })(); + api.appResponse.catch(()=>{}); + } root.Lazy = api; root.navigator.serviceWorker?.addEventListener('message',event=>{ if(event.data?.type==='ASSET_LAYOUT_REQUEST') event.source?.postMessage({type:'LAYOUT',value:api.layout}); diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index b084413..516c3de 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -2,16 +2,16 @@ const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const vm = require('node:vm'); -function fixture(current, held = []) { - const inserted = [], listeners = {}, writes = []; - const manifest = { buildTag: 'own', groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } }; +function fixture(current, held = [], appCache = false) { + const inserted = [], listeners = {}, writes = [], fetched = []; + const manifest = { buildTag: 'own', appCache, groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/app.js':{h:'a'}, '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } }; const doc = { readyState:'loading', documentElement: { dataset:{} }, getElementById: () => ({ textContent:JSON.stringify(manifest) }), querySelectorAll: () => [], createElement: tag => ({ tagName:tag.toUpperCase() }), write: value => writes.push(value), addEventListener: (t,f) => listeners[t]=f }; doc.head = { append: node => { inserted.push(node); queueMicrotask(() => node.onload?.()); } }; - const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, setTimeout, clearTimeout, navigator:{}, addEventListener(){} }; + const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{}, addEventListener(){} }; if (current) root.caches = { open: async () => ({ match: async key => key === '/__ytp_asset_state' ? new Response(JSON.stringify({current})) : held.includes(key) ? new Response('', {headers:{'X-Asset-Hash':key.split('=')[1]}}) : undefined }) }; root.window=root; root.globalThis=root; vm.runInNewContext(readFileSync(require.resolve('./lazy.js'),'utf8'), root); - return { root, inserted, writes, listeners, manifest }; + return { root, inserted, writes, listeners, manifest, fetched }; } test('external head bootstrap selects remembered CSS before paint without fetching a manifest', () => { const {root,writes}=fixture(); @@ -84,3 +84,16 @@ test('classic chunk registry proxies use window.YT and keep the executed singlet const singleton=root.YT.TestApi;await root.Lazy.load('feature:test'); assert.equal(root.YT.TestApi,singleton);assert.equal(inserted.length,2); }); + + +test('server-enabled head capture owns exactly one app response; native and rollback do not fetch',async()=>{ + const modern=fixture(null,[],true);await modern.root.Lazy.appResponse; + assert.deepEqual(modern.fetched,['/app.js?v=a']); + const legacy=fixture();assert.deepEqual(legacy.fetched,[]);assert.equal(legacy.root.Lazy.appResponse,undefined); +}); + + +test('head capture is cache-first even before a worker controls the page',async()=>{ + const f=fixture(fixture().manifest,['/app.js?v=a'],true);const response=await f.root.Lazy.appResponse; + assert.equal(response.headers.get('X-Asset-Hash'),'a');assert.deepEqual(f.fetched,[]); +}); diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index 8302dd8..bfd326c 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -98,3 +98,14 @@ test('classic first-visit style preload is discovered before the head loader wit assert.ok(html.indexOf(preload[0])]*rel="stylesheet"[^>]*href="theme-classic.css"/.test(html),'the selected layout remains parser-applied by the loader'); }); + + +test('the eager cache bootstrap stays last and retains app.js in core and legacy shell',()=>{ + const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); + assert.ok(groups.core.files.includes('/app-bootstrap.js')); + assert.ok(groups.core.files.includes('/app.js')); + assert.ok(listed.has('/app-bootstrap.js')&&listed.has('/app.js')); + assert.ok(html.indexOf('src="app-bootstrap.js"')>html.indexOf('src="section-rail.js"')); + assert.ok(html.includes("'sha256-__APP_SCRIPT_HASH__'")); + assert.ok(readFileSync(join(__dirname,'lazy.js'),'utf8').includes("api.appResponse=(async()=>")); +}); diff --git a/frontend/sw.js b/frontend/sw.js index 0551c1b..410430c 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -146,6 +146,7 @@ const SHELL = [ '/share-external.js', '/stats-view.js', '/app.js', + '/app-bootstrap.js', '/manifest.webmanifest', '/icons/icon-192.png', '/icons/icon-512.png', diff --git a/perf/README.md b/perf/README.md index ee46ade..96b74cb 100644 --- a/perf/README.md +++ b/perf/README.md @@ -346,3 +346,7 @@ Every cold sample has `waterfalls`: proxy request order/start/headers/end times and page Resource Timing discovery/start/end times. Proxy times start when tracking begins; page times start at navigation. Compare within each clock, then use the page FCP to locate the rendering dependency. + +Pass `--assert-cold` on new builds to require exactly one positive-byte app.js +response in every cold sample, including worker installation. Omit this assertion +when diagnosing historical regressions. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index 3f64556..92190a2 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -26,7 +26,7 @@ */ import assert from 'node:assert/strict'; -import { assertChangedAssets, assertWarmAssets, waitForIdleAssets } from './measurement.mjs'; +import { assertColdAssets, assertChangedAssets, assertWarmAssets, waitForIdleAssets } from './measurement.mjs'; import { createHash } from 'node:crypto'; import { spawn, spawnSync, execFileSync } from 'node:child_process'; import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs'; @@ -63,6 +63,7 @@ function parseArgs() { compare: null, frontendCommit: null, sourceRoot: null, + assertCold: false, }; for (let i = 0; i < args.length; i++) { @@ -72,6 +73,7 @@ function parseArgs() { else if (a === '--profile' && i + 1 < args.length) options.profile = args[++i]; else if (a === '--scenario' && i + 1 < args.length) options.scenario = args[++i]; else if (a === '--out' && i + 1 < args.length) options.out = args[++i]; + else if (a === '--assert-cold') options.assertCold = true; else if (a === '--source-root' && i + 1 < args.length) options.sourceRoot = path.resolve(args[++i]); else if (a === '--frontend-commit' && i + 1 < args.length) options.frontendCommit = args[++i]; else if (a === '--compare' && i + 1 < args.length) options.compare = args[++i]; @@ -774,6 +776,7 @@ async function main() { for (let r = 0; r < options.runs; r++) { process.stdout.write(` run ${r + 1}/${options.runs}... `); const res = await runColdScenario({ browserType: bType, server, proxy, profile: prof }); + if(options.assertCold)assertColdAssets(res.requests); coldRuns.push(res); console.log(`done (${res.wireBytes} bytes, ${res.requestCount} reqs, boot=${res.bootDone}ms)`); } diff --git a/perf/measurement.mjs b/perf/measurement.mjs index 66035aa..f255f76 100644 --- a/perf/measurement.mjs +++ b/perf/measurement.mjs @@ -27,3 +27,8 @@ export function assertWarmAssets(requests) { const assets=requests.filter(r=>r.bytes>0&&/\.(?:js|css|woff2?|png|svg)(?:[?#]|$)/.test(r.url)&&!new URL(r.url,'http://localhost').pathname.endsWith('/sw.js')); assert.deepEqual(assets,[],'warm reload does not transfer unfinished shell assets'); } + +export function assertColdAssets(requests) { + const transferred=requests.filter(r=>r.bytes>0&&new URL(r.url,'http://localhost').pathname==='/app.js'); + assert.equal(transferred.length,1,'cold app.js transfers its body exactly once across page and worker'); +} diff --git a/perf/measurement.test.mjs b/perf/measurement.test.mjs index 6fd0109..0e2c361 100644 --- a/perf/measurement.test.mjs +++ b/perf/measurement.test.mjs @@ -1,6 +1,6 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { assertChangedAssets, assertWarmAssets } from './measurement.mjs'; +import { assertChangedAssets, assertWarmAssets, assertColdAssets } from './measurement.mjs'; test('changed CSS and feature measurements reject unrelated application transfers',()=>{ const requests=[{url:'/sw.js',bytes:7000},{url:'/asset-sync-core.js',bytes:2000},{url:'/index.html',bytes:12000},{url:'/api/manifest',bytes:3000},{url:'/theme-glass.css?v=new',bytes:5000},{url:'/fonts/a.woff2',bytes:0}]; assertChangedAssets(requests,'/theme-glass.css'); @@ -14,3 +14,10 @@ test('warm measurements reject unfinished shell downloads but allow API checks', assertWarmAssets([{url:'/api/version',bytes:62},{url:'/app.js?v=current',bytes:0}]); assert.throws(()=>assertWarmAssets([{url:'/theme-glass.css?v=current',bytes:5000}])); }); + + +test('cold acceptance rejects a second positive app response while allowing cache revalidation',()=>{ + assertColdAssets([{url:'/app.js?v=current',bytes:12000},{url:'/app.js?v=current',bytes:0}]); + assert.throws(()=>assertColdAssets([{url:'/app.js?v=current',bytes:12000},{url:'/app.js?v=current',bytes:12000}])); + assert.throws(()=>assertColdAssets([])); +}); diff --git a/server/asset-manifest.js b/server/asset-manifest.js index 82127d2..47eff33 100644 --- a/server/asset-manifest.js +++ b/server/asset-manifest.js @@ -8,12 +8,12 @@ const tagHash = bytes => createHash('sha256').update(bytes).digest('hex').slice( export const injectBuildTag = (source, tag) => source.replace( /typeof __BUILD_TAG__ !== 'undefined' \? __BUILD_TAG__ : '[^']*'/, JSON.stringify(tag)); -function embedAssets(source, files, groups, buildTag, hashing) { +function embedAssets(source, files, groups, buildTag, hashing, assetSync) { const pageFiles = {}; for (const group of Object.values(groups)) for (const path of group.files) { if (path !== '/index.html' && path !== '/sw.js') pageFiles[path] = { ...files[path], h: hashing ? files[path].h : buildTag }; } - const json = JSON.stringify({ buildTag, groups, files: pageFiles }).replace(/)[\s\S]*?(<\/script>)/, (_, open, close) => open + json + close); } @@ -70,16 +70,17 @@ export function createAssetManifest(publicDir = './public', { hashing = true, bu } const files = {}; for (const url of [...bytes.keys()].sort()) files[url] = { h: assetHash(bytes.get(url)), s: bytes.get(url).length, g: membership.get(url) || 'core' }; - const source = bytes.get('/index.html')?.toString() ?? null; + const source = bytes.get('/index.html')?.toString() + .replaceAll('__APP_SCRIPT_HASH__', createHash('sha256').update(bytes.get('/app.js') || '').digest('base64')) ?? null; const swSource = bytes.get('/sw.js')?.toString() ?? null; // Derived build metadata cannot be an input to its own hash. Canonicalize // the index meta and SW injected tag, then publish hashes of the final bytes. // All original bytes (including index/SW source) remain inputs via source hashes. - let canonicalIndex = source === null ? null : stampIndex(embedAssets(source, files, groups, '__BUILD_TAG__', hashing), files, { hashing }); + let canonicalIndex = source === null ? null : stampIndex(embedAssets(source, files, groups, '__BUILD_TAG__', hashing, assetSync), files, { hashing }); const canonical = { assetSync, files: { ...files }, groups, contracts }; if (canonicalIndex !== null && hashing) canonical.files['/index.html'] = { ...files['/index.html'], h: assetHash(canonicalIndex), s: Buffer.byteLength(canonicalIndex), source: files['/index.html'].h }; const buildTag = hashing ? tagHash(JSON.stringify(canonical)) : (override || legacy.digest('hex').slice(0, 12)); - const index = source === null ? null : embedAssets(stampIndex(source, files, { hashing, buildTag }), files, groups, buildTag, hashing); + const index = source === null ? null : embedAssets(stampIndex(source, files, { hashing, buildTag }), files, groups, buildTag, hashing, assetSync); const sw = swSource === null ? null : injectBuildTag(swSource, buildTag) .replace("typeof __ASSET_SYNC__ !== 'undefined' ? __ASSET_SYNC__ : true", JSON.stringify(assetSync)) .replace("importScripts('/asset-sync-core.js')", "importScripts('/asset-sync-core.js?v=" + (files['/asset-sync-core.js']?.h || '') + "')"); diff --git a/server/asset-manifest.test.js b/server/asset-manifest.test.js index ca3a58e..b71bbcc 100644 --- a/server/asset-manifest.test.js +++ b/server/asset-manifest.test.js @@ -88,3 +88,15 @@ test('index embeds build-local group hashes without recursively embedding index/ const legacy=JSON.parse(off.index.match(/id="ytp-assets">([^<]+)<\/script>/)[1]); expect(legacy.files['/app.js'].h).toBe(off.manifest.buildTag); })); + +test('app bootstrap CSP hash follows exact app bytes and rollback keeps external execution',()=>fixture(dir=>{ + writeFileSync(join(dir,'index.html'),''); + const result=createAssetManifest(dir),digest=createHash('sha256').update('window.app=1').digest('base64'); + expect(result.index).toContain("'sha256-"+digest+"'"); + + expect(JSON.parse(result.index.match(/id="ytp-assets">([^<]+)([^<]+)([^<]+) Date: Thu, 8 Oct 2026 09:06:40 +0800 Subject: [PATCH 48/81] Record cache reuse probes and reset each benchmark configuration --- perf/baseline.mjs | 3 + perf/results/phase6-handoff-mode.json | 3892 +++++++++++++++++++++++++ perf/results/phase6-owned-trial.json | 3736 ++++++++++++++++++++++++ plans/phase6-investigation.md | 25 + 4 files changed, 7656 insertions(+) create mode 100644 perf/results/phase6-handoff-mode.json create mode 100644 perf/results/phase6-owned-trial.json diff --git a/perf/baseline.mjs b/perf/baseline.mjs index 92190a2..b6321db 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -761,6 +761,9 @@ async function main() { results.browsers[bName] = {}; for (const prof of profiles) { + // The preceding profile can end on a synthetic feature-update tree. + // Always measure the actual base build on the next cold visit. + await server.restartWithPublic(treeBase); console.log(`\n>>> Running Benchmark: Browser=[${bName}] Profile=[${prof}]`); results.browsers[bName][prof] = {}; diff --git a/perf/results/phase6-handoff-mode.json b/perf/results/phase6-handoff-mode.json new file mode 100644 index 0000000..c17a4bb --- /dev/null +++ b/perf/results/phase6-handoff-mode.json @@ -0,0 +1,3892 @@ +{ + "date": "2026-10-08T00:50:44.941Z", + "frontendCommit": null, + "sourceRoot": null, + "sourceCommit": "799b1e7ed68fd5e55eb7faa9ed58ad633efbbbd2", + "frontendBuildTag": "90c8b7554b30", + "commit": "799b1e7ed68fd5e55eb7faa9ed58ad633efbbbd2", + "runsConfigured": 1, + "browsers": { + "webkit": { + "lte": { + "cold": { + "pageHandoff": [ + [ + { + "data": { + "type": "ASSET_LAYOUT_REQUEST" + }, + "own": "90c8b7554b30" + }, + { + "data": { + "type": "ASSET_DIAGNOSTIC", + "tag": "90c8b7554b30", + "pageCache": true, + "freshInstall": true, + "layoutKnown": true + }, + "own": "90c8b7554b30" + }, + "/app.js?v=f485286cbc", + "/asset-sync-core.js?v=b1b63f1b41", + "/assets.json?v=6f517e2aa4", + "/async-guard.js?v=e4afa1f2be", + "/audio-continuity.js?v=63b5464dd5", + "/device-db.js?v=880c5cd70e", + "/download-actions.css?v=12d3bcfe3e", + "/download-actions.js?v=388c7edecb", + "/download-errors.js?v=bb6a4c887a", + "/downloads-page.js?v=c1a3a218c0", + "/downloads.js?v=f2d3e7d212", + "/eq-parameters.js?v=dc2c6a8e8d", + "/feature-bootstrap.js?v=33779ecef7", + "/fingerprint.js?v=a635143269", + "/flag-ui.js?v=eeae1c1d1a", + "/fonts/BricolageGrotesque-latin-ext.woff2?v=776f6dcaf0", + "/fonts/BricolageGrotesque-latin.woff2?v=a79fdb52d4", + "/fonts/HankenGrotesk-latin-ext.woff2?v=768af2923e", + "/fonts/HankenGrotesk-latin.woff2?v=e9201eddf1", + "/fonts/JetBrainsMono-latin-ext.woff2?v=db5ff4db83", + "/fonts/JetBrainsMono-latin.woff2?v=83c005d49d", + "/fonts/fonts.css?v=dda3dfb804", + "/fullscreen-orientation.css?v=91f2d84453", + "/fullscreen-orientation.js?v=c8e44eb66b", + "/icons/icon-192.png?v=b48798bcd0", + "/icons/icon-512.png?v=f0a54dba90", + "/index.html?v=ae64b7c867", + "/layout-base.css?v=4f3307cd3b", + "/lazy.js?v=b22dd9be31", + "/loudness-wasm.js?v=c6102d7844", + "/loudness.js?v=01b3da88dd", + "/lyrics-core.js?v=4dcdac2edd", + "/lyrics-display.js?v=48e8550175", + "/manifest.webmanifest?v=096b294d57", + "/offline-pages.css?v=2889456261", + "/opfs-worker.js?v=17cfe8fb26", + "/opfs.js?v=df7a8d0391", + "/prewarm-next.js?v=ed16a51424", + "/recommendations.css?v=055101368d", + "/refresh.css?v=62498384f1", + "/related-videos.css?v=5a616b1be8", + "/related-videos.js?v=3eec0ebd4c", + "/resume-core.js?v=df42e94600", + "/saved-page.css?v=3ff576a784", + "/saved-page.js?v=f1518c50fb", + "/section-rail.js?v=07417c1bcc", + "/server-backfill.js?v=294b103023", + "/service-ui.css?v=b9bf96a3a8", + "/settings-sections.css?v=055507ab85", + "/settings-sections.js?v=1101425859", + "/sha256-wasm.js?v=393c50ba56", + "/sha256.js?v=cd9b980e6f", + "/shell-core.js?v=a04305c2ad", + "/styles.css?v=9f3a5dea41", + "/sw-update.js?v=772c123c20", + "/theme-classic.css?v=d420fcfb12", + "/views-core.js?v=49be16274c", + "/visible-timer.js?v=5322e86ef4" + ] + ], + "requestCount": { + "median": 159, + "min": 159, + "max": 159, + "values": [ + 159 + ] + }, + "wireBytes": { + "median": 1100519, + "min": 1100519, + "max": 1100519, + "values": [ + 1100519 + ] + }, + "fcp": { + "median": 1025, + "min": 1025, + "max": 1025, + "values": [ + 1025 + ] + }, + "lcp": { + "median": 1100, + "min": 1100, + "max": 1100, + "values": [ + 1100 + ] + }, + "domContentLoaded": { + "median": 3100, + "min": 3100, + "max": 3100, + "values": [ + 3100 + ] + }, + "bootDone": { + "median": 3106, + "min": 3106, + "max": 3106, + "values": [ + 3106 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "longTasks": [ + [] + ], + "swInstallDuration": { + "median": 32266, + "min": 32266, + "max": 32266, + "values": [ + 32266 + ] + }, + "swInstallBytes": { + "median": 1100519, + "min": 1100519, + "max": 1100519, + "values": [ + 1100519 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28176, + "js": 560109, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5078, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:5254/?v=benchmedia01", + "status": 200, + "bytes": 14088, + "index": 1, + "startMs": 19, + "headersMs": 234, + "endMs": 306 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 314, + "headersMs": 469, + "endMs": 644 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 313, + "headersMs": 470, + "endMs": 853 + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 315, + "headersMs": 488, + "endMs": 509 + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "status": 200, + "bytes": 3484, + "index": 5, + "startMs": 315, + "headersMs": 497, + "endMs": 515 + }, + { + "url": "http://127.0.0.1:5254/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 315, + "headersMs": 501, + "endMs": 503 + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 316, + "headersMs": 675, + "endMs": 841 + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 516, + "headersMs": 677, + "endMs": 678 + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 509, + "headersMs": 711, + "endMs": 742 + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 504, + "headersMs": 731, + "endMs": 755 + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 644, + "headersMs": 801, + "endMs": 805 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 679, + "headersMs": 836, + "endMs": 841 + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 743, + "headersMs": 899, + "endMs": 904 + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 756, + "headersMs": 910, + "endMs": 913 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 806, + "headersMs": 965, + "endMs": 974 + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 842, + "headersMs": 995, + "endMs": 999 + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 842, + "headersMs": 997, + "endMs": 1000 + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 853, + "headersMs": 1010, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 906, + "headersMs": 1074, + "endMs": 1097 + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 914, + "headersMs": 1084, + "endMs": 1099 + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 975, + "headersMs": 1128, + "endMs": 1132 + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1000, + "headersMs": 1158, + "endMs": 1171 + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1001, + "headersMs": 1163, + "endMs": 1172 + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1017, + "headersMs": 1177, + "endMs": 1194 + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1098, + "headersMs": 1254, + "endMs": 1260 + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1099, + "headersMs": 1259, + "endMs": 1271 + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1133, + "headersMs": 1288, + "endMs": 1294 + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1172, + "headersMs": 1326, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 29, + "startMs": 1173, + "headersMs": 1333, + "endMs": 1345 + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1195, + "headersMs": 1361, + "endMs": 1387 + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1260, + "headersMs": 1415, + "endMs": 1419 + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1272, + "headersMs": 1427, + "endMs": 1431 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1294, + "headersMs": 1455, + "endMs": 1470 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1331, + "headersMs": 1492, + "endMs": 1508 + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1345, + "headersMs": 1500, + "endMs": 1504 + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1388, + "headersMs": 1543, + "endMs": 1547 + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1420, + "headersMs": 1578, + "endMs": 1588 + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1432, + "headersMs": 1599, + "endMs": 1617 + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1471, + "headersMs": 1624, + "endMs": 1629 + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1505, + "headersMs": 1659, + "endMs": 1665 + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1509, + "headersMs": 1661, + "endMs": 1664 + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1547, + "headersMs": 1703, + "endMs": 1708 + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1589, + "headersMs": 1744, + "endMs": 1748 + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1618, + "headersMs": 1777, + "endMs": 1790 + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1629, + "headersMs": 1795, + "endMs": 1817 + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1665, + "headersMs": 1891, + "endMs": 1988 + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1666, + "headersMs": 1903, + "endMs": 1925 + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1709, + "headersMs": 2449, + "cacheHeaders": { + "request": { + "accept": "*/*", + "referer": "http://127.0.0.1:5254/?v=benchmedia01", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15", + "accept-encoding": "gzip, deflate", + "accept-language": "en-US", + "connection": "Keep-Alive", + "host": "127.0.0.1:5254", + "sec-fetch-dest": "script", + "sec-fetch-mode": "no-cors", + "sec-fetch-site": "same-origin" + }, + "response": { + "content-type": "text/javascript; charset=utf-8", + "cache-control": "public, max-age=31536000, immutable", + "etag": "\"f485286cbcd8767a8c4f9a25a18b8982\"", + "vary": "Accept-Encoding", + "content-encoding": "gzip", + "x-asset-hash": "f485286cbc", + "date": "Thu, 08 Oct 2026 00:50:46 GMT", + "content-length": "118521" + } + }, + "endMs": 3044 + }, + { + "url": "http://127.0.0.1:5254/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1748, + "headersMs": 2457, + "endMs": 2461 + }, + { + "url": "http://127.0.0.1:5254/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3087, + "headersMs": 3241, + "endMs": 3242 + }, + { + "url": "http://127.0.0.1:5254/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3104, + "headersMs": 3255, + "endMs": 3257 + }, + { + "url": "http://127.0.0.1:5254/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3106, + "headersMs": 3263, + "endMs": 3265 + }, + { + "url": "http://127.0.0.1:5254/sw.js", + "status": 200, + "bytes": 9447, + "index": 53, + "startMs": 3110, + "headersMs": 3299, + "endMs": 3349 + }, + { + "url": "http://127.0.0.1:5254/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3268, + "headersMs": 3420, + "endMs": 3420 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 55, + "startMs": 3359, + "headersMs": 3511, + "endMs": 3522 + }, + { + "url": "http://127.0.0.1:5254/api/manifest", + "status": 200, + "bytes": 3737, + "index": 56, + "startMs": 3527, + "headersMs": 3693, + "endMs": 3713 + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3738, + "headersMs": 3893, + "cacheHeaders": { + "request": { + "referer": "http://127.0.0.1:5254/?v=benchmedia01", + "accept": "*/*", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15", + "accept-encoding": "gzip, deflate", + "accept-language": "en-US", + "connection": "Keep-Alive", + "host": "127.0.0.1:5254", + "sec-fetch-dest": "empty", + "sec-fetch-mode": "no-cors", + "sec-fetch-site": "same-origin" + }, + "response": { + "content-type": "text/javascript; charset=utf-8", + "cache-control": "public, max-age=31536000, immutable", + "etag": "\"f485286cbcd8767a8c4f9a25a18b8982\"", + "vary": "Accept-Encoding", + "content-encoding": "gzip", + "x-asset-hash": "f485286cbc", + "date": "Thu, 08 Oct 2026 00:50:48 GMT", + "content-length": "118521" + } + }, + "endMs": 4490 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 58, + "startMs": 3738, + "headersMs": 3893, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3738, + "headersMs": 3900, + "endMs": 3906 + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3738, + "headersMs": 3901, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3739, + "headersMs": 3901, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3739, + "headersMs": 3901, + "endMs": 3906 + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3914, + "headersMs": 4065, + "endMs": 4069 + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4069 + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4070 + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4084 + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4076 + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4075, + "headersMs": 4227, + "endMs": 4232 + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4075, + "headersMs": 4228, + "endMs": 4240 + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4075, + "headersMs": 4228, + "endMs": 4234 + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4080, + "headersMs": 4231, + "endMs": 4243 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4088, + "headersMs": 4238, + "endMs": 4391 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4237, + "headersMs": 4391, + "endMs": 4774 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4238, + "headersMs": 4391, + "endMs": 4489 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4244, + "headersMs": 4397, + "endMs": 4571 + }, + { + "url": "http://127.0.0.1:5254/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4246, + "headersMs": 4398, + "endMs": 4457 + }, + { + "url": "http://127.0.0.1:5254/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4396, + "headersMs": 4549, + "endMs": 4707 + }, + { + "url": "http://127.0.0.1:5254/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4461, + "headersMs": 4612, + "endMs": 4615 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4496, + "headersMs": 4647, + "endMs": 4656 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4498, + "headersMs": 4648, + "endMs": 4662 + }, + { + "url": "http://127.0.0.1:5254/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4576, + "headersMs": 4726, + "endMs": 4735 + }, + { + "url": "http://127.0.0.1:5254/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4619, + "headersMs": 4772, + "endMs": 3919 + }, + { + "url": "http://127.0.0.1:5254/index.html?v=ae64b7c867", + "status": 200, + "bytes": 14088, + "index": 83, + "startMs": 4663, + "headersMs": 3938, + "endMs": 4008 + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4665, + "headersMs": 3940, + "endMs": 3941 + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "status": 200, + "bytes": 3484, + "index": 85, + "startMs": 4712, + "headersMs": 3990, + "endMs": 4008 + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4739, + "headersMs": 4013, + "endMs": 4019 + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4778, + "headersMs": 4054, + "endMs": 4064 + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 3923, + "headersMs": 4075, + "endMs": 4091 + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 3945, + "headersMs": 4096, + "endMs": 4099 + }, + { + "url": "http://127.0.0.1:5254/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4012, + "headersMs": 4164, + "endMs": 4166 + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4013, + "headersMs": 4164, + "endMs": 4170 + }, + { + "url": "http://127.0.0.1:5254/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4023, + "headersMs": 4187, + "endMs": 4207 + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4069, + "headersMs": 4219, + "endMs": 4243 + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4095, + "headersMs": 4246, + "endMs": 4250 + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4103, + "headersMs": 4254, + "endMs": 4259 + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4171, + "headersMs": 4324, + "endMs": 4353 + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 4173, + "headersMs": 4324, + "endMs": 4326 + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 4211, + "headersMs": 4362, + "endMs": 4366 + }, + { + "url": "http://127.0.0.1:5254/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 4248, + "headersMs": 4402, + "endMs": 4405 + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 4254, + "headersMs": 4405, + "endMs": 4409 + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 4262, + "headersMs": 4413, + "endMs": 4418 + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 4330, + "headersMs": 4483, + "endMs": 4505 + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 4358, + "headersMs": 4509, + "endMs": 4514 + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 4369, + "headersMs": 4520, + "endMs": 4543 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 4409, + "headersMs": 4561, + "endMs": 4566 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 4413, + "headersMs": 4563, + "endMs": 4577 + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 4421, + "headersMs": 4573, + "endMs": 4581 + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 4509, + "headersMs": 4661, + "endMs": 4677 + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 4518, + "headersMs": 4670, + "endMs": 4693 + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 4547, + "headersMs": 4699, + "endMs": 4867 + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 4573, + "headersMs": 4724, + "endMs": 4750 + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 4581, + "headersMs": 4732, + "endMs": 4753 + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 4584, + "headersMs": 4735, + "endMs": 4832 + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 4680, + "headersMs": 4832, + "endMs": 4834 + }, + { + "url": "http://127.0.0.1:5254/sw.js", + "status": 200, + "bytes": 9447, + "index": 115, + "startMs": 4878, + "headersMs": 5031, + "endMs": 5079 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 116, + "startMs": 5081, + "headersMs": 5233, + "endMs": 5245 + }, + { + "url": "http://127.0.0.1:5254/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 5909, + "headersMs": 6065, + "endMs": 6073 + }, + { + "url": "http://127.0.0.1:5254/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 5909, + "headersMs": 6067, + "endMs": 6069 + }, + { + "url": "http://127.0.0.1:5254/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 5909, + "headersMs": 6073, + "endMs": 6084 + }, + { + "url": "http://127.0.0.1:5254/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 5909, + "headersMs": 6074, + "endMs": 6075 + }, + { + "url": "http://127.0.0.1:5254/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 5909, + "headersMs": 6087, + "endMs": 6108 + }, + { + "url": "http://127.0.0.1:5254/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 5909, + "headersMs": 6090, + "endMs": 6097 + }, + { + "url": "http://127.0.0.1:5254/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6072, + "headersMs": 6227, + "endMs": 6234 + }, + { + "url": "http://127.0.0.1:5254/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6075, + "headersMs": 6232, + "endMs": 6239 + }, + { + "url": "http://127.0.0.1:5254/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6077, + "headersMs": 6234, + "endMs": 6239 + }, + { + "url": "http://127.0.0.1:5254/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6086, + "headersMs": 6242, + "endMs": 6250 + }, + { + "url": "http://127.0.0.1:5254/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6099, + "headersMs": 6263, + "endMs": 6287 + }, + { + "url": "http://127.0.0.1:5254/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6110, + "headersMs": 6263, + "endMs": 6373 + }, + { + "url": "http://127.0.0.1:5254/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 6236, + "headersMs": 6387, + "endMs": 6524 + }, + { + "url": "http://127.0.0.1:5254/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 6241, + "headersMs": 6403, + "endMs": 6420 + }, + { + "url": "http://127.0.0.1:5254/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 6241, + "headersMs": 6407, + "endMs": 6413 + }, + { + "url": "http://127.0.0.1:5254/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 6252, + "headersMs": 6409, + "endMs": 6413 + }, + { + "url": "http://127.0.0.1:5254/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 6289, + "headersMs": 6443, + "endMs": 6445 + }, + { + "url": "http://127.0.0.1:5254/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 6375, + "headersMs": 6530, + "endMs": 6535 + }, + { + "url": "http://127.0.0.1:5254/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 6415, + "headersMs": 6574, + "endMs": 6587 + }, + { + "url": "http://127.0.0.1:5254/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 6415, + "headersMs": 6581, + "endMs": 6592 + }, + { + "url": "http://127.0.0.1:5254/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 6422, + "headersMs": 6596, + "endMs": 6619 + }, + { + "url": "http://127.0.0.1:5254/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 6447, + "headersMs": 6603, + "endMs": 6609 + }, + { + "url": "http://127.0.0.1:5254/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 6527, + "headersMs": 6682, + "endMs": 6690 + }, + { + "url": "http://127.0.0.1:5254/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 6537, + "headersMs": 6698, + "endMs": 6712 + }, + { + "url": "http://127.0.0.1:5254/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 6590, + "headersMs": 6747, + "endMs": 6754 + }, + { + "url": "http://127.0.0.1:5254/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 6594, + "headersMs": 6750, + "endMs": 6755 + }, + { + "url": "http://127.0.0.1:5254/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 6611, + "headersMs": 6762, + "endMs": 6774 + }, + { + "url": "http://127.0.0.1:5254/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 6622, + "headersMs": 6788, + "endMs": 6808 + }, + { + "url": "http://127.0.0.1:5254/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 6692, + "headersMs": 6853, + "endMs": 6870 + }, + { + "url": "http://127.0.0.1:5254/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 6714, + "headersMs": 6896, + "endMs": 6942 + }, + { + "url": "http://127.0.0.1:5254/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 6756, + "headersMs": 6916, + "endMs": 6930 + }, + { + "url": "http://127.0.0.1:5254/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 6757, + "headersMs": 6929, + "endMs": 6949 + }, + { + "url": "http://127.0.0.1:5254/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 6776, + "headersMs": 6940, + "endMs": 6953 + }, + { + "url": "http://127.0.0.1:5254/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 6810, + "headersMs": 6969, + "endMs": 6981 + }, + { + "url": "http://127.0.0.1:5254/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 6872, + "headersMs": 7069, + "endMs": 7108 + }, + { + "url": "http://127.0.0.1:5254/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 6932, + "headersMs": 7110, + "endMs": 7137 + }, + { + "url": "http://127.0.0.1:5254/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 6945, + "headersMs": 7117, + "endMs": 7125 + }, + { + "url": "http://127.0.0.1:5254/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 6951, + "headersMs": 7124, + "endMs": 7130 + }, + { + "url": "http://127.0.0.1:5254/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 6954, + "headersMs": 7155, + "endMs": 7185 + }, + { + "url": "http://127.0.0.1:5254/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 6983, + "headersMs": 7379, + "endMs": 7604 + }, + { + "url": "http://127.0.0.1:5254/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7111, + "headersMs": 7389, + "endMs": 7402 + }, + { + "url": "http://127.0.0.1:5254/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7127, + "headersMs": 7394, + "endMs": 7401 + }, + { + "url": "http://127.0.0.1:5254/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7131, + "headersMs": 7417, + "endMs": 7454 + } + ], + "initialJsCss": { + "median": 256053, + "min": 256053, + "max": 256053, + "values": [ + 256053 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:5254/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 310, + "responseStart": 499, + "end": 500, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 310, + "responseStart": 505, + "end": 506, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "bytes": 3484, + "start": 310, + "responseStart": 512, + "end": 512, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 310, + "responseStart": 738, + "end": 739, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 310, + "responseStart": 751, + "end": 752, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 310, + "responseStart": 835, + "end": 838, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 311, + "responseStart": 675, + "end": 675, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "bytes": 983, + "start": 311, + "responseStart": 802, + "end": 802, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 311, + "responseStart": 838, + "end": 838, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 311, + "responseStart": 901, + "end": 902, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 311, + "responseStart": 910, + "end": 910, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 311, + "responseStart": 971, + "end": 971, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 311, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 311, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 312, + "responseStart": 1013, + "end": 1013, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 312, + "responseStart": 1093, + "end": 1094, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 312, + "responseStart": 1095, + "end": 1096, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 312, + "responseStart": 1129, + "end": 1129, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 312, + "responseStart": 1168, + "end": 1168, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 313, + "responseStart": 1169, + "end": 1169, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 313, + "responseStart": 1191, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 313, + "responseStart": 1256, + "end": 1257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 313, + "responseStart": 1267, + "end": 1269, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 313, + "responseStart": 1290, + "end": 1291, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 313, + "responseStart": 1327, + "end": 1327, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "bytes": 2344, + "start": 313, + "responseStart": 1341, + "end": 1342, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 313, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 313, + "responseStart": 1415, + "end": 1416, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 314, + "responseStart": 1428, + "end": 1428, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 314, + "responseStart": 1467, + "end": 1467, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 314, + "responseStart": 1500, + "end": 1501, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 314, + "responseStart": 1505, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 314, + "responseStart": 1543, + "end": 1544, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 314, + "responseStart": 1585, + "end": 1586, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 314, + "responseStart": 1614, + "end": 1615, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 314, + "responseStart": 1625, + "end": 1626, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 315, + "responseStart": 1661, + "end": 1661, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 315, + "responseStart": 1662, + "end": 1662, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 315, + "responseStart": 1704, + "end": 1705, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 315, + "responseStart": 1744, + "end": 1745, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 315, + "responseStart": 1787, + "end": 1787, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 315, + "responseStart": 1814, + "end": 1814, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 315, + "responseStart": 1921, + "end": 1922, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 315, + "responseStart": 1985, + "end": 1985, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "bytes": 118521, + "start": 315, + "responseStart": 2772, + "end": 3041, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1025, + "requests": [ + { + "url": "http://127.0.0.1:5254/?v=benchmedia01", + "status": 200, + "bytes": 14088, + "index": 1, + "startMs": 19, + "headersMs": 234, + "endMs": 306 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 314, + "headersMs": 469, + "endMs": 644 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 313, + "headersMs": 470, + "endMs": 853 + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 315, + "headersMs": 488, + "endMs": 509 + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "status": 200, + "bytes": 3484, + "index": 5, + "startMs": 315, + "headersMs": 497, + "endMs": 515 + }, + { + "url": "http://127.0.0.1:5254/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 315, + "headersMs": 501, + "endMs": 503 + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 316, + "headersMs": 675, + "endMs": 841 + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 516, + "headersMs": 677, + "endMs": 678 + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 509, + "headersMs": 711, + "endMs": 742 + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 504, + "headersMs": 731, + "endMs": 755 + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 644, + "headersMs": 801, + "endMs": 805 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 679, + "headersMs": 836, + "endMs": 841 + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 743, + "headersMs": 899, + "endMs": 904 + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 756, + "headersMs": 910, + "endMs": 913 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 806, + "headersMs": 965, + "endMs": 974 + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 842, + "headersMs": 995, + "endMs": 999 + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 842, + "headersMs": 997, + "endMs": 1000 + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 853, + "headersMs": 1010, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 906, + "headersMs": 1074, + "endMs": 1097 + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 914, + "headersMs": 1084, + "endMs": 1099 + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 975, + "headersMs": 1128, + "endMs": 1132 + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1000, + "headersMs": 1158, + "endMs": 1171 + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1001, + "headersMs": 1163, + "endMs": 1172 + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1017, + "headersMs": 1177, + "endMs": 1194 + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1098, + "headersMs": 1254, + "endMs": 1260 + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1099, + "headersMs": 1259, + "endMs": 1271 + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1133, + "headersMs": 1288, + "endMs": 1294 + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1172, + "headersMs": 1326, + "endMs": 1330 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 29, + "startMs": 1173, + "headersMs": 1333, + "endMs": 1345 + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1195, + "headersMs": 1361, + "endMs": 1387 + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1260, + "headersMs": 1415, + "endMs": 1419 + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1272, + "headersMs": 1427, + "endMs": 1431 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1294, + "headersMs": 1455, + "endMs": 1470 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1331, + "headersMs": 1492, + "endMs": 1508 + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1345, + "headersMs": 1500, + "endMs": 1504 + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1388, + "headersMs": 1543, + "endMs": 1547 + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1420, + "headersMs": 1578, + "endMs": 1588 + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1432, + "headersMs": 1599, + "endMs": 1617 + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1471, + "headersMs": 1624, + "endMs": 1629 + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1505, + "headersMs": 1659, + "endMs": 1665 + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1509, + "headersMs": 1661, + "endMs": 1664 + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1547, + "headersMs": 1703, + "endMs": 1708 + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1589, + "headersMs": 1744, + "endMs": 1748 + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1618, + "headersMs": 1777, + "endMs": 1790 + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1629, + "headersMs": 1795, + "endMs": 1817 + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1665, + "headersMs": 1891, + "endMs": 1988 + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1666, + "headersMs": 1903, + "endMs": 1925 + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 48, + "startMs": 1709, + "headersMs": 2449, + "cacheHeaders": { + "request": { + "accept": "*/*", + "referer": "http://127.0.0.1:5254/?v=benchmedia01", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15", + "accept-encoding": "gzip, deflate", + "accept-language": "en-US", + "connection": "Keep-Alive", + "host": "127.0.0.1:5254", + "sec-fetch-dest": "script", + "sec-fetch-mode": "no-cors", + "sec-fetch-site": "same-origin" + }, + "response": { + "content-type": "text/javascript; charset=utf-8", + "cache-control": "public, max-age=31536000, immutable", + "etag": "\"f485286cbcd8767a8c4f9a25a18b8982\"", + "vary": "Accept-Encoding", + "content-encoding": "gzip", + "x-asset-hash": "f485286cbc", + "date": "Thu, 08 Oct 2026 00:50:46 GMT", + "content-length": "118521" + } + }, + "endMs": 3044 + }, + { + "url": "http://127.0.0.1:5254/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 49, + "startMs": 1748, + "headersMs": 2457, + "endMs": 2461 + }, + { + "url": "http://127.0.0.1:5254/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 50, + "startMs": 3087, + "headersMs": 3241, + "endMs": 3242 + }, + { + "url": "http://127.0.0.1:5254/api/version", + "status": 200, + "bytes": 62, + "index": 51, + "startMs": 3104, + "headersMs": 3255, + "endMs": 3257 + }, + { + "url": "http://127.0.0.1:5254/api/user/sync", + "status": 200, + "bytes": 11, + "index": 52, + "startMs": 3106, + "headersMs": 3263, + "endMs": 3265 + }, + { + "url": "http://127.0.0.1:5254/sw.js", + "status": 200, + "bytes": 9447, + "index": 53, + "startMs": 3110, + "headersMs": 3299, + "endMs": 3349 + }, + { + "url": "http://127.0.0.1:5254/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 54, + "startMs": 3268, + "headersMs": 3420, + "endMs": 3420 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 55, + "startMs": 3359, + "headersMs": 3511, + "endMs": 3522 + }, + { + "url": "http://127.0.0.1:5254/api/manifest", + "status": 200, + "bytes": 3737, + "index": 56, + "startMs": 3527, + "headersMs": 3693, + "endMs": 3713 + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 57, + "startMs": 3738, + "headersMs": 3893, + "cacheHeaders": { + "request": { + "referer": "http://127.0.0.1:5254/?v=benchmedia01", + "accept": "*/*", + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.5 Safari/605.1.15", + "accept-encoding": "gzip, deflate", + "accept-language": "en-US", + "connection": "Keep-Alive", + "host": "127.0.0.1:5254", + "sec-fetch-dest": "empty", + "sec-fetch-mode": "no-cors", + "sec-fetch-site": "same-origin" + }, + "response": { + "content-type": "text/javascript; charset=utf-8", + "cache-control": "public, max-age=31536000, immutable", + "etag": "\"f485286cbcd8767a8c4f9a25a18b8982\"", + "vary": "Accept-Encoding", + "content-encoding": "gzip", + "x-asset-hash": "f485286cbc", + "date": "Thu, 08 Oct 2026 00:50:48 GMT", + "content-length": "118521" + } + }, + "endMs": 4490 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 58, + "startMs": 3738, + "headersMs": 3893, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/assets.json?v=6f517e2aa4", + "status": 200, + "bytes": 1220, + "index": 59, + "startMs": 3738, + "headersMs": 3900, + "endMs": 3906 + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 60, + "startMs": 3738, + "headersMs": 3901, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 61, + "startMs": 3739, + "headersMs": 3901, + "endMs": 3904 + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 62, + "startMs": 3739, + "headersMs": 3901, + "endMs": 3906 + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 63, + "startMs": 3914, + "headersMs": 4065, + "endMs": 4069 + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 64, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4069 + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 65, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4070 + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 66, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4084 + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 67, + "startMs": 3914, + "headersMs": 4066, + "endMs": 4076 + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 68, + "startMs": 4075, + "headersMs": 4227, + "endMs": 4232 + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 69, + "startMs": 4075, + "headersMs": 4228, + "endMs": 4240 + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 70, + "startMs": 4075, + "headersMs": 4228, + "endMs": 4234 + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 71, + "startMs": 4080, + "headersMs": 4231, + "endMs": 4243 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 72, + "startMs": 4088, + "headersMs": 4238, + "endMs": 4391 + }, + { + "url": "http://127.0.0.1:5254/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 73, + "startMs": 4237, + "headersMs": 4391, + "endMs": 4774 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 74, + "startMs": 4238, + "headersMs": 4391, + "endMs": 4489 + }, + { + "url": "http://127.0.0.1:5254/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 75, + "startMs": 4244, + "headersMs": 4397, + "endMs": 4571 + }, + { + "url": "http://127.0.0.1:5254/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 76, + "startMs": 4246, + "headersMs": 4398, + "endMs": 4457 + }, + { + "url": "http://127.0.0.1:5254/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 77, + "startMs": 4396, + "headersMs": 4549, + "endMs": 4707 + }, + { + "url": "http://127.0.0.1:5254/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 78, + "startMs": 4461, + "headersMs": 4612, + "endMs": 4615 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 79, + "startMs": 4496, + "headersMs": 4647, + "endMs": 4656 + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 80, + "startMs": 4498, + "headersMs": 4648, + "endMs": 4662 + }, + { + "url": "http://127.0.0.1:5254/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 81, + "startMs": 4576, + "headersMs": 4726, + "endMs": 4735 + }, + { + "url": "http://127.0.0.1:5254/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 82, + "startMs": 4619, + "headersMs": 4772, + "endMs": 3919 + }, + { + "url": "http://127.0.0.1:5254/index.html?v=ae64b7c867", + "status": 200, + "bytes": 14088, + "index": 83, + "startMs": 4663, + "headersMs": 3938, + "endMs": 4008 + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 84, + "startMs": 4665, + "headersMs": 3940, + "endMs": 3941 + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "status": 200, + "bytes": 3484, + "index": 85, + "startMs": 4712, + "headersMs": 3990, + "endMs": 4008 + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 86, + "startMs": 4739, + "headersMs": 4013, + "endMs": 4019 + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 87, + "startMs": 4778, + "headersMs": 4054, + "endMs": 4064 + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 88, + "startMs": 3923, + "headersMs": 4075, + "endMs": 4091 + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 89, + "startMs": 3945, + "headersMs": 4096, + "endMs": 4099 + }, + { + "url": "http://127.0.0.1:5254/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 90, + "startMs": 4012, + "headersMs": 4164, + "endMs": 4166 + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 91, + "startMs": 4013, + "headersMs": 4164, + "endMs": 4170 + }, + { + "url": "http://127.0.0.1:5254/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 92, + "startMs": 4023, + "headersMs": 4187, + "endMs": 4207 + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 93, + "startMs": 4069, + "headersMs": 4219, + "endMs": 4243 + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 94, + "startMs": 4095, + "headersMs": 4246, + "endMs": 4250 + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 95, + "startMs": 4103, + "headersMs": 4254, + "endMs": 4259 + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 96, + "startMs": 4171, + "headersMs": 4324, + "endMs": 4353 + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 97, + "startMs": 4173, + "headersMs": 4324, + "endMs": 4326 + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 98, + "startMs": 4211, + "headersMs": 4362, + "endMs": 4366 + }, + { + "url": "http://127.0.0.1:5254/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 99, + "startMs": 4248, + "headersMs": 4402, + "endMs": 4405 + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 100, + "startMs": 4254, + "headersMs": 4405, + "endMs": 4409 + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 101, + "startMs": 4262, + "headersMs": 4413, + "endMs": 4418 + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 102, + "startMs": 4330, + "headersMs": 4483, + "endMs": 4505 + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 103, + "startMs": 4358, + "headersMs": 4509, + "endMs": 4514 + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 104, + "startMs": 4369, + "headersMs": 4520, + "endMs": 4543 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 105, + "startMs": 4409, + "headersMs": 4561, + "endMs": 4566 + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 106, + "startMs": 4413, + "headersMs": 4563, + "endMs": 4577 + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 107, + "startMs": 4421, + "headersMs": 4573, + "endMs": 4581 + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 108, + "startMs": 4509, + "headersMs": 4661, + "endMs": 4677 + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 109, + "startMs": 4518, + "headersMs": 4670, + "endMs": 4693 + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 110, + "startMs": 4547, + "headersMs": 4699, + "endMs": 4867 + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 111, + "startMs": 4573, + "headersMs": 4724, + "endMs": 4750 + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 112, + "startMs": 4581, + "headersMs": 4732, + "endMs": 4753 + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 113, + "startMs": 4584, + "headersMs": 4735, + "endMs": 4832 + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 114, + "startMs": 4680, + "headersMs": 4832, + "endMs": 4834 + }, + { + "url": "http://127.0.0.1:5254/sw.js", + "status": 200, + "bytes": 9447, + "index": 115, + "startMs": 4878, + "headersMs": 5031, + "endMs": 5079 + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "status": 200, + "bytes": 2344, + "index": 116, + "startMs": 5081, + "headersMs": 5233, + "endMs": 5245 + }, + { + "url": "http://127.0.0.1:5254/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 117, + "startMs": 5909, + "headersMs": 6065, + "endMs": 6073 + }, + { + "url": "http://127.0.0.1:5254/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 118, + "startMs": 5909, + "headersMs": 6067, + "endMs": 6069 + }, + { + "url": "http://127.0.0.1:5254/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 119, + "startMs": 5909, + "headersMs": 6073, + "endMs": 6084 + }, + { + "url": "http://127.0.0.1:5254/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 120, + "startMs": 5909, + "headersMs": 6074, + "endMs": 6075 + }, + { + "url": "http://127.0.0.1:5254/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 121, + "startMs": 5909, + "headersMs": 6087, + "endMs": 6108 + }, + { + "url": "http://127.0.0.1:5254/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 122, + "startMs": 5909, + "headersMs": 6090, + "endMs": 6097 + }, + { + "url": "http://127.0.0.1:5254/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 123, + "startMs": 6072, + "headersMs": 6227, + "endMs": 6234 + }, + { + "url": "http://127.0.0.1:5254/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 124, + "startMs": 6075, + "headersMs": 6232, + "endMs": 6239 + }, + { + "url": "http://127.0.0.1:5254/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 125, + "startMs": 6077, + "headersMs": 6234, + "endMs": 6239 + }, + { + "url": "http://127.0.0.1:5254/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 126, + "startMs": 6086, + "headersMs": 6242, + "endMs": 6250 + }, + { + "url": "http://127.0.0.1:5254/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 127, + "startMs": 6099, + "headersMs": 6263, + "endMs": 6287 + }, + { + "url": "http://127.0.0.1:5254/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 128, + "startMs": 6110, + "headersMs": 6263, + "endMs": 6373 + }, + { + "url": "http://127.0.0.1:5254/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 129, + "startMs": 6236, + "headersMs": 6387, + "endMs": 6524 + }, + { + "url": "http://127.0.0.1:5254/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 130, + "startMs": 6241, + "headersMs": 6403, + "endMs": 6420 + }, + { + "url": "http://127.0.0.1:5254/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 131, + "startMs": 6241, + "headersMs": 6407, + "endMs": 6413 + }, + { + "url": "http://127.0.0.1:5254/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 132, + "startMs": 6252, + "headersMs": 6409, + "endMs": 6413 + }, + { + "url": "http://127.0.0.1:5254/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 133, + "startMs": 6289, + "headersMs": 6443, + "endMs": 6445 + }, + { + "url": "http://127.0.0.1:5254/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 134, + "startMs": 6375, + "headersMs": 6530, + "endMs": 6535 + }, + { + "url": "http://127.0.0.1:5254/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 135, + "startMs": 6415, + "headersMs": 6574, + "endMs": 6587 + }, + { + "url": "http://127.0.0.1:5254/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 136, + "startMs": 6415, + "headersMs": 6581, + "endMs": 6592 + }, + { + "url": "http://127.0.0.1:5254/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 137, + "startMs": 6422, + "headersMs": 6596, + "endMs": 6619 + }, + { + "url": "http://127.0.0.1:5254/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 138, + "startMs": 6447, + "headersMs": 6603, + "endMs": 6609 + }, + { + "url": "http://127.0.0.1:5254/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 139, + "startMs": 6527, + "headersMs": 6682, + "endMs": 6690 + }, + { + "url": "http://127.0.0.1:5254/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 140, + "startMs": 6537, + "headersMs": 6698, + "endMs": 6712 + }, + { + "url": "http://127.0.0.1:5254/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 141, + "startMs": 6590, + "headersMs": 6747, + "endMs": 6754 + }, + { + "url": "http://127.0.0.1:5254/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 142, + "startMs": 6594, + "headersMs": 6750, + "endMs": 6755 + }, + { + "url": "http://127.0.0.1:5254/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 143, + "startMs": 6611, + "headersMs": 6762, + "endMs": 6774 + }, + { + "url": "http://127.0.0.1:5254/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 144, + "startMs": 6622, + "headersMs": 6788, + "endMs": 6808 + }, + { + "url": "http://127.0.0.1:5254/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 145, + "startMs": 6692, + "headersMs": 6853, + "endMs": 6870 + }, + { + "url": "http://127.0.0.1:5254/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 146, + "startMs": 6714, + "headersMs": 6896, + "endMs": 6942 + }, + { + "url": "http://127.0.0.1:5254/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 147, + "startMs": 6756, + "headersMs": 6916, + "endMs": 6930 + }, + { + "url": "http://127.0.0.1:5254/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 148, + "startMs": 6757, + "headersMs": 6929, + "endMs": 6949 + }, + { + "url": "http://127.0.0.1:5254/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 149, + "startMs": 6776, + "headersMs": 6940, + "endMs": 6953 + }, + { + "url": "http://127.0.0.1:5254/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 150, + "startMs": 6810, + "headersMs": 6969, + "endMs": 6981 + }, + { + "url": "http://127.0.0.1:5254/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 151, + "startMs": 6872, + "headersMs": 7069, + "endMs": 7108 + }, + { + "url": "http://127.0.0.1:5254/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 152, + "startMs": 6932, + "headersMs": 7110, + "endMs": 7137 + }, + { + "url": "http://127.0.0.1:5254/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 153, + "startMs": 6945, + "headersMs": 7117, + "endMs": 7125 + }, + { + "url": "http://127.0.0.1:5254/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 154, + "startMs": 6951, + "headersMs": 7124, + "endMs": 7130 + }, + { + "url": "http://127.0.0.1:5254/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 155, + "startMs": 6954, + "headersMs": 7155, + "endMs": 7185 + }, + { + "url": "http://127.0.0.1:5254/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 156, + "startMs": 6983, + "headersMs": 7379, + "endMs": 7604 + }, + { + "url": "http://127.0.0.1:5254/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 157, + "startMs": 7111, + "headersMs": 7389, + "endMs": 7402 + }, + { + "url": "http://127.0.0.1:5254/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 158, + "startMs": 7127, + "headersMs": 7394, + "endMs": 7401 + }, + { + "url": "http://127.0.0.1:5254/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 159, + "startMs": 7131, + "headersMs": 7417, + "endMs": 7454 + } + ], + "page": [ + { + "url": "http://127.0.0.1:5254/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 310, + "responseStart": 499, + "end": 500, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 310, + "responseStart": 505, + "end": 506, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/lazy.js?v=b22dd9be31", + "bytes": 3484, + "start": 310, + "responseStart": 512, + "end": 512, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 310, + "responseStart": 738, + "end": 739, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 310, + "responseStart": 751, + "end": 752, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 310, + "responseStart": 835, + "end": 838, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 311, + "responseStart": 675, + "end": 675, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/recommendations.css?v=055101368d", + "bytes": 983, + "start": 311, + "responseStart": 802, + "end": 802, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 311, + "responseStart": 838, + "end": 838, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 311, + "responseStart": 901, + "end": 902, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 311, + "responseStart": 910, + "end": 910, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 311, + "responseStart": 971, + "end": 971, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 311, + "responseStart": 995, + "end": 996, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 311, + "responseStart": 997, + "end": 997, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:5254/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 312, + "responseStart": 1013, + "end": 1013, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 312, + "responseStart": 1093, + "end": 1094, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 312, + "responseStart": 1095, + "end": 1096, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 312, + "responseStart": 1129, + "end": 1129, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 312, + "responseStart": 1168, + "end": 1168, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 313, + "responseStart": 1169, + "end": 1169, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 313, + "responseStart": 1191, + "end": 1191, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 313, + "responseStart": 1256, + "end": 1257, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 313, + "responseStart": 1267, + "end": 1269, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 313, + "responseStart": 1290, + "end": 1291, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 313, + "responseStart": 1327, + "end": 1327, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/asset-sync-core.js?v=b1b63f1b41", + "bytes": 2344, + "start": 313, + "responseStart": 1341, + "end": 1342, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 313, + "responseStart": 1384, + "end": 1384, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 313, + "responseStart": 1415, + "end": 1416, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 314, + "responseStart": 1428, + "end": 1428, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 314, + "responseStart": 1467, + "end": 1467, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 314, + "responseStart": 1500, + "end": 1501, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 314, + "responseStart": 1505, + "end": 1505, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 314, + "responseStart": 1543, + "end": 1544, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 314, + "responseStart": 1585, + "end": 1586, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 314, + "responseStart": 1614, + "end": 1615, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 314, + "responseStart": 1625, + "end": 1626, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 315, + "responseStart": 1661, + "end": 1661, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 315, + "responseStart": 1662, + "end": 1662, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 315, + "responseStart": 1704, + "end": 1705, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 315, + "responseStart": 1744, + "end": 1745, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 315, + "responseStart": 1787, + "end": 1787, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 315, + "responseStart": 1814, + "end": 1814, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 315, + "responseStart": 1921, + "end": 1922, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 315, + "responseStart": 1985, + "end": 1985, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:5254/app.js?v=f485286cbc", + "bytes": 118521, + "start": 315, + "responseStart": 2772, + "end": 3041, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/perf/results/phase6-owned-trial.json b/perf/results/phase6-owned-trial.json new file mode 100644 index 0000000..15c8e1a --- /dev/null +++ b/perf/results/phase6-owned-trial.json @@ -0,0 +1,3736 @@ +{ + "date": "2026-10-08T01:00:43.582Z", + "frontendCommit": null, + "sourceRoot": null, + "sourceCommit": "e7a7cdc6b9fb69cf1426c5f94cd79371787a262a", + "frontendBuildTag": "bef1ace0232b", + "commit": "e7a7cdc6b9fb69cf1426c5f94cd79371787a262a", + "runsConfigured": 1, + "browsers": { + "webkit": { + "lte": { + "cold": { + "requestCount": { + "median": 160, + "min": 160, + "max": 160, + "values": [ + 160 + ] + }, + "wireBytes": { + "median": 981468, + "min": 981468, + "max": 981468, + "values": [ + 981468 + ] + }, + "fcp": { + "median": 1040, + "min": 1040, + "max": 1040, + "values": [ + 1040 + ] + }, + "lcp": { + "median": 1118, + "min": 1118, + "max": 1118, + "values": [ + 1118 + ] + }, + "domContentLoaded": { + "median": 1996, + "min": 1996, + "max": 1996, + "values": [ + 1996 + ] + }, + "bootDone": { + "median": 3139, + "min": 3139, + "max": 3139, + "values": [ + 3139 + ] + }, + "longTaskTotal": { + "median": 0, + "min": 0, + "max": 0, + "values": [ + 0 + ] + }, + "longTasks": [ + [] + ], + "swInstallDuration": { + "median": 32281, + "min": 32281, + "max": 32281, + "values": [ + 32281 + ] + }, + "swInstallBytes": { + "median": 981468, + "min": 981468, + "max": 981468, + "values": [ + 981468 + ] + }, + "storageEstimate": { + "usage": null, + "quota": null + }, + "mediaReady": { + "median": null, + "min": null, + "max": null, + "values": [ + null + ] + }, + "autoplayBlocked": true, + "wireBytesByType": { + "html": 28340, + "js": 440852, + "css": 133672, + "fonts": 365640, + "images": 6278, + "media": 0, + "api": 5120, + "other": 1566 + }, + "requests": [ + { + "url": "http://127.0.0.1:4817/?v=benchmedia01", + "status": 200, + "bytes": 14170, + "index": 1, + "startMs": 17, + "headersMs": 236, + "endMs": 308 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 316, + "headersMs": 470, + "endMs": 854 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 471, + "endMs": 645 + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 318, + "headersMs": 491, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "status": 200, + "bytes": 3150, + "index": 5, + "startMs": 318, + "headersMs": 500, + "endMs": 516 + }, + { + "url": "http://127.0.0.1:4817/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 318, + "headersMs": 504, + "endMs": 507 + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 319, + "headersMs": 682, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 517, + "headersMs": 686, + "endMs": 688 + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 512, + "headersMs": 717, + "endMs": 747 + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 508, + "headersMs": 738, + "endMs": 761 + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 646, + "headersMs": 802, + "endMs": 807 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 688, + "headersMs": 844, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 748, + "headersMs": 904, + "endMs": 910 + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 763, + "headersMs": 915, + "endMs": 919 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 808, + "headersMs": 966, + "endMs": 975 + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 850, + "headersMs": 1004, + "endMs": 1006 + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 852, + "headersMs": 1006, + "endMs": 1008 + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 854, + "headersMs": 1010, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 910, + "headersMs": 1079, + "endMs": 1103 + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 919, + "headersMs": 1089, + "endMs": 1105 + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 976, + "headersMs": 1129, + "endMs": 1133 + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1007, + "headersMs": 1167, + "endMs": 1179 + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1008, + "headersMs": 1170, + "endMs": 1179 + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1017, + "headersMs": 1181, + "endMs": 1198 + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1103, + "headersMs": 1258, + "endMs": 1265 + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1105, + "headersMs": 1264, + "endMs": 1275 + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1133, + "headersMs": 1289, + "endMs": 1296 + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1180, + "headersMs": 1336, + "endMs": 1340 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1181, + "headersMs": 1342, + "endMs": 1352 + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1199, + "headersMs": 1366, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1265, + "headersMs": 1420, + "endMs": 1424 + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1276, + "headersMs": 1429, + "endMs": 1433 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1297, + "headersMs": 1456, + "endMs": 1470 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1341, + "headersMs": 1503, + "endMs": 1519 + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1352, + "headersMs": 1505, + "endMs": 1509 + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1392, + "headersMs": 1548, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1425, + "headersMs": 1582, + "endMs": 1594 + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1434, + "headersMs": 1596, + "endMs": 1616 + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1471, + "headersMs": 1625, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1510, + "headersMs": 1666, + "endMs": 1672 + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1519, + "headersMs": 1671, + "endMs": 1673 + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1554, + "headersMs": 1706, + "endMs": 1710 + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1594, + "headersMs": 1748, + "endMs": 1753 + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1616, + "headersMs": 1775, + "endMs": 1788 + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1630, + "headersMs": 1795, + "endMs": 1816 + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1673, + "headersMs": 1898, + "endMs": 1994 + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1674, + "headersMs": 1910, + "endMs": 1931 + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "status": 200, + "bytes": 1201, + "index": 48, + "startMs": 1711, + "headersMs": 1913, + "endMs": 1918 + }, + { + "url": "http://127.0.0.1:4817/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 49, + "startMs": 1754, + "headersMs": 2481, + "endMs": 3077 + }, + { + "url": "http://127.0.0.1:4817/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 50, + "startMs": 1789, + "headersMs": 2488, + "endMs": 2492 + }, + { + "url": "http://127.0.0.1:4817/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 51, + "startMs": 3119, + "headersMs": 3273, + "endMs": 3275 + }, + { + "url": "http://127.0.0.1:4817/api/version", + "status": 200, + "bytes": 62, + "index": 52, + "startMs": 3136, + "headersMs": 3288, + "endMs": 3290 + }, + { + "url": "http://127.0.0.1:4817/api/user/sync", + "status": 200, + "bytes": 11, + "index": 53, + "startMs": 3138, + "headersMs": 3295, + "endMs": 3295 + }, + { + "url": "http://127.0.0.1:4817/sw.js", + "status": 200, + "bytes": 8992, + "index": 54, + "startMs": 3143, + "headersMs": 3325, + "endMs": 3370 + }, + { + "url": "http://127.0.0.1:4817/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 55, + "startMs": 3298, + "headersMs": 3451, + "endMs": 3452 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 56, + "startMs": 3377, + "headersMs": 3529, + "endMs": 3538 + }, + { + "url": "http://127.0.0.1:4817/api/manifest", + "status": 200, + "bytes": 3774, + "index": 57, + "startMs": 3542, + "headersMs": 3711, + "endMs": 3730 + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "status": 200, + "bytes": 1201, + "index": 58, + "startMs": 3758, + "headersMs": 3022, + "endMs": 3028 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 59, + "startMs": 3758, + "headersMs": 3022, + "endMs": 3031 + }, + { + "url": "http://127.0.0.1:4817/assets.json?v=5eb4df9a5f", + "status": 200, + "bytes": 1225, + "index": 60, + "startMs": 3758, + "headersMs": 3029, + "endMs": 3036 + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 61, + "startMs": 3758, + "headersMs": 3029, + "endMs": 3033 + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 62, + "startMs": 3759, + "headersMs": 3029, + "endMs": 3032 + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 63, + "startMs": 3759, + "headersMs": 3030, + "endMs": 3036 + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 64, + "startMs": 3030, + "headersMs": 3181, + "endMs": 3184 + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 65, + "startMs": 3033, + "headersMs": 3184, + "endMs": 3188 + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 66, + "startMs": 3034, + "headersMs": 3184, + "endMs": 3188 + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 67, + "startMs": 3035, + "headersMs": 3186, + "endMs": 3205 + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 68, + "startMs": 3038, + "headersMs": 3188, + "endMs": 3199 + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 69, + "startMs": 3039, + "headersMs": 3189, + "endMs": 3193 + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 70, + "startMs": 3186, + "headersMs": 3338, + "endMs": 3351 + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 71, + "startMs": 3189, + "headersMs": 3340, + "endMs": 3346 + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 72, + "startMs": 3190, + "headersMs": 3340, + "endMs": 3352 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 73, + "startMs": 3194, + "headersMs": 3345, + "endMs": 3499 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 74, + "startMs": 3200, + "headersMs": 3352, + "endMs": 3735 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 75, + "startMs": 3206, + "headersMs": 3359, + "endMs": 3458 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 76, + "startMs": 3349, + "headersMs": 3501, + "endMs": 3674 + }, + { + "url": "http://127.0.0.1:4817/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 77, + "startMs": 3353, + "headersMs": 3502, + "endMs": 3561 + }, + { + "url": "http://127.0.0.1:4817/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 78, + "startMs": 3354, + "headersMs": 3504, + "endMs": 3662 + }, + { + "url": "http://127.0.0.1:4817/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 79, + "startMs": 3460, + "headersMs": 3612, + "endMs": 3613 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 80, + "startMs": 3502, + "headersMs": 3653, + "endMs": 3662 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 81, + "startMs": 3563, + "headersMs": 3715, + "endMs": 3730 + }, + { + "url": "http://127.0.0.1:4817/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 82, + "startMs": 3615, + "headersMs": 3767, + "endMs": 3774 + }, + { + "url": "http://127.0.0.1:4817/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 83, + "startMs": 3664, + "headersMs": 3819, + "endMs": 3843 + }, + { + "url": "http://127.0.0.1:4817/index.html?v=ec7cba6163", + "status": 200, + "bytes": 14170, + "index": 84, + "startMs": 3665, + "headersMs": 3820, + "endMs": 3890 + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 85, + "startMs": 3676, + "headersMs": 3828, + "endMs": 3829 + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "status": 200, + "bytes": 3150, + "index": 86, + "startMs": 3733, + "headersMs": 3885, + "endMs": 3901 + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 87, + "startMs": 3737, + "headersMs": 3888, + "endMs": 3895 + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 88, + "startMs": 3777, + "headersMs": 3928, + "endMs": 3938 + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 89, + "startMs": 3832, + "headersMs": 3983, + "endMs": 3999 + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 90, + "startMs": 3845, + "headersMs": 3996, + "endMs": 4000 + }, + { + "url": "http://127.0.0.1:4817/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 91, + "startMs": 3892, + "headersMs": 4043, + "endMs": 4047 + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 92, + "startMs": 3896, + "headersMs": 4047, + "endMs": 4053 + }, + { + "url": "http://127.0.0.1:4817/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 93, + "startMs": 3902, + "headersMs": 4067, + "endMs": 4088 + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 94, + "startMs": 3940, + "headersMs": 4091, + "endMs": 4114 + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 95, + "startMs": 4001, + "headersMs": 4153, + "endMs": 4157 + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 96, + "startMs": 4001, + "headersMs": 4153, + "endMs": 4158 + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 97, + "startMs": 4049, + "headersMs": 4201, + "endMs": 4231 + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 98, + "startMs": 4054, + "headersMs": 4205, + "endMs": 4208 + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 99, + "startMs": 4090, + "headersMs": 4242, + "endMs": 4245 + }, + { + "url": "http://127.0.0.1:4817/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 100, + "startMs": 4118, + "headersMs": 4273, + "endMs": 4277 + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 101, + "startMs": 4158, + "headersMs": 4309, + "endMs": 4312 + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 102, + "startMs": 4160, + "headersMs": 4310, + "endMs": 4314 + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 103, + "startMs": 4209, + "headersMs": 4361, + "endMs": 4383 + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 104, + "startMs": 4234, + "headersMs": 4384, + "endMs": 4389 + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 105, + "startMs": 4247, + "headersMs": 4399, + "endMs": 4421 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 106, + "startMs": 4279, + "headersMs": 4431, + "endMs": 4436 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 107, + "startMs": 4314, + "headersMs": 4466, + "endMs": 4481 + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 108, + "startMs": 4316, + "headersMs": 4466, + "endMs": 4474 + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 109, + "startMs": 4385, + "headersMs": 4537, + "endMs": 4553 + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 110, + "startMs": 4391, + "headersMs": 4541, + "endMs": 4563 + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 111, + "startMs": 4424, + "headersMs": 4574, + "endMs": 4742 + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 112, + "startMs": 4438, + "headersMs": 4589, + "endMs": 4615 + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 113, + "startMs": 4477, + "headersMs": 4628, + "endMs": 4649 + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 114, + "startMs": 4483, + "headersMs": 4634, + "endMs": 4729 + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 115, + "startMs": 4556, + "headersMs": 4707, + "endMs": 4710 + }, + { + "url": "http://127.0.0.1:4817/sw.js", + "status": 200, + "bytes": 8992, + "index": 116, + "startMs": 4752, + "headersMs": 4904, + "endMs": 4949 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 117, + "startMs": 4951, + "headersMs": 5103, + "endMs": 5113 + }, + { + "url": "http://127.0.0.1:4817/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 118, + "startMs": 5780, + "headersMs": 5936, + "endMs": 5943 + }, + { + "url": "http://127.0.0.1:4817/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 119, + "startMs": 5780, + "headersMs": 5937, + "endMs": 5940 + }, + { + "url": "http://127.0.0.1:4817/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 120, + "startMs": 5780, + "headersMs": 5943, + "endMs": 5953 + }, + { + "url": "http://127.0.0.1:4817/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 121, + "startMs": 5780, + "headersMs": 5944, + "endMs": 5945 + }, + { + "url": "http://127.0.0.1:4817/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 122, + "startMs": 5780, + "headersMs": 5956, + "endMs": 5978 + }, + { + "url": "http://127.0.0.1:4817/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 123, + "startMs": 5780, + "headersMs": 5960, + "endMs": 5966 + }, + { + "url": "http://127.0.0.1:4817/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 124, + "startMs": 5942, + "headersMs": 6099, + "endMs": 6106 + }, + { + "url": "http://127.0.0.1:4817/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 125, + "startMs": 5945, + "headersMs": 6103, + "endMs": 6110 + }, + { + "url": "http://127.0.0.1:4817/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 126, + "startMs": 5947, + "headersMs": 6106, + "endMs": 6111 + }, + { + "url": "http://127.0.0.1:4817/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 127, + "startMs": 5955, + "headersMs": 6110, + "endMs": 6117 + }, + { + "url": "http://127.0.0.1:4817/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 128, + "startMs": 5968, + "headersMs": 6132, + "endMs": 6156 + }, + { + "url": "http://127.0.0.1:4817/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 129, + "startMs": 5980, + "headersMs": 6132, + "endMs": 6242 + }, + { + "url": "http://127.0.0.1:4817/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 130, + "startMs": 6108, + "headersMs": 6260, + "endMs": 6395 + }, + { + "url": "http://127.0.0.1:4817/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 131, + "startMs": 6112, + "headersMs": 6270, + "endMs": 6287 + }, + { + "url": "http://127.0.0.1:4817/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 132, + "startMs": 6113, + "headersMs": 6273, + "endMs": 6279 + }, + { + "url": "http://127.0.0.1:4817/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 133, + "startMs": 6119, + "headersMs": 6275, + "endMs": 6279 + }, + { + "url": "http://127.0.0.1:4817/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 134, + "startMs": 6160, + "headersMs": 6314, + "endMs": 6316 + }, + { + "url": "http://127.0.0.1:4817/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 135, + "startMs": 6244, + "headersMs": 6399, + "endMs": 6405 + }, + { + "url": "http://127.0.0.1:4817/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 136, + "startMs": 6280, + "headersMs": 6438, + "endMs": 6451 + }, + { + "url": "http://127.0.0.1:4817/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 137, + "startMs": 6280, + "headersMs": 6443, + "endMs": 6453 + }, + { + "url": "http://127.0.0.1:4817/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 138, + "startMs": 6288, + "headersMs": 6459, + "endMs": 6481 + }, + { + "url": "http://127.0.0.1:4817/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 139, + "startMs": 6319, + "headersMs": 6474, + "endMs": 6480 + }, + { + "url": "http://127.0.0.1:4817/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 140, + "startMs": 6397, + "headersMs": 6553, + "endMs": 6560 + }, + { + "url": "http://127.0.0.1:4817/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 141, + "startMs": 6406, + "headersMs": 6565, + "endMs": 6579 + }, + { + "url": "http://127.0.0.1:4817/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 142, + "startMs": 6453, + "headersMs": 6610, + "endMs": 6617 + }, + { + "url": "http://127.0.0.1:4817/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 143, + "startMs": 6454, + "headersMs": 6612, + "endMs": 6617 + }, + { + "url": "http://127.0.0.1:4817/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 144, + "startMs": 6482, + "headersMs": 6633, + "endMs": 6646 + }, + { + "url": "http://127.0.0.1:4817/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 145, + "startMs": 6483, + "headersMs": 6647, + "endMs": 6668 + }, + { + "url": "http://127.0.0.1:4817/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 146, + "startMs": 6563, + "headersMs": 6723, + "endMs": 6741 + }, + { + "url": "http://127.0.0.1:4817/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 147, + "startMs": 6581, + "headersMs": 6760, + "endMs": 6806 + }, + { + "url": "http://127.0.0.1:4817/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 148, + "startMs": 6619, + "headersMs": 6778, + "endMs": 6793 + }, + { + "url": "http://127.0.0.1:4817/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 149, + "startMs": 6619, + "headersMs": 6791, + "endMs": 6813 + }, + { + "url": "http://127.0.0.1:4817/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 150, + "startMs": 6648, + "headersMs": 6806, + "endMs": 6820 + }, + { + "url": "http://127.0.0.1:4817/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 151, + "startMs": 6670, + "headersMs": 6829, + "endMs": 6843 + }, + { + "url": "http://127.0.0.1:4817/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 152, + "startMs": 6744, + "headersMs": 6936, + "endMs": 6974 + }, + { + "url": "http://127.0.0.1:4817/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 153, + "startMs": 6795, + "headersMs": 6972, + "endMs": 6999 + }, + { + "url": "http://127.0.0.1:4817/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 154, + "startMs": 6808, + "headersMs": 6980, + "endMs": 6989 + }, + { + "url": "http://127.0.0.1:4817/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 155, + "startMs": 6815, + "headersMs": 6986, + "endMs": 6991 + }, + { + "url": "http://127.0.0.1:4817/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 156, + "startMs": 6822, + "headersMs": 7018, + "endMs": 7049 + }, + { + "url": "http://127.0.0.1:4817/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 157, + "startMs": 6845, + "headersMs": 7211, + "endMs": 7436 + }, + { + "url": "http://127.0.0.1:4817/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 158, + "startMs": 6977, + "headersMs": 7222, + "endMs": 7234 + }, + { + "url": "http://127.0.0.1:4817/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 159, + "startMs": 6991, + "headersMs": 7226, + "endMs": 7233 + }, + { + "url": "http://127.0.0.1:4817/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 160, + "startMs": 6994, + "headersMs": 7248, + "endMs": 7286 + } + ], + "initialJsCss": { + "median": 138009, + "min": 138009, + "max": 138009, + "values": [ + 138009 + ] + }, + "initialAssetRequests": [ + { + "url": "http://127.0.0.1:4817/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 314, + "responseStart": 504, + "end": 505, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 314, + "responseStart": 509, + "end": 509, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "bytes": 3150, + "start": 314, + "responseStart": 513, + "end": 513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 314, + "responseStart": 685, + "end": 685, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 314, + "responseStart": 744, + "end": 744, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 314, + "responseStart": 758, + "end": 759, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "bytes": 983, + "start": 314, + "responseStart": 804, + "end": 804, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 314, + "responseStart": 847, + "end": 848, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 315, + "responseStart": 847, + "end": 847, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 315, + "responseStart": 907, + "end": 907, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 315, + "responseStart": 916, + "end": 916, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 315, + "responseStart": 972, + "end": 972, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 315, + "responseStart": 1003, + "end": 1004, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 315, + "responseStart": 1005, + "end": 1005, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 316, + "responseStart": 1014, + "end": 1014, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 316, + "responseStart": 1100, + "end": 1100, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 316, + "responseStart": 1102, + "end": 1102, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 316, + "responseStart": 1130, + "end": 1130, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 316, + "responseStart": 1176, + "end": 1177, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 317, + "responseStart": 1177, + "end": 1177, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 317, + "responseStart": 1195, + "end": 1195, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 317, + "responseStart": 1262, + "end": 1262, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 317, + "responseStart": 1272, + "end": 1273, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 317, + "responseStart": 1293, + "end": 1294, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 317, + "responseStart": 1338, + "end": 1338, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 317, + "responseStart": 1349, + "end": 1349, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 318, + "responseStart": 1388, + "end": 1389, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 318, + "responseStart": 1421, + "end": 1421, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 318, + "responseStart": 1430, + "end": 1430, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 318, + "responseStart": 1468, + "end": 1468, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 318, + "responseStart": 1506, + "end": 1506, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 318, + "responseStart": 1516, + "end": 1516, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 318, + "responseStart": 1550, + "end": 1550, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 318, + "responseStart": 1591, + "end": 1591, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 318, + "responseStart": 1613, + "end": 1613, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 318, + "responseStart": 1627, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 319, + "responseStart": 1669, + "end": 1670, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 319, + "responseStart": 1670, + "end": 1670, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 319, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 319, + "responseStart": 1751, + "end": 1751, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 319, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 319, + "responseStart": 1814, + "end": 1814, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 319, + "responseStart": 1928, + "end": 1928, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 319, + "responseStart": 1991, + "end": 1992, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "bytes": 1201, + "start": 320, + "responseStart": 1915, + "end": 1916, + "initiator": "script" + } + ], + "waterfalls": [ + { + "fcp": 1040, + "requests": [ + { + "url": "http://127.0.0.1:4817/?v=benchmedia01", + "status": 200, + "bytes": 14170, + "index": 1, + "startMs": 17, + "headersMs": 236, + "endMs": 308 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 2, + "startMs": 316, + "headersMs": 470, + "endMs": 854 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 3, + "startMs": 317, + "headersMs": 471, + "endMs": 645 + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 4, + "startMs": 318, + "headersMs": 491, + "endMs": 512 + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "status": 200, + "bytes": 3150, + "index": 5, + "startMs": 318, + "headersMs": 500, + "endMs": 516 + }, + { + "url": "http://127.0.0.1:4817/fonts/fonts.css?v=dda3dfb804", + "status": 200, + "bytes": 457, + "index": 6, + "startMs": 318, + "headersMs": 504, + "endMs": 507 + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 7, + "startMs": 319, + "headersMs": 682, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 10, + "startMs": 517, + "headersMs": 686, + "endMs": 688 + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 9, + "startMs": 512, + "headersMs": 717, + "endMs": 747 + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 8, + "startMs": 508, + "headersMs": 738, + "endMs": 761 + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 11, + "startMs": 646, + "headersMs": 802, + "endMs": 807 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 12, + "startMs": 688, + "headersMs": 844, + "endMs": 850 + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 13, + "startMs": 748, + "headersMs": 904, + "endMs": 910 + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 14, + "startMs": 763, + "headersMs": 915, + "endMs": 919 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 15, + "startMs": 808, + "headersMs": 966, + "endMs": 975 + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 16, + "startMs": 850, + "headersMs": 1004, + "endMs": 1006 + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 17, + "startMs": 852, + "headersMs": 1006, + "endMs": 1008 + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 18, + "startMs": 854, + "headersMs": 1010, + "endMs": 1016 + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 19, + "startMs": 910, + "headersMs": 1079, + "endMs": 1103 + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 20, + "startMs": 919, + "headersMs": 1089, + "endMs": 1105 + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 21, + "startMs": 976, + "headersMs": 1129, + "endMs": 1133 + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 22, + "startMs": 1007, + "headersMs": 1167, + "endMs": 1179 + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 23, + "startMs": 1008, + "headersMs": 1170, + "endMs": 1179 + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 24, + "startMs": 1017, + "headersMs": 1181, + "endMs": 1198 + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 25, + "startMs": 1103, + "headersMs": 1258, + "endMs": 1265 + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 26, + "startMs": 1105, + "headersMs": 1264, + "endMs": 1275 + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 27, + "startMs": 1133, + "headersMs": 1289, + "endMs": 1296 + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 28, + "startMs": 1180, + "headersMs": 1336, + "endMs": 1340 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 29, + "startMs": 1181, + "headersMs": 1342, + "endMs": 1352 + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 30, + "startMs": 1199, + "headersMs": 1366, + "endMs": 1391 + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 31, + "startMs": 1265, + "headersMs": 1420, + "endMs": 1424 + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 32, + "startMs": 1276, + "headersMs": 1429, + "endMs": 1433 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 33, + "startMs": 1297, + "headersMs": 1456, + "endMs": 1470 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 34, + "startMs": 1341, + "headersMs": 1503, + "endMs": 1519 + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 35, + "startMs": 1352, + "headersMs": 1505, + "endMs": 1509 + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 36, + "startMs": 1392, + "headersMs": 1548, + "endMs": 1553 + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 37, + "startMs": 1425, + "headersMs": 1582, + "endMs": 1594 + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 38, + "startMs": 1434, + "headersMs": 1596, + "endMs": 1616 + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 39, + "startMs": 1471, + "headersMs": 1625, + "endMs": 1630 + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 40, + "startMs": 1510, + "headersMs": 1666, + "endMs": 1672 + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 41, + "startMs": 1519, + "headersMs": 1671, + "endMs": 1673 + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 42, + "startMs": 1554, + "headersMs": 1706, + "endMs": 1710 + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 43, + "startMs": 1594, + "headersMs": 1748, + "endMs": 1753 + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 44, + "startMs": 1616, + "headersMs": 1775, + "endMs": 1788 + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 45, + "startMs": 1630, + "headersMs": 1795, + "endMs": 1816 + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 46, + "startMs": 1673, + "headersMs": 1898, + "endMs": 1994 + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 47, + "startMs": 1674, + "headersMs": 1910, + "endMs": 1931 + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "status": 200, + "bytes": 1201, + "index": 48, + "startMs": 1711, + "headersMs": 1913, + "endMs": 1918 + }, + { + "url": "http://127.0.0.1:4817/app.js?v=f485286cbc", + "status": 200, + "bytes": 118521, + "index": 49, + "startMs": 1754, + "headersMs": 2481, + "endMs": 3077 + }, + { + "url": "http://127.0.0.1:4817/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 50, + "startMs": 1789, + "headersMs": 2488, + "endMs": 2492 + }, + { + "url": "http://127.0.0.1:4817/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 51, + "startMs": 3119, + "headersMs": 3273, + "endMs": 3275 + }, + { + "url": "http://127.0.0.1:4817/api/version", + "status": 200, + "bytes": 62, + "index": 52, + "startMs": 3136, + "headersMs": 3288, + "endMs": 3290 + }, + { + "url": "http://127.0.0.1:4817/api/user/sync", + "status": 200, + "bytes": 11, + "index": 53, + "startMs": 3138, + "headersMs": 3295, + "endMs": 3295 + }, + { + "url": "http://127.0.0.1:4817/sw.js", + "status": 200, + "bytes": 8992, + "index": 54, + "startMs": 3143, + "headersMs": 3325, + "endMs": 3370 + }, + { + "url": "http://127.0.0.1:4817/api/recommendations?fp=163577c02a53bc40", + "status": 200, + "bytes": 24, + "index": 55, + "startMs": 3298, + "headersMs": 3451, + "endMs": 3452 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 56, + "startMs": 3377, + "headersMs": 3529, + "endMs": 3538 + }, + { + "url": "http://127.0.0.1:4817/api/manifest", + "status": 200, + "bytes": 3774, + "index": 57, + "startMs": 3542, + "headersMs": 3711, + "endMs": 3730 + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "status": 200, + "bytes": 1201, + "index": 58, + "startMs": 3758, + "headersMs": 3022, + "endMs": 3028 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 59, + "startMs": 3758, + "headersMs": 3022, + "endMs": 3031 + }, + { + "url": "http://127.0.0.1:4817/assets.json?v=5eb4df9a5f", + "status": 200, + "bytes": 1225, + "index": 60, + "startMs": 3758, + "headersMs": 3029, + "endMs": 3036 + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "status": 200, + "bytes": 887, + "index": 61, + "startMs": 3758, + "headersMs": 3029, + "endMs": 3033 + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "status": 200, + "bytes": 677, + "index": 62, + "startMs": 3759, + "headersMs": 3029, + "endMs": 3032 + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "status": 200, + "bytes": 1230, + "index": 63, + "startMs": 3759, + "headersMs": 3030, + "endMs": 3036 + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "status": 200, + "bytes": 560, + "index": 64, + "startMs": 3030, + "headersMs": 3181, + "endMs": 3184 + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "status": 200, + "bytes": 669, + "index": 65, + "startMs": 3033, + "headersMs": 3184, + "endMs": 3188 + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "status": 200, + "bytes": 959, + "index": 66, + "startMs": 3034, + "headersMs": 3184, + "endMs": 3188 + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "status": 200, + "bytes": 3642, + "index": 67, + "startMs": 3035, + "headersMs": 3186, + "endMs": 3205 + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "status": 200, + "bytes": 2088, + "index": 68, + "startMs": 3038, + "headersMs": 3188, + "endMs": 3199 + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "status": 200, + "bytes": 832, + "index": 69, + "startMs": 3039, + "headersMs": 3189, + "endMs": 3193 + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "status": 200, + "bytes": 2430, + "index": 70, + "startMs": 3186, + "headersMs": 3338, + "endMs": 3351 + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "status": 200, + "bytes": 1269, + "index": 71, + "startMs": 3189, + "headersMs": 3340, + "endMs": 3346 + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "status": 200, + "bytes": 2469, + "index": 72, + "startMs": 3190, + "headersMs": 3340, + "endMs": 3352 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin-ext.woff2", + "status": 200, + "bytes": 30736, + "index": 73, + "startMs": 3194, + "headersMs": 3345, + "endMs": 3499 + }, + { + "url": "http://127.0.0.1:4817/fonts/BricolageGrotesque-latin.woff2", + "status": 200, + "bytes": 76888, + "index": 74, + "startMs": 3200, + "headersMs": 3352, + "endMs": 3735 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin-ext.woff2", + "status": 200, + "bytes": 19588, + "index": 75, + "startMs": 3206, + "headersMs": 3359, + "endMs": 3458 + }, + { + "url": "http://127.0.0.1:4817/fonts/HankenGrotesk-latin.woff2", + "status": 200, + "bytes": 34704, + "index": 76, + "startMs": 3349, + "headersMs": 3501, + "endMs": 3674 + }, + { + "url": "http://127.0.0.1:4817/fonts/JetBrainsMono-latin-ext.woff2", + "status": 200, + "bytes": 11624, + "index": 77, + "startMs": 3353, + "headersMs": 3502, + "endMs": 3561 + }, + { + "url": "http://127.0.0.1:4817/fonts/JetBrainsMono-latin.woff2", + "status": 200, + "bytes": 31432, + "index": 78, + "startMs": 3354, + "headersMs": 3504, + "endMs": 3662 + }, + { + "url": "http://127.0.0.1:4817/fonts/fonts.css", + "status": 200, + "bytes": 457, + "index": 79, + "startMs": 3460, + "headersMs": 3612, + "endMs": 3613 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "status": 200, + "bytes": 1721, + "index": 80, + "startMs": 3502, + "headersMs": 3653, + "endMs": 3662 + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "status": 200, + "bytes": 2916, + "index": 81, + "startMs": 3563, + "headersMs": 3715, + "endMs": 3730 + }, + { + "url": "http://127.0.0.1:4817/icons/icon-192.png", + "status": 200, + "bytes": 1669, + "index": 82, + "startMs": 3615, + "headersMs": 3767, + "endMs": 3774 + }, + { + "url": "http://127.0.0.1:4817/icons/icon-512.png", + "status": 200, + "bytes": 4609, + "index": 83, + "startMs": 3664, + "headersMs": 3819, + "endMs": 3843 + }, + { + "url": "http://127.0.0.1:4817/index.html?v=ec7cba6163", + "status": 200, + "bytes": 14170, + "index": 84, + "startMs": 3665, + "headersMs": 3820, + "endMs": 3890 + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "status": 200, + "bytes": 336, + "index": 85, + "startMs": 3676, + "headersMs": 3828, + "endMs": 3829 + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "status": 200, + "bytes": 3150, + "index": 86, + "startMs": 3733, + "headersMs": 3885, + "endMs": 3901 + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "status": 200, + "bytes": 1279, + "index": 87, + "startMs": 3737, + "headersMs": 3888, + "endMs": 3895 + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "status": 200, + "bytes": 2068, + "index": 88, + "startMs": 3777, + "headersMs": 3928, + "endMs": 3938 + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "status": 200, + "bytes": 3038, + "index": 89, + "startMs": 3832, + "headersMs": 3983, + "endMs": 3999 + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "status": 200, + "bytes": 750, + "index": 90, + "startMs": 3845, + "headersMs": 3996, + "endMs": 4000 + }, + { + "url": "http://127.0.0.1:4817/manifest.webmanifest", + "status": 200, + "bytes": 783, + "index": 91, + "startMs": 3892, + "headersMs": 4043, + "endMs": 4047 + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "status": 200, + "bytes": 1069, + "index": 92, + "startMs": 3896, + "headersMs": 4047, + "endMs": 4053 + }, + { + "url": "http://127.0.0.1:4817/opfs-worker.js?v=17cfe8fb26", + "status": 200, + "bytes": 4042, + "index": 93, + "startMs": 3902, + "headersMs": 4067, + "endMs": 4088 + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "status": 200, + "bytes": 4571, + "index": 94, + "startMs": 3940, + "headersMs": 4091, + "endMs": 4114 + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "status": 200, + "bytes": 665, + "index": 95, + "startMs": 4001, + "headersMs": 4153, + "endMs": 4157 + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "status": 200, + "bytes": 983, + "index": 96, + "startMs": 4001, + "headersMs": 4153, + "endMs": 4158 + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "status": 200, + "bytes": 5828, + "index": 97, + "startMs": 4049, + "headersMs": 4201, + "endMs": 4231 + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "status": 200, + "bytes": 517, + "index": 98, + "startMs": 4054, + "headersMs": 4205, + "endMs": 4208 + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "status": 200, + "bytes": 642, + "index": 99, + "startMs": 4090, + "headersMs": 4242, + "endMs": 4245 + }, + { + "url": "http://127.0.0.1:4817/resume-core.js?v=df42e94600", + "status": 200, + "bytes": 915, + "index": 100, + "startMs": 4118, + "headersMs": 4273, + "endMs": 4277 + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "status": 200, + "bytes": 673, + "index": 101, + "startMs": 4158, + "headersMs": 4309, + "endMs": 4312 + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "status": 200, + "bytes": 820, + "index": 102, + "startMs": 4160, + "headersMs": 4310, + "endMs": 4314 + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "status": 200, + "bytes": 4206, + "index": 103, + "startMs": 4209, + "headersMs": 4361, + "endMs": 4383 + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "status": 200, + "bytes": 1105, + "index": 104, + "startMs": 4234, + "headersMs": 4384, + "endMs": 4389 + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "status": 200, + "bytes": 4417, + "index": 105, + "startMs": 4247, + "headersMs": 4399, + "endMs": 4421 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "status": 200, + "bytes": 1076, + "index": 106, + "startMs": 4279, + "headersMs": 4431, + "endMs": 4436 + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "status": 200, + "bytes": 3174, + "index": 107, + "startMs": 4314, + "headersMs": 4466, + "endMs": 4481 + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "status": 200, + "bytes": 1748, + "index": 108, + "startMs": 4316, + "headersMs": 4466, + "endMs": 4474 + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "status": 200, + "bytes": 3209, + "index": 109, + "startMs": 4385, + "headersMs": 4537, + "endMs": 4553 + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "status": 200, + "bytes": 4548, + "index": 110, + "startMs": 4391, + "headersMs": 4541, + "endMs": 4563 + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "status": 200, + "bytes": 33412, + "index": 111, + "startMs": 4424, + "headersMs": 4574, + "endMs": 4742 + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "status": 200, + "bytes": 5195, + "index": 112, + "startMs": 4438, + "headersMs": 4589, + "endMs": 4615 + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "status": 200, + "bytes": 4079, + "index": 113, + "startMs": 4477, + "headersMs": 4628, + "endMs": 4649 + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "status": 200, + "bytes": 19016, + "index": 114, + "startMs": 4483, + "headersMs": 4634, + "endMs": 4729 + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "status": 200, + "bytes": 474, + "index": 115, + "startMs": 4556, + "headersMs": 4707, + "endMs": 4710 + }, + { + "url": "http://127.0.0.1:4817/sw.js", + "status": 200, + "bytes": 8992, + "index": 116, + "startMs": 4752, + "headersMs": 4904, + "endMs": 4949 + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "status": 200, + "bytes": 1954, + "index": 117, + "startMs": 4951, + "headersMs": 5103, + "endMs": 5113 + }, + { + "url": "http://127.0.0.1:4817/bento-hub.js?v=c867882d7e", + "status": 200, + "bytes": 1523, + "index": 118, + "startMs": 5780, + "headersMs": 5936, + "endMs": 5943 + }, + { + "url": "http://127.0.0.1:4817/car-mode.css?v=7d421630b3", + "status": 200, + "bytes": 504, + "index": 119, + "startMs": 5780, + "headersMs": 5937, + "endMs": 5940 + }, + { + "url": "http://127.0.0.1:4817/car-mode.js?v=ebd6588f35", + "status": 200, + "bytes": 2080, + "index": 120, + "startMs": 5780, + "headersMs": 5943, + "endMs": 5953 + }, + { + "url": "http://127.0.0.1:4817/direct-media.css?v=19b8428bfd", + "status": 200, + "bytes": 370, + "index": 121, + "startMs": 5780, + "headersMs": 5944, + "endMs": 5945 + }, + { + "url": "http://127.0.0.1:4817/direct-media.js?v=035420e8fb", + "status": 200, + "bytes": 4252, + "index": 122, + "startMs": 5780, + "headersMs": 5956, + "endMs": 5978 + }, + { + "url": "http://127.0.0.1:4817/direct-protocol.js?v=87a73be90f", + "status": 200, + "bytes": 1245, + "index": 123, + "startMs": 5780, + "headersMs": 5960, + "endMs": 5966 + }, + { + "url": "http://127.0.0.1:4817/direct-recv-worker.js?v=caa45eb981", + "status": 200, + "bytes": 1216, + "index": 124, + "startMs": 5942, + "headersMs": 6099, + "endMs": 6106 + }, + { + "url": "http://127.0.0.1:4817/direct-stream.js?v=d7f9871605", + "status": 200, + "bytes": 1457, + "index": 125, + "startMs": 5945, + "headersMs": 6103, + "endMs": 6110 + }, + { + "url": "http://127.0.0.1:4817/eq-core.js?v=cb6d079933", + "status": 200, + "bytes": 1071, + "index": 126, + "startMs": 5947, + "headersMs": 6106, + "endMs": 6111 + }, + { + "url": "http://127.0.0.1:4817/export.js?v=5b7cdcd7a3", + "status": 200, + "bytes": 1536, + "index": 127, + "startMs": 5955, + "headersMs": 6110, + "endMs": 6117 + }, + { + "url": "http://127.0.0.1:4817/f7-layout.js?v=fe7e94a4a9", + "status": 200, + "bytes": 4763, + "index": 128, + "startMs": 5968, + "headersMs": 6132, + "endMs": 6156 + }, + { + "url": "http://127.0.0.1:4817/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80", + "status": 200, + "bytes": 21728, + "index": 129, + "startMs": 5980, + "headersMs": 6132, + "endMs": 6242 + }, + { + "url": "http://127.0.0.1:4817/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70", + "status": 200, + "bytes": 27348, + "index": 130, + "startMs": 6108, + "headersMs": 6260, + "endMs": 6395 + }, + { + "url": "http://127.0.0.1:4817/glass-controls.js?v=a60ed1fe84", + "status": 200, + "bytes": 3227, + "index": 131, + "startMs": 6112, + "headersMs": 6270, + "endMs": 6287 + }, + { + "url": "http://127.0.0.1:4817/glass-panel-layout.js?v=d5417786d0", + "status": 200, + "bytes": 1173, + "index": 132, + "startMs": 6113, + "headersMs": 6273, + "endMs": 6279 + }, + { + "url": "http://127.0.0.1:4817/hash-worker.js?v=5cccc78057", + "status": 200, + "bytes": 624, + "index": 133, + "startMs": 6119, + "headersMs": 6275, + "endMs": 6279 + }, + { + "url": "http://127.0.0.1:4817/lower-third.css?v=031f8e0ead", + "status": 200, + "bytes": 502, + "index": 134, + "startMs": 6160, + "headersMs": 6314, + "endMs": 6316 + }, + { + "url": "http://127.0.0.1:4817/lower-third.js?v=7705dcbfb4", + "status": 200, + "bytes": 1153, + "index": 135, + "startMs": 6244, + "headersMs": 6399, + "endMs": 6405 + }, + { + "url": "http://127.0.0.1:4817/lyrics-window.js?v=8f333e2442", + "status": 200, + "bytes": 2474, + "index": 136, + "startMs": 6280, + "headersMs": 6438, + "endMs": 6451 + }, + { + "url": "http://127.0.0.1:4817/midi.js?v=dbecfa74e1", + "status": 200, + "bytes": 2014, + "index": 137, + "startMs": 6280, + "headersMs": 6443, + "endMs": 6453 + }, + { + "url": "http://127.0.0.1:4817/p2p-client.js?v=74fbd79661", + "status": 200, + "bytes": 4444, + "index": 138, + "startMs": 6288, + "headersMs": 6459, + "endMs": 6481 + }, + { + "url": "http://127.0.0.1:4817/p2p-core.js?v=168a879219", + "status": 200, + "bytes": 1137, + "index": 139, + "startMs": 6319, + "headersMs": 6474, + "endMs": 6480 + }, + { + "url": "http://127.0.0.1:4817/p2p-recv-worker.js?v=9d435c6cbb", + "status": 200, + "bytes": 1475, + "index": 140, + "startMs": 6397, + "headersMs": 6553, + "endMs": 6560 + }, + { + "url": "http://127.0.0.1:4817/p2p-transfer.js?v=e508302618", + "status": 200, + "bytes": 2773, + "index": 141, + "startMs": 6406, + "headersMs": 6565, + "endMs": 6579 + }, + { + "url": "http://127.0.0.1:4817/party-dj.js?v=1677c38a88", + "status": 200, + "bytes": 1444, + "index": 142, + "startMs": 6453, + "headersMs": 6610, + "endMs": 6617 + }, + { + "url": "http://127.0.0.1:4817/piano-core.js?v=77c8269761", + "status": 200, + "bytes": 867, + "index": 143, + "startMs": 6454, + "headersMs": 6612, + "endMs": 6617 + }, + { + "url": "http://127.0.0.1:4817/piano-engine.mjs?v=2d2f29b38e", + "status": 200, + "bytes": 2580, + "index": 144, + "startMs": 6482, + "headersMs": 6633, + "endMs": 6646 + }, + { + "url": "http://127.0.0.1:4817/piano.js?v=e82bc30884", + "status": 200, + "bytes": 4003, + "index": 145, + "startMs": 6483, + "headersMs": 6647, + "endMs": 6668 + }, + { + "url": "http://127.0.0.1:4817/presenter.js?v=e5b34ff758", + "status": 200, + "bytes": 3558, + "index": 146, + "startMs": 6563, + "headersMs": 6723, + "endMs": 6741 + }, + { + "url": "http://127.0.0.1:4817/remote-client.js?v=a2b5acb20f", + "status": 200, + "bytes": 9042, + "index": 147, + "startMs": 6581, + "headersMs": 6760, + "endMs": 6806 + }, + { + "url": "http://127.0.0.1:4817/setlist-import.js?v=13bc5cc4a4", + "status": 200, + "bytes": 2879, + "index": 148, + "startMs": 6619, + "headersMs": 6778, + "endMs": 6793 + }, + { + "url": "http://127.0.0.1:4817/share-external.js?v=9de67de710", + "status": 200, + "bytes": 4222, + "index": 149, + "startMs": 6619, + "headersMs": 6791, + "endMs": 6813 + }, + { + "url": "http://127.0.0.1:4817/stats-core.js?v=3de0591d83", + "status": 200, + "bytes": 2619, + "index": 150, + "startMs": 6648, + "headersMs": 6806, + "endMs": 6820 + }, + { + "url": "http://127.0.0.1:4817/stats-view.js?v=beb2343b30", + "status": 200, + "bytes": 2664, + "index": 151, + "startMs": 6670, + "headersMs": 6829, + "endMs": 6843 + }, + { + "url": "http://127.0.0.1:4817/theme-bento-hub.css?v=f529dc4bb7", + "status": 200, + "bytes": 7731, + "index": 152, + "startMs": 6744, + "headersMs": 6936, + "endMs": 6974 + }, + { + "url": "http://127.0.0.1:4817/theme-f7.css?v=02ba226f82", + "status": 200, + "bytes": 5579, + "index": 153, + "startMs": 6795, + "headersMs": 6972, + "endMs": 6999 + }, + { + "url": "http://127.0.0.1:4817/theme-glass-controls.css?v=3354ad9631", + "status": 200, + "bytes": 1782, + "index": 154, + "startMs": 6808, + "headersMs": 6980, + "endMs": 6989 + }, + { + "url": "http://127.0.0.1:4817/theme-glass-panel.css?v=25aadb0bb7", + "status": 200, + "bytes": 1045, + "index": 155, + "startMs": 6815, + "headersMs": 6986, + "endMs": 6991 + }, + { + "url": "http://127.0.0.1:4817/theme-glass.css?v=09feb15c53", + "status": 200, + "bytes": 5903, + "index": 156, + "startMs": 6822, + "headersMs": 7018, + "endMs": 7049 + }, + { + "url": "http://127.0.0.1:4817/vendor/framework7-swipe.min.js?v=22b954749c", + "status": 200, + "bytes": 44829, + "index": 157, + "startMs": 6845, + "headersMs": 7211, + "endMs": 7436 + }, + { + "url": "http://127.0.0.1:4817/video-edit.js?v=90c5dd1eb6", + "status": 200, + "bytes": 2506, + "index": 158, + "startMs": 6977, + "headersMs": 7222, + "endMs": 7234 + }, + { + "url": "http://127.0.0.1:4817/vocal-reducer.js?v=ddb2fc1bbe", + "status": 200, + "bytes": 1397, + "index": 159, + "startMs": 6991, + "headersMs": 7226, + "endMs": 7233 + }, + { + "url": "http://127.0.0.1:4817/watch-party-client.js?v=0210655848", + "status": 200, + "bytes": 7473, + "index": 160, + "startMs": 6994, + "headersMs": 7248, + "endMs": 7286 + } + ], + "page": [ + { + "url": "http://127.0.0.1:4817/fonts/fonts.css?v=dda3dfb804", + "bytes": 457, + "start": 314, + "responseStart": 504, + "end": 505, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/theme-classic.css?v=d420fcfb12", + "bytes": 4079, + "start": 314, + "responseStart": 509, + "end": 509, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/lazy.js?v=da73321f20", + "bytes": 3150, + "start": 314, + "responseStart": 513, + "end": 513, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/layout-base.css?v=4f3307cd3b", + "bytes": 336, + "start": 314, + "responseStart": 685, + "end": 685, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/refresh.css?v=62498384f1", + "bytes": 5828, + "start": 314, + "responseStart": 744, + "end": 744, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/service-ui.css?v=b9bf96a3a8", + "bytes": 4417, + "start": 314, + "responseStart": 758, + "end": 759, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/recommendations.css?v=055101368d", + "bytes": 983, + "start": 314, + "responseStart": 804, + "end": 804, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/styles.css?v=9f3a5dea41", + "bytes": 33412, + "start": 314, + "responseStart": 847, + "end": 848, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/settings-sections.css?v=055507ab85", + "bytes": 1076, + "start": 315, + "responseStart": 847, + "end": 847, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/offline-pages.css?v=2889456261", + "bytes": 1069, + "start": 315, + "responseStart": 907, + "end": 907, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/saved-page.css?v=3ff576a784", + "bytes": 673, + "start": 315, + "responseStart": 916, + "end": 916, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.css?v=91f2d84453", + "bytes": 1721, + "start": 315, + "responseStart": 972, + "end": 972, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/related-videos.css?v=5a616b1be8", + "bytes": 517, + "start": 315, + "responseStart": 1003, + "end": 1004, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/download-actions.css?v=12d3bcfe3e", + "bytes": 560, + "start": 315, + "responseStart": 1005, + "end": 1005, + "initiator": "link" + }, + { + "url": "http://127.0.0.1:4817/fingerprint.js?v=a635143269", + "bytes": 1269, + "start": 316, + "responseStart": 1014, + "end": 1014, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/opfs.js?v=df7a8d0391", + "bytes": 4571, + "start": 316, + "responseStart": 1100, + "end": 1100, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/lyrics-core.js?v=4dcdac2edd", + "bytes": 3038, + "start": 316, + "responseStart": 1102, + "end": 1102, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/lyrics-display.js?v=48e8550175", + "bytes": 750, + "start": 316, + "responseStart": 1130, + "end": 1130, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/flag-ui.js?v=eeae1c1d1a", + "bytes": 2469, + "start": 316, + "responseStart": 1176, + "end": 1177, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sha256-wasm.js?v=393c50ba56", + "bytes": 1748, + "start": 317, + "responseStart": 1177, + "end": 1177, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sha256.js?v=cd9b980e6f", + "bytes": 3209, + "start": 317, + "responseStart": 1195, + "end": 1195, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/loudness-wasm.js?v=c6102d7844", + "bytes": 1279, + "start": 317, + "responseStart": 1262, + "end": 1262, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/loudness.js?v=01b3da88dd", + "bytes": 2068, + "start": 317, + "responseStart": 1272, + "end": 1273, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/device-db.js?v=880c5cd70e", + "bytes": 1230, + "start": 317, + "responseStart": 1293, + "end": 1294, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/async-guard.js?v=e4afa1f2be", + "bytes": 887, + "start": 317, + "responseStart": 1338, + "end": 1338, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/asset-sync-core.js?v=155be9339b", + "bytes": 1954, + "start": 317, + "responseStart": 1349, + "end": 1349, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/sw-update.js?v=772c123c20", + "bytes": 5195, + "start": 318, + "responseStart": 1388, + "end": 1389, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/related-videos.js?v=3eec0ebd4c", + "bytes": 642, + "start": 318, + "responseStart": 1421, + "end": 1421, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/audio-continuity.js?v=63b5464dd5", + "bytes": 677, + "start": 318, + "responseStart": 1430, + "end": 1430, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/fullscreen-orientation.js?v=c8e44eb66b", + "bytes": 2916, + "start": 318, + "responseStart": 1468, + "end": 1468, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/download-actions.js?v=388c7edecb", + "bytes": 669, + "start": 318, + "responseStart": 1506, + "end": 1506, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/settings-sections.js?v=1101425859", + "bytes": 3174, + "start": 318, + "responseStart": 1516, + "end": 1516, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/download-errors.js?v=bb6a4c887a", + "bytes": 959, + "start": 318, + "responseStart": 1550, + "end": 1550, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/downloads.js?v=f2d3e7d212", + "bytes": 2088, + "start": 318, + "responseStart": 1591, + "end": 1591, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/downloads-page.js?v=c1a3a218c0", + "bytes": 3642, + "start": 318, + "responseStart": 1613, + "end": 1613, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/saved-page.js?v=f1518c50fb", + "bytes": 820, + "start": 318, + "responseStart": 1627, + "end": 1627, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/server-backfill.js?v=294b103023", + "bytes": 1105, + "start": 319, + "responseStart": 1669, + "end": 1670, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/visible-timer.js?v=5322e86ef4", + "bytes": 474, + "start": 319, + "responseStart": 1670, + "end": 1670, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/prewarm-next.js?v=ed16a51424", + "bytes": 665, + "start": 319, + "responseStart": 1707, + "end": 1707, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/eq-parameters.js?v=dc2c6a8e8d", + "bytes": 832, + "start": 319, + "responseStart": 1751, + "end": 1751, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/feature-bootstrap.js?v=33779ecef7", + "bytes": 2430, + "start": 319, + "responseStart": 1785, + "end": 1786, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/shell-core.js?v=a04305c2ad", + "bytes": 4548, + "start": 319, + "responseStart": 1814, + "end": 1814, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/section-rail.js?v=07417c1bcc", + "bytes": 4206, + "start": 319, + "responseStart": 1928, + "end": 1928, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/views-core.js?v=49be16274c", + "bytes": 19016, + "start": 319, + "responseStart": 1991, + "end": 1992, + "initiator": "script" + }, + { + "url": "http://127.0.0.1:4817/app-bootstrap.js?v=9ecb3ed5c4", + "bytes": 1201, + "start": 320, + "responseStart": 1915, + "end": 1916, + "initiator": "script" + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/plans/phase6-investigation.md b/plans/phase6-investigation.md index f5e5a13..ad076c1 100644 --- a/plans/phase6-investigation.md +++ b/plans/phase6-investigation.md @@ -51,3 +51,28 @@ FCP is 909 ms; the first classic request reaches the proxy at 250 ms and complet at 423 ms. Lazy still applies only the saved layout, in the original cascade order. Other selected layouts may speculatively download the small classic stylesheet; it never applies or blocks their rendering. No inline script or CSP change. + + +The page-to-worker prototype successfully delivered bodies, but still transferred +app.js twice. `phase6-handoff-mode.json` records the two requests: identical URL, +`Accept-Encoding: gzip, deflate`, no-cors mode and immutable response, but script +versus empty request destinations. Force-cache in the page did not reuse the +script body's cache either. This prototype was discarded, not shipped. + +A fetch preload plus a later fetch also failed the one-body assertion. The +shipping fix instead starts one cache-first fetch promise in the head loader. +The final eager app-bootstrap consumes that response, verifies header AND SHA-256, +and caches it before executing unchanged app.js as a classic script. A specific +server-generated CSP hash authorizes only those exact bytes; unsafe-inline remains +absent. DOMContentLoaded boot runs exactly once; the temporary script node and +response promise are released. Native, insecure HTTP and rollback modes retain +external classic execution. Only server asset-manifest rendering changed; no +frontend imports, worker sync algorithm, update flow or playback source changed. + +The initial owned-response trial passed with one app.js body, FCP 1040 ms and +981468 wire bytes (one fresh sample; not a final median). Five-run acceptance and +regression results will be recorded separately. Historical diagnostics retained +all samples. Full-harness configurations now reset to the base tree before each +browser/profile, preventing a preceding synthetic update from contaminating the +next cold build. The historical invalid media fixture remains unchanged: home +launch only, not autoplay/audio latency. From 3505dc3c0e57e50983c4300bba4cd23ffa8744a0 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 09:10:28 +0800 Subject: [PATCH 49/81] Preserve verified N-1 app boot after a cache entry is lost --- frontend/app-bootstrap.js | 48 ++++++++++++++++++++++++---------- frontend/app-bootstrap.test.js | 19 +++++++++++--- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js index 3152544..398ca77 100644 --- a/frontend/app-bootstrap.js +++ b/frontend/app-bootstrap.js @@ -12,26 +12,46 @@ // consumption can finish after that event; boot exactly once in that case. if(domReady)root.boot(); } + async function external(url) { + await new Promise((resolve,reject)=>{ + const node=doc.createElement('script');node.src=url; + node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); + doc.head.append(node); + }); + } + async function verified(response, expected) { + const bytes=await response.clone().arrayBuffer(); + const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); + const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); + if(hex.slice(0,10)!==expected)throw Error('Player body hash mismatch'); + return {bytes,digest}; + } async function start() { - if(!manifest.appCache || !root.crypto?.subtle) { - await new Promise((resolve,reject)=>{ - const node=doc.createElement('script');node.src=key; - node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); - doc.head.append(node); - }); - return; - } + if(!manifest.appCache || !root.crypto?.subtle)return external(key); const expected=manifest.files['/app.js'].h; let cache; try { cache=await root.caches?.open('ytplayer-assets'); } catch {} let response=await cache?.match(key); - if(!response || response.headers.get('X-Asset-Hash')!==expected)response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); - if(!response.ok || response.headers.get('X-Asset-Hash')!==expected)throw Error('Player asset hash mismatch'); - const bytes=await response.clone().arrayBuffer(); - const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); - const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); + if(!response || response.headers.get('X-Asset-Hash')!==expected) { + try { response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); } catch {} + } + if(!response?.ok || response.headers.get('X-Asset-Hash')!==expected) { + // Preserve staged N-1 boot after an individual cache eviction. Only the + // controller can serve this old URL safely; never fetch stale URLs bare. + const state=cache && await root.AssetSyncCore.state(cache); + const previousKey=state && root.AssetSyncCore.fallback(manifest,state.previous,'/app.js'); + const previous=previousKey && await cache.match(previousKey); + const previousHash=state?.previous?.files['/app.js']?.h; + if(root.navigator?.serviceWorker?.controller && previous?.ok && previous.headers.get('X-Asset-Hash')===previousHash) { + await verified(previous,previousHash); + delete root.Lazy.appResponse; + return external(previousKey); + } + throw Error('Player asset hash mismatch'); + } + const {bytes,digest}=await verified(response,expected); const permission="'sha256-"+root.btoa(String.fromCharCode(...digest))+"'"; - if(hex.slice(0,10)!==expected || !doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); + if(!doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); // CacheStorage may share a full quota with saved music. Never remove data // to make room; boot from these verified bytes even if caching is refused. try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js index 912b9e0..ea11df6 100644 --- a/frontend/app-bootstrap.test.js +++ b/frontend/app-bootstrap.test.js @@ -3,16 +3,18 @@ const assert=require('node:assert/strict'); const {webcrypto,createHash}=require('node:crypto'); const vm=require('node:vm'); const {readFileSync}=require('node:fs'); -function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false}={}){ +function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false,previous=false,contract=1}={}){ const source='window.appRuns=(window.appRuns||0)+1; window.boot=()=>window.bootRuns=(window.bootRuns||0)+1; document.addEventListener("DOMContentLoaded",boot);',hash=createHash('sha256').update(source).digest('hex'), key='/app.js?v='+hash.slice(0,10); + const oldSource='window.oldApp=true;'+source, oldHash=createHash('sha256').update(oldSource).digest('hex').slice(0,10), oldKey='/app.js?v='+oldHash; const held=new Map(), appended=[],listeners={};let calls=0; const response=()=>new Response(tampered?'bad':source,{headers:{'X-Asset-Hash':hash.slice(0,10)}}); if(cached)held.set(key,response()); - const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,Lazy:{manifest:{appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; - const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {vm.runInContext(source,context);queueMicrotask(()=>node.onload());}}}}; + if(previous){held.set(oldKey,new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}));held.set('/__ytp_asset_state',Response.json({previous:{files:{'/app.js':{h:oldHash}},groups:{core:{contract,files:['/app.js']}}}}));} + const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,AssetSyncCore:require('./asset-sync-core'),navigator:{serviceWorker:{controller:{}}},Lazy:{manifest:{groups:{core:{contract:1,files:['/app.js']}},appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return previous?new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}):response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; + const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {vm.runInContext(node.src===oldKey?oldSource:source,context);queueMicrotask(()=>node.onload());}}}}; root.window=root;const context=vm.createContext(root); vm.runInContext(readFileSync(require.resolve('./app-bootstrap.js'),'utf8'),context); - return {root,held,appended,listeners,key,calls:()=>calls,doc,response}; + return {root,held,appended,listeners,key,calls:()=>calls,doc,response,oldKey}; } test('cold boot caches verified app before execution so worker skips its download',async()=>{ const f=fixture();await f.root.AppBootstrap.ready;assert.equal(f.calls(),1);assert.ok(f.held.has(f.key));assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1);assert.equal(f.appended[0].src,undefined);assert.equal(f.appended[0].removed,true); @@ -43,3 +45,12 @@ test('the early head response is consumed without a second page fetch',async()=> test('insecure local HTTP boot retains external execution without WebCrypto',async()=>{ const f=fixture({insecure:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); }); + + +test('missing current app uses verified same-contract N-1 offline through the controlling worker',async()=>{ + const f=fixture({previous:true});await f.root.AppBootstrap.ready; + assert.equal(f.appended[0].src,f.oldKey);assert.equal(f.root.oldApp,true);assert.equal(f.root.bootRuns,1);assert.equal(f.held.has(f.key),false); +}); +test('an incompatible previous core never executes against the new shell',async()=>{ + const f=fixture({previous:true,contract:2});await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); +}); From c4a512bea63da4c9c875501038727768080496c1 Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 09:18:51 +0800 Subject: [PATCH 50/81] Guard stale app execution against feature contract changes --- frontend/app-bootstrap.js | 3 +- frontend/app-bootstrap.test.js | 7 ++ perf/README.md | 4 + perf/baseline.mjs | 12 +-- perf/lazy.mjs | 19 ++++- perf/results/phase6-lazy-2026-10-08.json | 97 ++++++++++++++++++++++++ plans/phase6-investigation.md | 9 +++ 7 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 perf/results/phase6-lazy-2026-10-08.json diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js index 398ca77..09b95e4 100644 --- a/frontend/app-bootstrap.js +++ b/frontend/app-bootstrap.js @@ -42,7 +42,8 @@ const previousKey=state && root.AssetSyncCore.fallback(manifest,state.previous,'/app.js'); const previous=previousKey && await cache.match(previousKey); const previousHash=state?.previous?.files['/app.js']?.h; - if(root.navigator?.serviceWorker?.controller && previous?.ok && previous.headers.get('X-Asset-Hash')===previousHash) { + const contractsMatch=state?.previous && Object.entries(manifest.groups).every(([name,group])=>state.previous.groups[name]?.contract===group.contract); + if(contractsMatch && root.navigator?.serviceWorker?.controller && previous?.ok && previous.headers.get('X-Asset-Hash')===previousHash) { await verified(previous,previousHash); delete root.Lazy.appResponse; return external(previousKey); diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js index ea11df6..f7ed8c5 100644 --- a/frontend/app-bootstrap.test.js +++ b/frontend/app-bootstrap.test.js @@ -54,3 +54,10 @@ test('missing current app uses verified same-contract N-1 offline through the co test('an incompatible previous core never executes against the new shell',async()=>{ const f=fixture({previous:true,contract:2});await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); }); + + +test('a feature contract change also prevents stale core execution',async()=>{ + const f=fixture({previous:true});f.root.Lazy.manifest.groups['feature:test']={contract:2,files:[]}; + const state=await f.held.get('/__ytp_asset_state').json();state.previous.groups['feature:test']={contract:1,files:[]};f.held.set('/__ytp_asset_state',Response.json(state)); + await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); +}); diff --git a/perf/README.md b/perf/README.md index 96b74cb..f2dac35 100644 --- a/perf/README.md +++ b/perf/README.md @@ -350,3 +350,7 @@ then use the page FCP to locate the rendering dependency. Pass `--assert-cold` on new builds to require exactly one positive-byte app.js response in every cold sample, including worker installation. Omit this assertion when diagnosing historical regressions. + +Phase 6 counts its fetch-owned app.js response in initial JS/CSS bytes. Since the +bootstrap consumes that response asynchronously, DOMContentLoaded no longer means +app execution is complete; compare the existing actual boot-done landmark. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index b6321db..f1365e6 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -377,8 +377,8 @@ async function runColdScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { - initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -486,8 +486,8 @@ async function runWarmScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { - initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, @@ -567,8 +567,8 @@ async function runOfflineScenario({ browserType, server, proxy, profile }) { const fcp = paint.find((p) => p.name === 'first-contentful-paint'); return { - initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).reduce((sum,entry)=>sum+entry.encodedBodySize,0), - initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&['script','link','css'].includes(entry.initiatorType)).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), + initialJsCss: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).reduce((sum,entry)=>sum+entry.encodedBodySize,0), + initialAssetRequests: performance.getEntriesByType('resource').filter(entry=>/\.(?:js|css)(?:[?#]|$)/.test(entry.name)&&entry.startTime <= nav.domContentLoadedEventEnd&&(['script','link','css'].includes(entry.initiatorType)||(entry.initiatorType==='fetch'&&new URL(entry.name).pathname==='/app.js'))).map(entry=>({url:entry.name,bytes:entry.encodedBodySize,start:entry.startTime,responseStart:entry.responseStart,end:entry.responseEnd,initiator:entry.initiatorType})), fcp: fcp ? Math.round(fcp.startTime) : null, lcp: window.__lcp ? Math.round(window.__lcp) : null, domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null, diff --git a/perf/lazy.mjs b/perf/lazy.mjs index b1afee7..77a21de 100644 --- a/perf/lazy.mjs +++ b/perf/lazy.mjs @@ -84,6 +84,23 @@ async function run(name){ await page.evaluate(async()=>{await Lazy.load('feature:export');await Lazy.load('feature:video-edit');}); assert.equal(proxy.getStats().requestCount,before,'all warmed extension assets stay offline'); await start();disconnected=false;await proxy.setOffline(false);await page.evaluate(()=>localStorage.removeItem('perf-offline')); + // Change only app bytes, then prove loss of its current cache entry can boot + // the compatible N-1 core offline without weakening the inline CSP policy. + await stop();writeFileSync(join(cwd,'public/app.js'),readFileSync(join(cwd,'public/app.js'),'utf8')+'\n// phase6 app eviction probe\n');await start(); + const appTarget=await(await fetch(origin+'/api/manifest')).json(); + await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();await r.update();}); + await wait(page,async tag=>{const r=await navigator.serviceWorker.getRegistration();return r?.waiting&&(await SwUpdate.askCacheStatus(r.waiting))?.version===tag;},appTarget.buildTag); + await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});}); + await wait(page,async tag=>{const c=await caches.open('ytplayer-assets');return(await(await c.match('/__ytp_asset_state')).json()).current.buildTag===tag;},appTarget.buildTag); + const appKey='/app.js?v='+appTarget.files['/app.js'].h; + await page.evaluate(async key=>{await(await caches.open('ytplayer-assets')).delete(key);},appKey); + await stop();disconnected=true;await proxy.setOffline(true); + const probe=await context.newPage();probe.on('pageerror',e=>errors.push({message:e.message,disconnected})); + const offlineBefore=proxy.getStats().requestCount;await probe.goto(origin);await probe.waitForFunction(()=>typeof data!=='undefined'&&typeof Player!=='undefined'&&document.querySelector('#carModeBtn')); + assert.equal(await probe.evaluate(async key=>!!await(await caches.open('ytplayer-assets')).match(key),appKey),false,'N-1 never poisons the current app key'); + assert.equal(proxy.getStats().requestCount,offlineBefore,'N-1 app boot is entirely offline'); + await probe.close();await start();disconnected=false;await proxy.setOffline(false); + await page.evaluate(async key=>{const r=await fetch(key+'&__ytpfresh=1');if(r.headers.get('X-Asset-Hash')!==key.split('v=')[1])throw Error('Wrong repair body');await(await caches.open('ytplayer-assets')).put(key,r);},appKey); // Keep an old tab whose core and group contracts remain those of build N. const old=await context.newPage();old.on('pageerror',e=>errors.push({message:e.message,disconnected}));await old.goto(origin);await old.waitForSelector('#carModeBtn'); await old.evaluate(async()=>{window.__saveData=true;await Lazy.load('feature:setlist-import');window.__pinned=window.SetlistImport;}); @@ -128,7 +145,7 @@ async function run(name){ const offlineTransportErrors=errors.filter(error=>name==='webkit'&&error.disconnected&&(error.message==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(error.message))); assert.deepEqual(errors.filter(error=>!offlineTransportErrors.includes(error)),[]); if(offlineTransportErrors.length)assert.ok(failedRequests.some(url=>/\/api\/(?:recommendations|version)/.test(url))); - results.push({browser:name,sourceBuildTag:previous.buildTag,classicSharedDefaults:true,cssOrderPreserved:true,settingsSearch:true,carControls:4,offlineFeature:true,firstUseNetwork:0,layoutsOffline:['glass-stage','bento-hub','f7-swipe','classic'],pinned:true,compatibleUnexecutedNewURL:true,incompatibleN1ReloadRequired:true,stagedN1:true,playbackGuard:true,prePaintLayout:true,offlineSettingsPanels:true,scriptErrors:[],offlineTransportErrors}); + results.push({browser:name,sourceBuildTag:previous.buildTag,classicSharedDefaults:true,cssOrderPreserved:true,settingsSearch:true,carControls:4,offlineFeature:true,firstUseNetwork:0,layoutsOffline:['glass-stage','bento-hub','f7-swipe','classic'],pinned:true,compatibleUnexecutedNewURL:true,incompatibleN1ReloadRequired:true,stagedN1:true,appEvictionN1Offline:true,playbackGuard:true,prePaintLayout:true,offlineSettingsPanels:true,scriptErrors:[],offlineTransportErrors}); console.log(name,'PASS'); } finally {await browser?.close();await proxy?.close();await stop();} } diff --git a/perf/results/phase6-lazy-2026-10-08.json b/perf/results/phase6-lazy-2026-10-08.json new file mode 100644 index 0000000..7901450 --- /dev/null +++ b/perf/results/phase6-lazy-2026-10-08.json @@ -0,0 +1,97 @@ +{ + "results": [ + { + "browser": "chromium", + "sourceBuildTag": "41a7ba2c29a3", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "appEvictionN1Offline": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [] + }, + { + "browser": "webkit", + "sourceBuildTag": "41a7ba2c29a3", + "classicSharedDefaults": true, + "cssOrderPreserved": true, + "settingsSearch": true, + "carControls": 4, + "offlineFeature": true, + "firstUseNetwork": 0, + "layoutsOffline": [ + "glass-stage", + "bento-hub", + "f7-swipe", + "classic" + ], + "pinned": true, + "compatibleUnexecutedNewURL": true, + "incompatibleN1ReloadRequired": true, + "stagedN1": true, + "appEvictionN1Offline": true, + "playbackGuard": true, + "prePaintLayout": true, + "offlineSettingsPanels": true, + "scriptErrors": [], + "offlineTransportErrors": [ + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:36117/api/version.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:36117/api/recommendations?fp=163577c02a53bc40.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:36117/api/version.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:36117/api/recommendations?fp=163577c02a53bc40.", + "disconnected": true + }, + { + "message": "TypeError: Load failed", + "disconnected": true + }, + { + "message": "/127.0.0.1:36117/api/version.", + "disconnected": true + } + ] + } + ] +} diff --git a/plans/phase6-investigation.md b/plans/phase6-investigation.md index ad076c1..c8e7a3e 100644 --- a/plans/phase6-investigation.md +++ b/plans/phase6-investigation.md @@ -76,3 +76,12 @@ all samples. Full-harness configurations now reset to the base tree before each browser/profile, preventing a preceding synthetic update from contaminating the next cold build. The historical invalid media fixture remains unchanged: home launch only, not autoplay/audio latency. + + +Self-review added explicit N-1 app boot after eviction: verify the retained body +and use its exact classic URL through the controlling worker. It never fills the +new key with old bytes. Stale core execution additionally requires every group +contract to match the running shell's expectations; a core or feature contract +change rejects it. Both-engine lazy smoke now changes app bytes, evicts the new +entry, boots N-1 offline, then repairs the current entry before the existing +feature pinning/contract/playback checks. No source in app.js changed. From 57edb410c3f637e8b4e4afb96ee33d3a618aa7ff Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 09:43:51 +0800 Subject: [PATCH 51/81] Keep native Chromium loading and prevent stale browser cache entries --- frontend/app-bootstrap.js | 4 +- frontend/app-bootstrap.test.js | 17 ++- frontend/asset-worker.test.js | 4 +- frontend/lazy.js | 7 +- frontend/lazy.test.js | 15 ++- frontend/sw.js | 8 +- perf/README.md | 3 + perf/baseline.mjs | 16 +-- perf/results/phase6-lazy-2026-10-08.json | 14 +-- perf/results/phase6-native-chromium-warm.json | 101 ++++++++++++++++++ plans/phase6-investigation.md | 13 +++ 11 files changed, 179 insertions(+), 23 deletions(-) create mode 100644 perf/results/phase6-native-chromium-warm.json diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js index 09b95e4..4359af0 100644 --- a/frontend/app-bootstrap.js +++ b/frontend/app-bootstrap.js @@ -27,11 +27,12 @@ return {bytes,digest}; } async function start() { - if(!manifest.appCache || !root.crypto?.subtle)return external(key); + if(!manifest.appCache || !root.crypto?.subtle || (!root.Lazy.captureApp&&!root.navigator?.serviceWorker?.controller))return external(key); const expected=manifest.files['/app.js'].h; let cache; try { cache=await root.caches?.open('ytplayer-assets'); } catch {} let response=await cache?.match(key); + if(!root.Lazy.captureApp && response?.ok && response.headers.get('X-Asset-Hash')===expected)return external(key); if(!response || response.headers.get('X-Asset-Hash')!==expected) { try { response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); } catch {} } @@ -56,6 +57,7 @@ // CacheStorage may share a full quota with saved music. Never remove data // to make room; boot from these verified bytes even if caching is refused. try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } + if(!root.Lazy.captureApp)return external(key); const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); execute(node); } diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js index f7ed8c5..d7b5778 100644 --- a/frontend/app-bootstrap.test.js +++ b/frontend/app-bootstrap.test.js @@ -3,14 +3,14 @@ const assert=require('node:assert/strict'); const {webcrypto,createHash}=require('node:crypto'); const vm=require('node:vm'); const {readFileSync}=require('node:fs'); -function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false,previous=false,contract=1}={}){ +function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false,previous=false,contract=1,capture=true,controller=true}={}){ const source='window.appRuns=(window.appRuns||0)+1; window.boot=()=>window.bootRuns=(window.bootRuns||0)+1; document.addEventListener("DOMContentLoaded",boot);',hash=createHash('sha256').update(source).digest('hex'), key='/app.js?v='+hash.slice(0,10); const oldSource='window.oldApp=true;'+source, oldHash=createHash('sha256').update(oldSource).digest('hex').slice(0,10), oldKey='/app.js?v='+oldHash; const held=new Map(), appended=[],listeners={};let calls=0; const response=()=>new Response(tampered?'bad':source,{headers:{'X-Asset-Hash':hash.slice(0,10)}}); if(cached)held.set(key,response()); if(previous){held.set(oldKey,new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}));held.set('/__ytp_asset_state',Response.json({previous:{files:{'/app.js':{h:oldHash}},groups:{core:{contract,files:['/app.js']}}}}));} - const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,AssetSyncCore:require('./asset-sync-core'),navigator:{serviceWorker:{controller:{}}},Lazy:{manifest:{groups:{core:{contract:1,files:['/app.js']}},appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return previous?new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}):response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; + const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,AssetSyncCore:require('./asset-sync-core'),navigator:{serviceWorker:{controller:controller?{}:null}},Lazy:{captureApp:capture,manifest:{groups:{core:{contract:1,files:['/app.js']}},appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return previous?new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}):response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {vm.runInContext(node.src===oldKey?oldSource:source,context);queueMicrotask(()=>node.onload());}}}}; root.window=root;const context=vm.createContext(root); vm.runInContext(readFileSync(require.resolve('./app-bootstrap.js'),'utf8'),context); @@ -61,3 +61,16 @@ test('a feature contract change also prevents stale core execution',async()=>{ const state=await f.held.get('/__ytp_asset_state').json();state.previous.groups['feature:test']={contract:1,files:[]};f.held.set('/__ytp_asset_state',Response.json(state)); await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); }); + + +test('native-cache engines use their external script and keep normal code-cache behavior',async()=>{ + const f=fixture({capture:false,controller:false});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); +}); + + +test('native-cache engines still reject an incompatible retained core',async()=>{ + const f=fixture({capture:false,previous:true,contract:2});await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); +}); +test('native-cache engines use the validated current cache entry without decoding its body',async()=>{ + const f=fixture({capture:false,cached:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); +}); diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index e84da7b..7b766a7 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -15,10 +15,10 @@ test('staged same-contract responses use verified N-1 without poisoning the new const e=environment(); const cache=await e.storage.open(core.CACHE); const old={buildTag:'old',files:{'/extra.js':{h:'old'}},groups:{core:{files:[],contract:1},'feature:extra':{files:['/extra.js'],contract:1,background:true}}}; e.m.groups.core.contract=1; e.m.groups['feature:extra']={files:['/extra.js'],contract:1,background:true}; e.m.files['/extra.js']={h:'new'}; - await cache.put(core.STATE,Response.json({current:old})); await cache.put('/extra.js?v=old',new Response('old body',{headers:{'X-Asset-Hash':'old'}})); + await cache.put(core.STATE,Response.json({current:old})); await cache.put('/extra.js?v=old',new Response('old body',{headers:{'X-Asset-Hash':'old','Cache-Control':'public, max-age=31536000, immutable','Content-Encoding':'gzip','Content-Length':'9'}})); await e.dispatch('install'); await e.dispatch('activate'); assert.equal(await cache.match('/extra.js?v=new'),undefined); - const stale=await e.request('/extra.js?v=new'); assert.equal(await stale.text(),'old body');assert.equal(stale.headers.get('X-Asset-Hash'),'old');assert.equal(await cache.match('/extra.js?v=new'),undefined); + const stale=await e.request('/extra.js?v=new'); assert.equal(await stale.text(),'old body');assert.equal(stale.headers.get('X-Asset-Hash'),'old');assert.equal(stale.headers.get('Cache-Control'),'no-store');assert.equal(stale.headers.get('Content-Encoding'),null);assert.equal(stale.headers.get('Content-Length'),null);assert.equal(await cache.match('/extra.js?v=new'),undefined); await e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:true}}); assert.equal(await cache.match('/extra.js?v=new'),undefined); await e.dispatch('message',{data:{type:'WARM_ASSETS',saveData:false}}); assert.equal((await cache.match('/extra.js?v=new')).headers.get('X-Asset-Hash'),'new'); assert.equal((await e.request('/extra.js?v=new')).headers.get('X-Asset-Hash'),'new'); diff --git a/frontend/lazy.js b/frontend/lazy.js index 6b8214b..58412c8 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -124,7 +124,9 @@ }; // Own this response once. Classic-script and fetch preloads do not share // their cached bodies in WebKit; the later bootstrap consumes this promise. - if(manifest.appCache && root.crypto?.subtle) { + const agent=root.navigator.userAgent || ''; + api.captureApp=!!(manifest.appCache && root.crypto?.subtle && /AppleWebKit\//.test(agent) && !/(?:Chrome|Chromium|Edg|OPR)\//.test(agent)); + if(api.captureApp) { api.appResponse=(async()=>{ const key=url('/app.js'); try { @@ -134,6 +136,9 @@ return root.fetch(key,{credentials:'same-origin'}); })(); api.appResponse.catch(()=>{}); + } else if(manifest.appCache) { + // Preserve native script/code-cache reuse in engines without the WebKit gap. + const preload=doc.createElement('link');preload.rel='preload';preload.as='script';preload.href=url('/app.js');doc.head.append(preload); } root.Lazy = api; root.navigator.serviceWorker?.addEventListener('message',event=>{ diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index 516c3de..fddcfdb 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -2,12 +2,12 @@ const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const vm = require('node:vm'); -function fixture(current, held = [], appCache = false) { +function fixture(current, held = [], appCache = false, userAgent = 'AppleWebKit/605.1 Safari/605.1') { const inserted = [], listeners = {}, writes = [], fetched = []; const manifest = { buildTag: 'own', appCache, groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/app.js':{h:'a'}, '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } }; const doc = { readyState:'loading', documentElement: { dataset:{} }, getElementById: () => ({ textContent:JSON.stringify(manifest) }), querySelectorAll: () => [], createElement: tag => ({ tagName:tag.toUpperCase() }), write: value => writes.push(value), addEventListener: (t,f) => listeners[t]=f }; doc.head = { append: node => { inserted.push(node); queueMicrotask(() => node.onload?.()); } }; - const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{}, addEventListener(){} }; + const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{userAgent}, addEventListener(){} }; if (current) root.caches = { open: async () => ({ match: async key => key === '/__ytp_asset_state' ? new Response(JSON.stringify({current})) : held.includes(key) ? new Response('', {headers:{'X-Asset-Hash':key.split('=')[1]}}) : undefined }) }; root.window=root; root.globalThis=root; vm.runInNewContext(readFileSync(require.resolve('./lazy.js'),'utf8'), root); @@ -97,3 +97,14 @@ test('head capture is cache-first even before a worker controls the page',async( const f=fixture(fixture().manifest,['/app.js?v=a'],true);const response=await f.root.Lazy.appResponse; assert.equal(response.headers.get('X-Asset-Hash'),'a');assert.deepEqual(f.fetched,[]); }); + + +test('Chromium retains native script loading and only preloads the current app URL',async()=>{ + const f=fixture(null,[],true,'AppleWebKit/537.36 Chrome/140.0 Safari/537.36'); + assert.equal(f.root.Lazy.captureApp,false);assert.equal(f.root.Lazy.appResponse,undefined);assert.deepEqual(f.fetched,[]); + assert.equal(f.inserted.length,1);assert.equal(f.inserted[0].rel,'preload');assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a'); +}); +test('iOS Chromium-branded browsers still use their WebKit response capture',async()=>{ + const f=fixture(null,[],true,'AppleWebKit/605.1 CriOS/140.0 Mobile Safari/605.1');await f.root.Lazy.appResponse; + assert.equal(f.root.Lazy.captureApp,true);assert.deepEqual(f.fetched,['/app.js?v=a']); +}); diff --git a/frontend/sw.js b/frontend/sw.js index 410430c..6d29ad9 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -576,7 +576,13 @@ async function assetFetch(request, clientId) { if(state.current.files[path]?.h === h) { const previousKey=AssetSyncCore.fallback(state.current,state.previous,path); const previousResponse=previousKey && await cache.match(previousKey); - if(previousResponse && previousResponse.headers.get('X-Asset-Hash')===state.previous.files[path].h) return previousResponse; + if(previousResponse && previousResponse.headers.get('X-Asset-Hash')===state.previous.files[path].h) { + // A stale body returned under a new URL must not poison the browser's + // resource cache either. Its decoded stream has no transport encoding. + const headers=new Headers(previousResponse.headers);headers.set('Cache-Control','no-store'); + for(const name of ['Content-Encoding','Content-Length','Transfer-Encoding'])headers.delete(name); + return new Response(previousResponse.body,{status:previousResponse.status,headers}); + } } try { const r = await fetch(key); if(r.ok && r.headers.get('X-Asset-Hash') !== h) return new Response('Asset version unavailable',{status:409}); if(r.ok && request.method !== 'HEAD') await cache.put(key,r.clone()); return r; } catch { return new Response('Offline',{status:503}); } } diff --git a/perf/README.md b/perf/README.md index f2dac35..342df37 100644 --- a/perf/README.md +++ b/perf/README.md @@ -354,3 +354,6 @@ when diagnosing historical regressions. Phase 6 counts its fetch-owned app.js response in initial JS/CSS bytes. Since the bootstrap consumes that response asynchronously, DOMContentLoaded no longer means app execution is complete; compare the existing actual boot-done landmark. + +`--scenario warm,offline,update-js,update-css,update-feature` runs a regression +sweep without repeating an already-completed cold acceptance run. diff --git a/perf/baseline.mjs b/perf/baseline.mjs index f1365e6..7667062 100755 --- a/perf/baseline.mjs +++ b/perf/baseline.mjs @@ -709,6 +709,8 @@ async function main() { if (options.browser === 'all' || options.browser === 'chromium') browsers.push(pw.chromium); if (options.browser === 'all' || options.browser === 'webkit') browsers.push(pw.webkit); + const requestedScenarios=new Set(options.scenario.split(',')); + const wants=name=>requestedScenarios.has('all')||requestedScenarios.has(name); const profiles = []; if (options.profile === 'all' || options.profile === 'lte') profiles.push('lte'); if (options.profile === 'all' || options.profile === 'lossy') profiles.push('lossy'); @@ -773,7 +775,7 @@ async function main() { console.log(`Proxy listening on port ${proxy.port} (mode: ${proxyProfile})`); // 1. Cold Scenario - if (options.scenario === 'all' || options.scenario === 'cold') { + if (wants('cold')) { console.log(` [Scenario: Cold Load] running ${options.runs} iterations...`); const coldRuns = []; for (let r = 0; r < options.runs; r++) { @@ -781,7 +783,7 @@ async function main() { const res = await runColdScenario({ browserType: bType, server, proxy, profile: prof }); if(options.assertCold)assertColdAssets(res.requests); coldRuns.push(res); - console.log(`done (${res.wireBytes} bytes, ${res.requestCount} reqs, boot=${res.bootDone}ms)`); + console.log(`done (${res.wireBytes} bytes, ${res.requestCount} reqs, fcp=${res.fcp}ms, boot=${res.bootDone}ms)`); } results.browsers[bName][prof].cold = { @@ -807,7 +809,7 @@ async function main() { } // 2. Warm Scenario - if (options.scenario === 'all' || options.scenario === 'warm') { + if (wants('warm')) { console.log(` [Scenario: Warm Load] running ${options.runs} iterations...`); const warmRuns = []; for (let r = 0; r < options.runs; r++) { @@ -829,7 +831,7 @@ async function main() { } // 3. Offline Scenario - if (options.scenario === 'all' || options.scenario === 'offline') { + if (wants('offline')) { console.log(` [Scenario: Offline Reload] running ${options.runs} iterations...`); const offRuns = []; for (let r = 0; r < options.runs; r++) { @@ -851,7 +853,7 @@ async function main() { } // 4. Update N -> N+1 (JS) - if (options.scenario === 'all' || options.scenario === 'update-js') { + if (wants('update-js')) { console.log(` [Scenario: Update N->N+1 (1-line app.js)] running ${options.runs} iterations...`); const updJsRuns = []; for (let r = 0; r < options.runs; r++) { @@ -878,7 +880,7 @@ async function main() { } // 5. Update N -> N+1 (CSS) - if (options.scenario === 'all' || options.scenario === 'update-css') { + if (wants('update-css')) { console.log(` [Scenario: Update N->N+1 (1-line theme-glass.css)] running ${options.runs} iterations...`); const updCssRuns = []; for (let r = 0; r < options.runs; r++) { @@ -906,7 +908,7 @@ async function main() { }; } - if ((options.scenario === 'all' || options.scenario === 'update-feature') && existsSync(path.join(treeBase,'presenter.js'))) { + if ((wants('update-feature')) && existsSync(path.join(treeBase,'presenter.js'))) { console.log(` [Scenario: Update split-out presenter, including idle cache fill] running ${options.runs} iterations...`); const runs=[]; for(let r=0;r Date: Thu, 8 Oct 2026 10:05:38 +0800 Subject: [PATCH 52/81] Enforce stale core contracts in the worker without native startup I/O --- frontend/app-bootstrap.js | 4 +--- frontend/app-bootstrap.test.js | 4 ++-- frontend/asset-sync-core.js | 3 +++ frontend/asset-sync-core.test.js | 7 +++++++ frontend/asset-worker.test.js | 13 ++++++++++++- perf/results/phase6-lazy-2026-10-08.json | 14 +++++++------- plans/phase6-investigation.md | 8 ++++++++ 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js index 4359af0..9998a2e 100644 --- a/frontend/app-bootstrap.js +++ b/frontend/app-bootstrap.js @@ -27,12 +27,11 @@ return {bytes,digest}; } async function start() { - if(!manifest.appCache || !root.crypto?.subtle || (!root.Lazy.captureApp&&!root.navigator?.serviceWorker?.controller))return external(key); + if(!manifest.appCache || !root.crypto?.subtle || !root.Lazy.captureApp)return external(key); const expected=manifest.files['/app.js'].h; let cache; try { cache=await root.caches?.open('ytplayer-assets'); } catch {} let response=await cache?.match(key); - if(!root.Lazy.captureApp && response?.ok && response.headers.get('X-Asset-Hash')===expected)return external(key); if(!response || response.headers.get('X-Asset-Hash')!==expected) { try { response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); } catch {} } @@ -57,7 +56,6 @@ // CacheStorage may share a full quota with saved music. Never remove data // to make room; boot from these verified bytes even if caching is refused. try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } - if(!root.Lazy.captureApp)return external(key); const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); execute(node); } diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js index d7b5778..d790f97 100644 --- a/frontend/app-bootstrap.test.js +++ b/frontend/app-bootstrap.test.js @@ -11,7 +11,7 @@ function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=f if(cached)held.set(key,response()); if(previous){held.set(oldKey,new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}));held.set('/__ytp_asset_state',Response.json({previous:{files:{'/app.js':{h:oldHash}},groups:{core:{contract,files:['/app.js']}}}}));} const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,AssetSyncCore:require('./asset-sync-core'),navigator:{serviceWorker:{controller:controller?{}:null}},Lazy:{captureApp:capture,manifest:{groups:{core:{contract:1,files:['/app.js']}},appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return previous?new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}):response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; - const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {vm.runInContext(node.src===oldKey?oldSource:source,context);queueMicrotask(()=>node.onload());}}}}; + const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {queueMicrotask(async()=>{if(previous && node.src===key){const state=await held.get('/__ytp_asset_state').clone().json();if(!root.AssetSyncCore.fallback(root.Lazy.manifest,state.previous,'/app.js'))return node.onerror();vm.runInContext(oldSource,context);}else vm.runInContext(node.src===oldKey?oldSource:source,context);node.onload();});}}}}; root.window=root;const context=vm.createContext(root); vm.runInContext(readFileSync(require.resolve('./app-bootstrap.js'),'utf8'),context); return {root,held,appended,listeners,key,calls:()=>calls,doc,response,oldKey}; @@ -69,7 +69,7 @@ test('native-cache engines use their external script and keep normal code-cache test('native-cache engines still reject an incompatible retained core',async()=>{ - const f=fixture({capture:false,previous:true,contract:2});await assert.rejects(f.root.AppBootstrap.ready,/hash/);assert.equal(f.root.appRuns,undefined); + const f=fixture({capture:false,previous:true,contract:2});await assert.rejects(f.root.AppBootstrap.ready,/Unable to load player/);assert.equal(f.root.appRuns,undefined); }); test('native-cache engines use the validated current cache entry without decoding its body',async()=>{ const f=fixture({capture:false,cached:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); diff --git a/frontend/asset-sync-core.js b/frontend/asset-sync-core.js index e8d951c..32f4519 100644 --- a/frontend/asset-sync-core.js +++ b/frontend/asset-sync-core.js @@ -41,6 +41,9 @@ const group = Object.keys(manifest.groups).find(name => manifest.groups[name].files.includes(path)); if (!group || !previous.groups[group]?.files.includes(path) || manifest.groups[group].contract !== previous.groups[group].contract) return null; + // A stale core must understand every group contract in the new shell. + if (path === "/app.js" && Object.entries(manifest.groups).some(([name, entry]) => + previous.groups[name]?.contract !== entry.contract)) return null; return url(path, previous.files[path]); } diff --git a/frontend/asset-sync-core.test.js b/frontend/asset-sync-core.test.js index 2c9a9d4..a8fbd2f 100644 --- a/frontend/asset-sync-core.test.js +++ b/frontend/asset-sync-core.test.js @@ -45,3 +45,10 @@ test('removing group membership retains the old tab URL even if the physical fil const previous=manifest(),current=manifest();current.groups.core.files=['/index.html']; assert.ok(core.retained(current,previous).has('/a.js?v=a')); }); + + +test('stale app core requires every feature contract to match the new shell',()=>{ + const old={files:{'/app.js':{h:'old'}},groups:{core:{contract:1,files:['/app.js']},extra:{contract:1,files:[]}}}; + const next=structuredClone(old);next.files['/app.js'].h='new';next.groups.extra.contract=2; + assert.equal(core.fallback(next,old,'/app.js'),null);next.groups.extra.contract=1;assert.equal(core.fallback(next,old,'/app.js'),'/app.js?v=old'); +}); diff --git a/frontend/asset-worker.test.js b/frontend/asset-worker.test.js index 7b766a7..1aa6b2c 100644 --- a/frontend/asset-worker.test.js +++ b/frontend/asset-worker.test.js @@ -6,7 +6,7 @@ function environment(){ vm.runInNewContext(fs.readFileSync(__dirname+'/sw.js','utf8'),sandbox); async function dispatch(t,e={}){let p;listeners[t]({...e,waitUntil:v=>p=v});await p} async function request(url,mode='cors',clientId='new'){let p;listeners.fetch({request:{url:'https://local'+url,method:'GET',mode},clientId,respondWith:v=>p=v});return p} - return {storage,m,skips,fetches,dispatch,request}; + return {storage,m,skips,fetches,dispatch,request,sandbox}; } test('install does not activate or publish; CACHE_STATUS is honest; activation commits and exact requests self-heal',async()=>{const e=environment();await e.dispatch('install');assert.equal(e.skips.length,0);const cache=await e.storage.open(core.CACHE);assert.equal(await core.state(cache),null);let reply;await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,true);await e.dispatch('activate');assert.equal((await core.state(cache)).current.buildTag,'next');assert.equal((await e.request('/playlist/x','navigate')).headers.get('X-Asset-Hash'),'index');await cache.delete('/app.js?v=app');await e.dispatch('message',{data:{type:'CACHE_STATUS'},ports:[{postMessage:r=>reply=r}]});assert.equal(reply.ready,false);assert.equal(reply.missing,1);assert.equal(reply.version,'next');assert.equal((await e.request('/app.js')).headers.get('X-Asset-Hash'),'app');assert.ok(await cache.match('/app.js?v=app'));assert.equal(await cache.match('/app.js?v=stale'),undefined);assert.equal((await e.request('/app.js?v=stale')).status,409);}); test('reported playback defers explicit activation until pause; install never calls skipWaiting',async()=>{const e=environment(),source={id:'p'};await e.dispatch('message',{data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:true}});await e.dispatch('message',{source,data:{type:'SKIP_WAITING'}});assert.equal(e.skips.length,0);await e.dispatch('message',{source,data:{type:'PLAYING',value:false}});assert.equal(e.skips.length,1);}); @@ -51,3 +51,14 @@ test('page-captured app is reused on first install without a worker download',as assert.equal(await(await cache.match('/app.js?v=app')).text(),'page captured app'); assert.equal(e.skips.length,0);assert.equal(await core.state(cache),null); }); + + +test('worker never supplies stale app to a native script when a feature contract changed',async()=>{ + const e=environment(),cache=await e.storage.open(core.CACHE); + const old={buildTag:'old',files:{'/app.js':{h:'old'}},groups:{core:{contract:1,files:['/app.js']},extra:{contract:1,files:[]}}}; + e.m.groups.core.contract=1;e.m.groups.extra={contract:2,background:true,files:[]}; + await cache.put(core.STATE,Response.json({current:old}));await cache.put('/app.js?v=old',new Response('old app',{headers:{'X-Asset-Hash':'old'}})); + await e.dispatch('install');await e.dispatch('activate');await cache.delete('/app.js?v=app'); + e.sandbox.fetch=async()=>{throw Error('offline')}; + const response=await e.request('/app.js?v=app');assert.equal(response.status,503);assert.equal(await response.text(),'Offline'); +}); diff --git a/perf/results/phase6-lazy-2026-10-08.json b/perf/results/phase6-lazy-2026-10-08.json index b4734bc..5b3d1ef 100644 --- a/perf/results/phase6-lazy-2026-10-08.json +++ b/perf/results/phase6-lazy-2026-10-08.json @@ -2,7 +2,7 @@ "results": [ { "browser": "chromium", - "sourceBuildTag": "562f4031bcb7", + "sourceBuildTag": "22eb7414f94c", "classicSharedDefaults": true, "cssOrderPreserved": true, "settingsSearch": true, @@ -28,7 +28,7 @@ }, { "browser": "webkit", - "sourceBuildTag": "562f4031bcb7", + "sourceBuildTag": "22eb7414f94c", "classicSharedDefaults": true, "cssOrderPreserved": true, "settingsSearch": true, @@ -56,7 +56,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33967/api/version.", + "message": "/127.0.0.1:33445/api/version.", "disconnected": true }, { @@ -64,7 +64,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33967/api/recommendations?fp=163577c02a53bc40.", + "message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.", "disconnected": true }, { @@ -72,7 +72,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33967/api/version.", + "message": "/127.0.0.1:33445/api/version.", "disconnected": true }, { @@ -80,7 +80,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33967/api/recommendations?fp=163577c02a53bc40.", + "message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.", "disconnected": true }, { @@ -88,7 +88,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33967/api/version.", + "message": "/127.0.0.1:33445/api/version.", "disconnected": true } ] diff --git a/plans/phase6-investigation.md b/plans/phase6-investigation.md index 9810696..c089e04 100644 --- a/plans/phase6-investigation.md +++ b/plans/phase6-investigation.md @@ -98,3 +98,11 @@ native cache hits avoid decoding/rehashing; retained core fallback still enforce all group contracts. The new worker marks stale responses no-store and strips decoded transport headers, preventing browser resource-cache poisoning under a new URL. CacheStorage's exact keys and previous entries stay unchanged. + +The native-window contract lookup trial regressed Chromium warm boot (~698 ms). +It is rejected. The worker now owns the all-group stale app contract guard +(pure planner and actual worker VM tests first); native boot has no window-side +CacheStorage or hashing work. WebKit's byte-verified owned response path is +unchanged. The native fixture models the actual worker fallback decision instead +of a second page-side decision. All 221 frontend tests and 184 server tests pass; +both-engine lazy/offline/eviction/pinning/contracts/playback smoke passes. From 9408ee07e56db5bbb8319f8da862b549ab948bce Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 10:08:35 +0800 Subject: [PATCH 53/81] Limit the WebKit response handoff to uncontrolled visits --- frontend/lazy.js | 2 +- frontend/lazy.test.js | 10 ++++++++-- perf/results/phase6-lazy-2026-10-08.json | 14 +++++++------- plans/phase6-investigation.md | 7 +++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/frontend/lazy.js b/frontend/lazy.js index 58412c8..fe83a12 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -125,7 +125,7 @@ // Own this response once. Classic-script and fetch preloads do not share // their cached bodies in WebKit; the later bootstrap consumes this promise. const agent=root.navigator.userAgent || ''; - api.captureApp=!!(manifest.appCache && root.crypto?.subtle && /AppleWebKit\//.test(agent) && !/(?:Chrome|Chromium|Edg|OPR)\//.test(agent)); + api.captureApp=!!(manifest.appCache && !root.navigator.serviceWorker?.controller && root.crypto?.subtle && /AppleWebKit\//.test(agent) && !/(?:Chrome|Chromium|Edg|OPR)\//.test(agent)); if(api.captureApp) { api.appResponse=(async()=>{ const key=url('/app.js'); diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index fddcfdb..1e7d88a 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -2,12 +2,12 @@ const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const vm = require('node:vm'); -function fixture(current, held = [], appCache = false, userAgent = 'AppleWebKit/605.1 Safari/605.1') { +function fixture(current, held = [], appCache = false, userAgent = 'AppleWebKit/605.1 Safari/605.1', controlled = false) { const inserted = [], listeners = {}, writes = [], fetched = []; const manifest = { buildTag: 'own', appCache, groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/app.js':{h:'a'}, '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } }; const doc = { readyState:'loading', documentElement: { dataset:{} }, getElementById: () => ({ textContent:JSON.stringify(manifest) }), querySelectorAll: () => [], createElement: tag => ({ tagName:tag.toUpperCase() }), write: value => writes.push(value), addEventListener: (t,f) => listeners[t]=f }; doc.head = { append: node => { inserted.push(node); queueMicrotask(() => node.onload?.()); } }; - const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{userAgent}, addEventListener(){} }; + const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, crypto:{subtle:{}}, fetch:async key=>{fetched.push(key);return new Response('app');}, setTimeout, clearTimeout, navigator:{userAgent,serviceWorker:{controller:controlled?{}:null,addEventListener(){}}}, addEventListener(){} }; if (current) root.caches = { open: async () => ({ match: async key => key === '/__ytp_asset_state' ? new Response(JSON.stringify({current})) : held.includes(key) ? new Response('', {headers:{'X-Asset-Hash':key.split('=')[1]}}) : undefined }) }; root.window=root; root.globalThis=root; vm.runInNewContext(readFileSync(require.resolve('./lazy.js'),'utf8'), root); @@ -108,3 +108,9 @@ test('iOS Chromium-branded browsers still use their WebKit response capture',asy const f=fixture(null,[],true,'AppleWebKit/605.1 CriOS/140.0 Mobile Safari/605.1');await f.root.Lazy.appResponse; assert.equal(f.root.Lazy.captureApp,true);assert.deepEqual(f.fetched,['/app.js?v=a']); }); + +test('controlled WebKit visits use worker-cached native app scripts without a response handoff',async()=>{ + const f=fixture(null,[],true,'AppleWebKit/605.1 Safari/605.1',true); + assert.equal(f.root.Lazy.captureApp,false);assert.equal(f.root.Lazy.appResponse,undefined);assert.deepEqual(f.fetched,[]); + assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a'); +}); diff --git a/perf/results/phase6-lazy-2026-10-08.json b/perf/results/phase6-lazy-2026-10-08.json index 5b3d1ef..8a0c5b7 100644 --- a/perf/results/phase6-lazy-2026-10-08.json +++ b/perf/results/phase6-lazy-2026-10-08.json @@ -2,7 +2,7 @@ "results": [ { "browser": "chromium", - "sourceBuildTag": "22eb7414f94c", + "sourceBuildTag": "38131d1a6b5e", "classicSharedDefaults": true, "cssOrderPreserved": true, "settingsSearch": true, @@ -28,7 +28,7 @@ }, { "browser": "webkit", - "sourceBuildTag": "22eb7414f94c", + "sourceBuildTag": "38131d1a6b5e", "classicSharedDefaults": true, "cssOrderPreserved": true, "settingsSearch": true, @@ -56,7 +56,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33445/api/version.", + "message": "/127.0.0.1:43269/api/recommendations?fp=163577c02a53bc40.", "disconnected": true }, { @@ -64,7 +64,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.", + "message": "/127.0.0.1:43269/api/version.", "disconnected": true }, { @@ -72,7 +72,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33445/api/version.", + "message": "/127.0.0.1:43269/api/version.", "disconnected": true }, { @@ -80,7 +80,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33445/api/recommendations?fp=163577c02a53bc40.", + "message": "/127.0.0.1:43269/api/recommendations?fp=163577c02a53bc40.", "disconnected": true }, { @@ -88,7 +88,7 @@ "disconnected": true }, { - "message": "/127.0.0.1:33445/api/version.", + "message": "/127.0.0.1:43269/api/version.", "disconnected": true } ] diff --git a/plans/phase6-investigation.md b/plans/phase6-investigation.md index c089e04..4e789a1 100644 --- a/plans/phase6-investigation.md +++ b/plans/phase6-investigation.md @@ -106,3 +106,10 @@ CacheStorage or hashing work. WebKit's byte-verified owned response path is unchanged. The native fixture models the actual worker fallback decision instead of a second page-side decision. All 221 frontend tests and 184 server tests pass; both-engine lazy/offline/eviction/pinning/contracts/playback smoke passes. + +The WebKit warm prototype also paid repeated handoff/cache/hash work (warm +~98 ms versus Phase 5 83 ms). Capture now applies only to uncontrolled WebKit +visits. Controlled warm/offline/update pages use the worker's native exact-URL +script path, including its strengthened contract guard. A failing head-loader +test precedes this change; all 222 frontend and 184 server tests and both-engine +lazy smoke pass. Cold capture and both rollback flags are unchanged. From 4b1f5204f8fcd207305ee50fff29985497e58e3b Mon Sep 17 00:00:00 2001 From: Jonathan Sykes Date: Thu, 8 Oct 2026 11:25:03 +0800 Subject: [PATCH 54/81] Restore native boot scheduling without an extra core request --- frontend/app-bootstrap.js | 65 --------------------- frontend/app-bootstrap.test.js | 18 ++++-- frontend/app-seams.test.js | 4 +- frontend/assets.json | 5 +- frontend/index.html | 3 +- frontend/lazy.js | 2 +- frontend/lazy.test.js | 4 +- frontend/section-rail.js | 74 ++++++++++++++++++++++++ frontend/shell-consistency.test.js | 15 +++-- frontend/sw.js | 1 - perf/results/phase6-lazy-2026-10-08.json | 14 ++--- plans/phase6-investigation.md | 28 ++++++++- 12 files changed, 136 insertions(+), 97 deletions(-) delete mode 100644 frontend/app-bootstrap.js diff --git a/frontend/app-bootstrap.js b/frontend/app-bootstrap.js deleted file mode 100644 index 9998a2e..0000000 --- a/frontend/app-bootstrap.js +++ /dev/null @@ -1,65 +0,0 @@ -/* Cache the single page-owned app response before it registers the worker. */ -(function (root) { - 'use strict'; - const doc=root.document, manifest=root.Lazy.manifest, key=root.Lazy.url('/app.js'); - let domReady=doc.readyState==='complete', appSawDom=false; - doc.addEventListener('DOMContentLoaded',()=>{domReady=true;appSawDom=typeof root.boot==='function';},{once:true}); - function execute(node) { - doc.head.append(node); - node.remove(); - delete root.Lazy.appResponse; - // app.js keeps its original DOMContentLoaded listener. Async response - // consumption can finish after that event; boot exactly once in that case. - if(domReady)root.boot(); - } - async function external(url) { - await new Promise((resolve,reject)=>{ - const node=doc.createElement('script');node.src=url; - node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); - doc.head.append(node); - }); - } - async function verified(response, expected) { - const bytes=await response.clone().arrayBuffer(); - const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); - const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); - if(hex.slice(0,10)!==expected)throw Error('Player body hash mismatch'); - return {bytes,digest}; - } - async function start() { - if(!manifest.appCache || !root.crypto?.subtle || !root.Lazy.captureApp)return external(key); - const expected=manifest.files['/app.js'].h; - let cache; - try { cache=await root.caches?.open('ytplayer-assets'); } catch {} - let response=await cache?.match(key); - if(!response || response.headers.get('X-Asset-Hash')!==expected) { - try { response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); } catch {} - } - if(!response?.ok || response.headers.get('X-Asset-Hash')!==expected) { - // Preserve staged N-1 boot after an individual cache eviction. Only the - // controller can serve this old URL safely; never fetch stale URLs bare. - const state=cache && await root.AssetSyncCore.state(cache); - const previousKey=state && root.AssetSyncCore.fallback(manifest,state.previous,'/app.js'); - const previous=previousKey && await cache.match(previousKey); - const previousHash=state?.previous?.files['/app.js']?.h; - const contractsMatch=state?.previous && Object.entries(manifest.groups).every(([name,group])=>state.previous.groups[name]?.contract===group.contract); - if(contractsMatch && root.navigator?.serviceWorker?.controller && previous?.ok && previous.headers.get('X-Asset-Hash')===previousHash) { - await verified(previous,previousHash); - delete root.Lazy.appResponse; - return external(previousKey); - } - throw Error('Player asset hash mismatch'); - } - const {bytes,digest}=await verified(response,expected); - const permission="'sha256-"+root.btoa(String.fromCharCode(...digest))+"'"; - if(!doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); - // CacheStorage may share a full quota with saved music. Never remove data - // to make room; boot from these verified bytes even if caching is refused. - try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } - const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); - execute(node); - } - const ready=start(); - root.AppBootstrap={ready}; - ready.catch(error=>root.console.error('[app-cache]',error.message)); -})(typeof window!=='undefined'?window:globalThis); diff --git a/frontend/app-bootstrap.test.js b/frontend/app-bootstrap.test.js index d790f97..77fe7f6 100644 --- a/frontend/app-bootstrap.test.js +++ b/frontend/app-bootstrap.test.js @@ -3,18 +3,18 @@ const assert=require('node:assert/strict'); const {webcrypto,createHash}=require('node:crypto'); const vm=require('node:vm'); const {readFileSync}=require('node:fs'); -function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false,previous=false,contract=1,capture=true,controller=true}={}){ +function fixture({cached=false,tampered=false,enabled=true,loading=false,quota=false,insecure=false,previous=false,contract=1,capture=true,controller=true,parser=false}={}){ const source='window.appRuns=(window.appRuns||0)+1; window.boot=()=>window.bootRuns=(window.bootRuns||0)+1; document.addEventListener("DOMContentLoaded",boot);',hash=createHash('sha256').update(source).digest('hex'), key='/app.js?v='+hash.slice(0,10); const oldSource='window.oldApp=true;'+source, oldHash=createHash('sha256').update(oldSource).digest('hex').slice(0,10), oldKey='/app.js?v='+oldHash; - const held=new Map(), appended=[],listeners={};let calls=0; + const held=new Map(), appended=[],writes=[],listeners={};let calls=0; const response=()=>new Response(tampered?'bad':source,{headers:{'X-Asset-Hash':hash.slice(0,10)}}); if(cached)held.set(key,response()); if(previous){held.set(oldKey,new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}));held.set('/__ytp_asset_state',Response.json({previous:{files:{'/app.js':{h:oldHash}},groups:{core:{contract,files:['/app.js']}}}}));} const root={crypto:insecure?undefined:webcrypto,TextDecoder,Uint8Array,btoa,console,AssetSyncCore:require('./asset-sync-core'),navigator:{serviceWorker:{controller:controller?{}:null}},Lazy:{captureApp:capture,manifest:{groups:{core:{contract:1,files:['/app.js']}},appCache:enabled,files:{'/app.js':{h:hash.slice(0,10)}}},url:()=>key},fetch:async()=>{calls++;return previous?new Response(oldSource,{headers:{'X-Asset-Hash':oldHash}}):response();},caches:{open:async()=>({match:async k=>held.get(k)?.clone(),put:async(k,r)=>{if(quota)throw Error('quota');held.set(k,r.clone());}})}}; - const doc=root.document={readyState:loading?'loading':'complete',querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {queueMicrotask(async()=>{if(previous && node.src===key){const state=await held.get('/__ytp_asset_state').clone().json();if(!root.AssetSyncCore.fallback(root.Lazy.manifest,state.previous,'/app.js'))return node.onerror();vm.runInContext(oldSource,context);}else vm.runInContext(node.src===oldKey?oldSource:source,context);node.onload();});}}}}; + const doc=root.document={readyState:loading?'loading':'complete',currentScript:parser?{}:null,write:value=>{writes.push(value);vm.runInContext(source,context);},querySelector:()=>({content:"script-src 'self' 'sha256-"+Buffer.from(hash,'hex').toString('base64')+"'"}),addEventListener:(name,fn)=>(listeners[name] ||= []).push(fn),createElement:()=>({remove(){this.removed=true;}}),head:{append(node){appended.push(node);if(node.textContent)vm.runInContext(node.textContent,context);else {queueMicrotask(async()=>{if(previous && node.src===key){const state=await held.get('/__ytp_asset_state').clone().json();if(!root.AssetSyncCore.fallback(root.Lazy.manifest,state.previous,'/app.js'))return node.onerror();vm.runInContext(oldSource,context);}else vm.runInContext(node.src===oldKey?oldSource:source,context);node.onload();});}}}}; root.window=root;const context=vm.createContext(root); - vm.runInContext(readFileSync(require.resolve('./app-bootstrap.js'),'utf8'),context); - return {root,held,appended,listeners,key,calls:()=>calls,doc,response,oldKey}; + vm.runInContext(readFileSync(require.resolve('./section-rail.js'),'utf8'),context); + return {root,held,appended,writes,listeners,key,calls:()=>calls,doc,response,oldKey}; } test('cold boot caches verified app before execution so worker skips its download',async()=>{ const f=fixture();await f.root.AppBootstrap.ready;assert.equal(f.calls(),1);assert.ok(f.held.has(f.key));assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,1);assert.equal(f.appended[0].src,undefined);assert.equal(f.appended[0].removed,true); @@ -74,3 +74,11 @@ test('native-cache engines still reject an incompatible retained core',async()=> test('native-cache engines use the validated current cache entry without decoding its body',async()=>{ const f=fixture({capture:false,cached:true});await f.root.AppBootstrap.ready;assert.equal(f.calls(),0);assert.equal(f.appended[0].src,f.key);assert.equal(f.root.bootRuns,1); }); + +test('native parser boot preserves classic evaluation before the original DOM event',async()=>{ + const f=fixture({capture:false,loading:true,parser:true}); + assert.equal(f.root.appRuns,1);assert.equal(f.root.bootRuns,undefined); + assert.deepEqual(f.writes,['']);assert.equal(f.appended.length,0); + for(const fn of f.listeners.DOMContentLoaded)fn();await f.root.AppBootstrap.ready; + assert.equal(f.root.bootRuns,1);assert.equal(f.calls(),0); +}); diff --git a/frontend/app-seams.test.js b/frontend/app-seams.test.js index f17e810..f6dc72e 100644 --- a/frontend/app-seams.test.js +++ b/frontend/app-seams.test.js @@ -30,8 +30,8 @@ test('Phase 4 preserves the exact player, continuity, tracking and queue bodies' test('eager shell and Settings definitions load before app state and defer reading it',()=>{ const html=readFileSync(join(__dirname,'index.html'),'utf8'); for(const file of ['shell-core.js','views-core.js','section-rail.js']) { - assert.ok(html.indexOf('src="'+file+'"')({}),head:{append(){}}};const globals={document:doc,Lazy:{manifest:{appCache:false},url:()=>'/app.js'},console};globals.window=globals;const context=vm.createContext(globals); // Evaluation before any data/$/els/Player declaration must be safe. vm.runInContext(readFileSync(join(__dirname,file),'utf8'),context); } diff --git a/frontend/assets.json b/frontend/assets.json index 3ec184c..cdf4327 100644 --- a/frontend/assets.json +++ b/frontend/assets.json @@ -1,7 +1,7 @@ { "groups": { "core": { - "contract": 1, + "contract": 2, "eager": true, "files": [ "/index.html", @@ -60,8 +60,7 @@ "/device-db.js", "/shell-core.js", "/views-core.js", - "/section-rail.js", - "/app-bootstrap.js" + "/section-rail.js" ], "background": false }, diff --git a/frontend/index.html b/frontend/index.html index 76f1ab0..b57f5da 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -19,7 +19,7 @@ - + @@ -674,6 +674,5 @@ - diff --git a/frontend/lazy.js b/frontend/lazy.js index fe83a12..ae7f0de 100644 --- a/frontend/lazy.js +++ b/frontend/lazy.js @@ -138,7 +138,7 @@ api.appResponse.catch(()=>{}); } else if(manifest.appCache) { // Preserve native script/code-cache reuse in engines without the WebKit gap. - const preload=doc.createElement('link');preload.rel='preload';preload.as='script';preload.href=url('/app.js');doc.head.append(preload); + const preload=doc.createElement('link');preload.rel='preload';preload.as='script';preload.fetchPriority='low';preload.href=url('/app.js');doc.head.append(preload); } root.Lazy = api; root.navigator.serviceWorker?.addEventListener('message',event=>{ diff --git a/frontend/lazy.test.js b/frontend/lazy.test.js index 1e7d88a..6543250 100644 --- a/frontend/lazy.test.js +++ b/frontend/lazy.test.js @@ -102,7 +102,7 @@ test('head capture is cache-first even before a worker controls the page',async( test('Chromium retains native script loading and only preloads the current app URL',async()=>{ const f=fixture(null,[],true,'AppleWebKit/537.36 Chrome/140.0 Safari/537.36'); assert.equal(f.root.Lazy.captureApp,false);assert.equal(f.root.Lazy.appResponse,undefined);assert.deepEqual(f.fetched,[]); - assert.equal(f.inserted.length,1);assert.equal(f.inserted[0].rel,'preload');assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a'); + assert.equal(f.inserted.length,1);assert.equal(f.inserted[0].rel,'preload');assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a');assert.equal(f.inserted[0].fetchPriority,'low'); }); test('iOS Chromium-branded browsers still use their WebKit response capture',async()=>{ const f=fixture(null,[],true,'AppleWebKit/605.1 CriOS/140.0 Mobile Safari/605.1');await f.root.Lazy.appResponse; @@ -112,5 +112,5 @@ test('iOS Chromium-branded browsers still use their WebKit response capture',asy test('controlled WebKit visits use worker-cached native app scripts without a response handoff',async()=>{ const f=fixture(null,[],true,'AppleWebKit/605.1 Safari/605.1',true); assert.equal(f.root.Lazy.captureApp,false);assert.equal(f.root.Lazy.appResponse,undefined);assert.deepEqual(f.fetched,[]); - assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a'); + assert.equal(f.inserted[0].as,'script');assert.equal(f.inserted[0].href,'/app.js?v=a');assert.equal(f.inserted[0].fetchPriority,'low'); }); diff --git a/frontend/section-rail.js b/frontend/section-rail.js index c84cf10..e277312 100644 --- a/frontend/section-rail.js +++ b/frontend/section-rail.js @@ -245,3 +245,77 @@ const SectionRail = (() => { return { boot, refresh, setFolded, isFolded }; })(); + +/* Cache the single page-owned app response before it registers the worker. */ +(function (root) { + 'use strict'; + const doc=root.document, manifest=root.Lazy.manifest, key=root.Lazy.url('/app.js'); + let domReady=doc.readyState==='complete', appSawDom=false; + doc.addEventListener('DOMContentLoaded',()=>{domReady=true;appSawDom=typeof root.boot==='function';},{once:true}); + function execute(node) { + doc.head.append(node); + node.remove(); + delete root.Lazy.appResponse; + // app.js keeps its original DOMContentLoaded listener. Async response + // consumption can finish after that event; boot exactly once in that case. + if(domReady)root.boot(); + } + async function external(url) { + await new Promise((resolve,reject)=>{ + const node=doc.createElement('script');node.src=url; + node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); + doc.head.append(node); + }); + } + function native() { + if(doc.readyState!=='loading' || !doc.currentScript)return external(key); + return new Promise((resolve,reject)=>{ + doc.addEventListener('DOMContentLoaded',()=>typeof root.boot==='function'?resolve():reject(Error('Unable to load player')),{once:true}); + const escaped=key.replaceAll('&','&').replaceAll('"','"').replaceAll('<','<'); + doc.write(''); + }); + } + async function verified(response, expected) { + const bytes=await response.clone().arrayBuffer(); + const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); + const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); + if(hex.slice(0,10)!==expected)throw Error('Player body hash mismatch'); + return {bytes,digest}; + } + async function start() { + if(!manifest.appCache || !root.crypto?.subtle || !root.Lazy.captureApp)return native(); + const expected=manifest.files['/app.js'].h; + let cache; + try { cache=await root.caches?.open('ytplayer-assets'); } catch {} + let response=await cache?.match(key); + if(!response || response.headers.get('X-Asset-Hash')!==expected) { + try { response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); } catch {} + } + if(!response?.ok || response.headers.get('X-Asset-Hash')!==expected) { + // Preserve staged N-1 boot after an individual cache eviction. Only the + // controller can serve this old URL safely; never fetch stale URLs bare. + const state=cache && await root.AssetSyncCore.state(cache); + const previousKey=state && root.AssetSyncCore.fallback(manifest,state.previous,'/app.js'); + const previous=previousKey && await cache.match(previousKey); + const previousHash=state?.previous?.files['/app.js']?.h; + const contractsMatch=state?.previous && Object.entries(manifest.groups).every(([name,group])=>state.previous.groups[name]?.contract===group.contract); + if(contractsMatch && root.navigator?.serviceWorker?.controller && previous?.ok && previous.headers.get('X-Asset-Hash')===previousHash) { + await verified(previous,previousHash); + delete root.Lazy.appResponse; + return external(previousKey); + } + throw Error('Player asset hash mismatch'); + } + const {bytes,digest}=await verified(response,expected); + const permission="'sha256-"+root.btoa(String.fromCharCode(...digest))+"'"; + if(!doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); + // CacheStorage may share a full quota with saved music. Never remove data + // to make room; boot from these verified bytes even if caching is refused. + try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } + const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); + execute(node); + } + const ready=start(); + root.AppBootstrap={ready}; + ready.catch(error=>root.console.error('[app-cache]',error.message)); +})(typeof window!=='undefined'?window:globalThis); diff --git a/frontend/shell-consistency.test.js b/frontend/shell-consistency.test.js index bfd326c..e044ff5 100644 --- a/frontend/shell-consistency.test.js +++ b/frontend/shell-consistency.test.js @@ -32,7 +32,7 @@ test('assets.json describes the complete existing shell exactly once with eager const { groups } = JSON.parse(readFileSync(join(__dirname, 'assets.json'), 'utf8')); const described = new Set(); for (const [name, group] of Object.entries(groups)) { - assert.equal(group.contract, 1, `${name} initial contract`); + assert.equal(group.contract, name === 'core' ? 2 : 1, `${name} contract (core boot packing changed)`); assert.equal(typeof group.eager, 'boolean'); for (const asset of group.files) { assert.ok(!described.has(asset), `${asset} has one group`); @@ -100,12 +100,15 @@ test('classic first-visit style preload is discovered before the head loader wit }); -test('the eager cache bootstrap stays last and retains app.js in core and legacy shell',()=>{ +test('the last core script owns boot without an extra request or unsafe stale packing',()=>{ const {groups}=JSON.parse(readFileSync(join(__dirname,'assets.json'),'utf8')); - assert.ok(groups.core.files.includes('/app-bootstrap.js')); + assert.equal(groups.core.contract,2,'old core packing cannot fall back without the loader'); assert.ok(groups.core.files.includes('/app.js')); - assert.ok(listed.has('/app-bootstrap.js')&&listed.has('/app.js')); - assert.ok(html.indexOf('src="app-bootstrap.js"')>html.indexOf('src="section-rail.js"')); + assert.ok(groups.core.files.includes('/section-rail.js')); + assert.equal(groups.core.files.includes('/app-bootstrap.js'),false); + assert.equal(listed.has('/app-bootstrap.js'),false); + const scripts=[...html.matchAll(/