From aa146f07e4b05503c59110ec24836b0942221768 Mon Sep 17 00:00:00 2001 From: Harvey Zhao Date: Wed, 16 Sep 2026 01:19:58 +0800 Subject: [PATCH] test(audio): [PKG-AUDIO-BUFFER-01] observe switches while network responses are held --- .../ARCHITECTURE.md | 8 + refactor/audio-validation.md | 11 + .../audio-buffer-order-validation.json | 5118 +++++++++++++++++ .../2026-09-16-PKG-AUDIO-BUFFER-01-order.md | 46 + refactor/plan.md | 10 +- refactor/progress.md | 10 + refactor/risks.json | 8 +- refactor/tasks.json | 23 +- test/browser/audio-buffering.spec.js | 75 +- 9 files changed, 5299 insertions(+), 10 deletions(-) create mode 100644 refactor/baselines/audio-buffer-order-validation.json create mode 100644 refactor/changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md diff --git a/packages/artplayer-plugin-audio-track/ARCHITECTURE.md b/packages/artplayer-plugin-audio-track/ARCHITECTURE.md index f3f388f7b..8fb1f7e8d 100644 --- a/packages/artplayer-plugin-audio-track/ARCHITECTURE.md +++ b/packages/artplayer-plugin-audio-track/ARCHITECTURE.md @@ -65,6 +65,14 @@ source failure recovery, and old/native pause/end plus corrected candidate clean See refactor/audio-validation.md for failed baseline probes, Windows WebKit WAV/size limits, physical-device gaps and the remaining 05/06 combination/distribution gates. +`audio-buffering.spec.js` observes switchUrl's Promise independently while its real +HTTP response is held, and requires fulfillment after release. Never await that +Promise before allowing the test to release the network. A separate regression +sends complete MP4 format/metadata boxes while withholding frames to exercise this +ordering; it does not replace the existing trusted waiting and playback recovery +assertions. Phase/switch/media attachments distinguish a pending switch from the +Windows WebKit native buffering gap, which remains open. + The bilingual VitePress audio-track guides explain the actual deferred update, strict drift threshold, URL truthiness and shared mute behavior. Keep their Run Code source identical to docs/assets/example/audio.track.js. document-audio.spec.js diff --git a/refactor/audio-validation.md b/refactor/audio-validation.md index ec4c7935d..7face7003 100644 --- a/refactor/audio-validation.md +++ b/refactor/audio-validation.md @@ -1,5 +1,16 @@ # Audio Track 行为与媒体测试 +## PKG-AUDIO-BUFFER-01:断流测试的等待顺序 + +`audio-buffering.spec.js`不再先等待switchUrl完成才检查/放行网络,改为记录其 +pending/fulfilled/rejected状态,放行后明确要求成功。新增完整MP4元数据但扣住 +全部编码帧的回归:旧等待方式20秒超时,修正后的新旧核心/插件三浏览器12项通过。 +仅1字节的初版夹具曾触发Firefox媒体错误,失败保留;最终按ftyp/moov结构发出 +1605字节。此回归验证测试可继续放行网络,不代替真实缓冲断言。 +原断流矩阵仍16通过、Windows WebKit8失败,全部到达native-starvation阶段, +没有放宽trusted waiting、双时钟恢复或同步检查。详见[记录](changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md) +与[证据](baselines/audio-buffer-order-validation.json)。Audio-05和AUDIO-BUFFER-01继续开放。 + ## PKG-AUDIO-03 候选修复 音频状态已从核心事件接入拆出,源码 44 项、加入三种产物共 89 项 Node 通过。 diff --git a/refactor/baselines/audio-buffer-order-validation.json b/refactor/baselines/audio-buffer-order-validation.json new file mode 100644 index 000000000..da529d374 --- /dev/null +++ b/refactor/baselines/audio-buffer-order-validation.json @@ -0,0 +1,5118 @@ +{ + "schemaVersion": 1, + "task": "PKG-AUDIO-BUFFER-01", + "verifiedAt": "2026-09-15T17:16:20.451Z", + "startedFrom": "6f7fd7931d03d0581fb4dd5405021f9f34d5c48d", + "node": "v24.21.0", + "yarn": "1.22.22", + "inputs": [ + { + "path": "test/browser/audio-buffering.spec.js", + "sha256": "0deea1832fcec43fb4acef8ac82580f9f35363a38a513d73902ae68be1bf59d6" + }, + { + "path": "test/browser/audio-fixture.js", + "sha256": "4623be9d2c6df678a859d06d7bc713d125572d0698dcd4249612e4d4d7693c28" + }, + { + "path": "test/helpers/media-gate.js", + "sha256": "b9bc0e8550739902ed4d94674b53d6c5b35795cd25ddf3e567ed22eed591f385" + }, + { + "path": "test/browser/media/pattern.mp4", + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233" + }, + { + "path": "test/browser/media/audio-tone.m4a", + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56" + } + ], + "before": { + "report": { + "path": "refactor/.cache/audio-buffer-order-before/report.json", + "sha256": "ad2b0afd658768782bc9bb647b47bb3688100194026c9900b5929501a194b5f5" + }, + "archive": "refactor/.cache/audio-buffer-order-before", + "stats": { + "startTime": "2026-09-15T17:04:20.228Z", + "duration": 11734.457, + "expected": 0, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "rows": [ + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8487, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "oneByteDeadlock": { + "report": { + "path": "refactor/.cache/audio-held-switch-before/report.json", + "sha256": "b614ba299370d43df4e18773e7e2dae5994e97aab0ee1bfd520cf01cea1388d5" + }, + "archive": "refactor/.cache/audio-held-switch-before", + "stats": { + "startTime": "2026-09-15T17:08:15.212Z", + "duration": 23672.197, + "expected": 0, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "rows": [ + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "timedOut", + "durationMs": 20205, + "error": "Test timeout of 20000ms exceeded.", + "phase": "begin-switch", + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": false + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "intermediate": { + "report": { + "path": "refactor/.cache/audio-buffer-order-after/report.json", + "sha256": "ab9eedc1eceed4d0f4915ed61d6eb08a3d3b0575d02854c439a0ad70ff767983" + }, + "archive": "refactor/.cache/audio-buffer-order-after", + "stats": { + "startTime": "2026-09-15T17:05:45.142Z", + "duration": 90705.88699999999, + "expected": 16, + "skipped": 0, + "unexpected": 8, + "flaky": 0 + }, + "rows": [ + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5395, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 674.8999999761581, + "settledAt": 687.3999999761581 + }, + "video": { + "time": 3.472292, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.433187, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.058339, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.058339 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5328, + "phase": "complete", + "video": { + "time": 4.849775, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.807616, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520179, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.572018 + }, + { + "trusted": true, + "time": 3.717158, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.717373 + }, + { + "trusted": true, + "time": 4.774548, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.774729 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5243, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 621.3000000119209, + "settledAt": 630.9000000357628 + }, + "video": { + "time": 3.459903, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.436298, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.043885, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.043885 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5267, + "phase": "complete", + "video": { + "time": 4.806169, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.786307, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.52019, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.573059 + }, + { + "trusted": true, + "time": 3.709932, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.710136 + }, + { + "trusted": true, + "time": 4.77073, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.770904 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5404, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 694.5, + "settledAt": 707 + }, + "video": { + "time": 3.472963, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.435818, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.056098, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.056098 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5335, + "phase": "complete", + "video": { + "time": 4.841305, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.799145, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520126, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.572928 + }, + { + "trusted": true, + "time": 3.717128, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.717343 + }, + { + "trusted": true, + "time": 4.774518, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.774699 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5255, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 641.5999999642372, + "settledAt": 649.3999999761581 + }, + "video": { + "time": 3.463303, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.424018, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.058269, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.058269 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5292, + "phase": "complete", + "video": { + "time": 4.815589, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.781575, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520115, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.571816 + }, + { + "trusted": true, + "time": 3.710102, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.710442 + }, + { + "trusted": true, + "time": 4.768895, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.769076 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6646, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1064, + "settledAt": 1084 + }, + "video": { + "time": 3.500743, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.50818, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.088691, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.088691 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5349, + "phase": "complete", + "video": { + "time": 4.758001, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.75801, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.458769, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.46006 + }, + { + "trusted": true, + "time": 4.758001, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.758001 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5442, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 715, + "settledAt": 729 + }, + "video": { + "time": 3.498976, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.502444, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.091787, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.091787 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5563, + "phase": "complete", + "video": { + "time": 4.871169, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.868941, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.487658, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.488445 + }, + { + "trusted": true, + "time": 4.78841, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.78841 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6609, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1066, + "settledAt": 1084 + }, + "video": { + "time": 3.499999, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.505249, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.090104, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.090104 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5547, + "phase": "complete", + "video": { + "time": 4.848259, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.848599, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.469572, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.471145 + }, + { + "trusted": true, + "time": 4.808158, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.808158 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5512, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 743, + "settledAt": 760 + }, + "video": { + "time": 3.519148, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.526627, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.113773, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.113773 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5491, + "phase": "complete", + "video": { + "time": 4.766561, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.726205, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.458614, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.458332 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8718, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1671, + "settledAt": 1939 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 6.0359373, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8881, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.1260624, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0343655, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8635, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1628, + "settledAt": 1913 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 5.9918749, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8859, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.0014302, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 6.776101, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8666, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1604, + "settledAt": 1900 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 6.0174165, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9127, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.0861517, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0328709, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8530, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1461, + "settledAt": 1756 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 6.0604164, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8920, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.0759763, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0583174, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "oneByteMatrix": { + "report": { + "path": "refactor/.cache/audio-buffer-order-final/report.json", + "sha256": "3c0f3397bff1f3b284af3d839b048ca7643ac921265acc6225348c6323769556" + }, + "archive": "refactor/.cache/audio-buffer-order-final", + "stats": { + "startTime": "2026-09-15T17:09:12.227Z", + "duration": 113636.60800000001, + "expected": 24, + "skipped": 0, + "unexpected": 12, + "flaky": 0 + }, + "rows": [ + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1348, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 669.1999999880791, + "settledAt": 690.6000000238419 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5260, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 633.9000000357628, + "settledAt": 641.7000000476837 + }, + "video": { + "time": 3.481268, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.44259, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.058539, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.058539 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5399, + "phase": "complete", + "video": { + "time": 4.902567, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.861999, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520104, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.567244 + }, + { + "trusted": true, + "time": 3.706284, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.706466 + }, + { + "trusted": true, + "time": 4.768989, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.769842 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1195, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 629.5, + "settledAt": 643.6999999880791 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5177, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 608.1000000238419, + "settledAt": 615.8000000119209 + }, + "video": { + "time": 3.447884, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.421466, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.046244, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.046244 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5284, + "phase": "complete", + "video": { + "time": 4.829319, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.787348, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520091, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.572721 + }, + { + "trusted": true, + "time": 3.719659, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.719852 + }, + { + "trusted": true, + "time": 4.77371, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.773861 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1338, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 682.8000000119209, + "settledAt": 706.1000000238419 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=65536-", + "start": 65536, + "end": 251537, + "sent": 186002, + "wasHeld": false, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5258, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 631.3999999761581, + "settledAt": 640 + }, + "video": { + "time": 3.460888, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.427658, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.052447, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.052447 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5415, + "phase": "complete", + "video": { + "time": 4.899088, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.857075, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520129, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.564586 + }, + { + "trusted": true, + "time": 3.70659, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.706909 + }, + { + "trusted": true, + "time": 4.76731, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.768104 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1322, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 621.8999999761581, + "settledAt": 636.8999999761581 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=65536-", + "start": 65536, + "end": 251537, + "sent": 186002, + "wasHeld": false, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5228, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 618.1000000238419, + "settledAt": 626.4000000357628 + }, + "video": { + "time": 3.463853, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.437187, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.045467, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.045467 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5320, + "phase": "complete", + "video": { + "time": 4.8409, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.799491, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520094, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.573281 + }, + { + "trusted": true, + "time": 3.720923, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.721186 + }, + { + "trusted": true, + "time": 4.777407, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.778493 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "failed", + "durationMs": 2083, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"pending\"\nReceived: \"rejected\"", + "phase": "held-request", + "switch": { + "status": "rejected", + "startedAt": 1093, + "error": "[object Event]", + "settledAt": 1107 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6550, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1064, + "settledAt": 1082 + }, + "video": { + "time": 3.493939, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.500608, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.089734, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.089734 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5351, + "phase": "complete", + "video": { + "time": 4.755758, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.715324, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.462305, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.463106 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "failed", + "durationMs": 1061, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"pending\"\nReceived: \"rejected\"", + "phase": "held-request", + "switch": { + "status": "rejected", + "startedAt": 741, + "error": "[object Event]", + "settledAt": 747 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6491, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 999, + "settledAt": 1019 + }, + "video": { + "time": 3.488731, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.490329, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.083822, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.083822 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5554, + "phase": "complete", + "video": { + "time": 4.860968, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.858932, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.485747, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.486046 + }, + { + "trusted": true, + "time": 4.77841, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.77841 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "failed", + "durationMs": 2130, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"pending\"\nReceived: \"rejected\"", + "phase": "held-request", + "switch": { + "status": "rejected", + "startedAt": 1091, + "error": "[object Event]", + "settledAt": 1101 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6606, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1066, + "settledAt": 1087 + }, + "video": { + "time": 3.489504, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.493752, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.084457, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.084457 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5592, + "phase": "complete", + "video": { + "time": 4.870417, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.867951, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.493249, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.493691 + }, + { + "trusted": true, + "time": 4.787317, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.787317 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "failed", + "durationMs": 8009, + "error": "Error: expect(received).toBeGreaterThan(expected)\n\nExpected: > 0\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "held-request", + "switch": { + "status": "rejected", + "startedAt": 718, + "error": "[object Event]", + "settledAt": 726 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6323, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 981, + "settledAt": 1001 + }, + "video": { + "time": 3.508877, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.515531, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.104714, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.104714 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5651, + "phase": "complete", + "video": { + "time": 4.874999, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.872577, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.458196, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.458332 + }, + { + "trusted": true, + "time": 4.791666, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.791666 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3201, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1580, + "settledAt": 1946 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8189, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "pending", + "startedAt": 1266 + }, + "video": { + "time": 0, + "paused": true, + "readyState": 2, + "ended": false, + "error": null + }, + "audio": { + "time": 0.3828744, + "paused": true, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9018, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.1300552, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0428527, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3118, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1549, + "settledAt": 1851 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8327, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "pending", + "startedAt": 1363 + }, + "video": { + "time": 0, + "paused": true, + "readyState": 2, + "ended": false, + "error": null + }, + "audio": { + "time": 0, + "paused": true, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9116, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.1497204, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0433545, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 2984, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1465, + "settledAt": 1784 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8500, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1491, + "settledAt": 1809 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 6.0495623, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9044, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.2113846, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0696768, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3242, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1674, + "settledAt": 2022 + }, + "limit": 1, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8477, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1526, + "settledAt": 1843 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 5.9970415, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8942, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 6.9909619, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 6.8273659, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "matchedBefore": { + "report": { + "path": "refactor/.cache/audio-held-switch-matched-before/report.json", + "sha256": "82725ae9bfe92d5ee58fe0026e324bac58ee20600c562b569db8338ac67a5af6" + }, + "archive": "refactor/.cache/audio-held-switch-matched-before", + "stats": { + "startTime": "2026-09-15T17:14:31.577Z", + "duration": 23649.425, + "expected": 0, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "rows": [ + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "timedOut", + "durationMs": 20199, + "error": "Test timeout of 20000ms exceeded.", + "phase": "begin-switch", + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 1605, + "wasHeld": true, + "closed": false + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "finalHeldSwitch": { + "report": { + "path": "refactor/.cache/audio-held-switch-metadata/report.json", + "sha256": "eef0f2bbf8390f9f0ecaf0b3b3f918595098af69fb1f2808fbc95afc49f08a2e" + }, + "archive": "refactor/.cache/audio-held-switch-metadata", + "stats": { + "startTime": "2026-09-15T17:13:10.970Z", + "duration": 20208.417999999998, + "expected": 12, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "rows": [ + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1370, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 700.8000000119209, + "settledAt": 717 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1255, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 656, + "settledAt": 678.2000000476837 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1361, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 668.6999999880791, + "settledAt": 687.1999999880791 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=65536-", + "start": 65536, + "end": 251537, + "sent": 186002, + "wasHeld": false, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "chromium", + "status": "passed", + "durationMs": 1266, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 669.8999999761581, + "settledAt": 687.6000000238419 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=65536-", + "start": 65536, + "end": 251537, + "sent": 186002, + "wasHeld": false, + "closed": true + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "passed", + "durationMs": 2435, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1047, + "settledAt": 1071 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "passed", + "durationMs": 1677, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 723, + "settledAt": 846 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "passed", + "durationMs": 2734, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1045, + "settledAt": 1174 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "firefox", + "status": "passed", + "durationMs": 1656, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 721, + "settledAt": 852 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3152, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1463, + "settledAt": 1790 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3181, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1519, + "settledAt": 1923 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3151, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1482, + "settledAt": 1875 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: held switch can release before its Promise settles", + "project": "webkit", + "status": "passed", + "durationMs": 3117, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1549, + "settledAt": 1968 + }, + "limit": 1605, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ] + }, + "finalStarvation": { + "report": { + "path": "refactor/.cache/audio-buffer-order-final/report.json", + "sha256": "3c0f3397bff1f3b284af3d839b048ca7643ac921265acc6225348c6323769556" + }, + "rows": [ + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5260, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 633.9000000357628, + "settledAt": 641.7000000476837 + }, + "video": { + "time": 3.481268, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.44259, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.058539, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.058539 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5399, + "phase": "complete", + "video": { + "time": 4.902567, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.861999, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520104, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.567244 + }, + { + "trusted": true, + "time": 3.706284, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.706466 + }, + { + "trusted": true, + "time": 4.768989, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.769842 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5177, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 608.1000000238419, + "settledAt": 615.8000000119209 + }, + "video": { + "time": 3.447884, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.421466, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.046244, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.046244 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5284, + "phase": "complete", + "video": { + "time": 4.829319, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.787348, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520091, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.572721 + }, + { + "trusted": true, + "time": 3.719659, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.719852 + }, + { + "trusted": true, + "time": 4.77371, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.773861 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5258, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 631.3999999761581, + "settledAt": 640 + }, + "video": { + "time": 3.460888, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.427658, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.052447, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.052447 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5415, + "phase": "complete", + "video": { + "time": 4.899088, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.857075, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520129, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.564586 + }, + { + "trusted": true, + "time": 3.70659, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.706909 + }, + { + "trusted": true, + "time": 4.76731, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.768104 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5228, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 618.1000000238419, + "settledAt": 626.4000000357628 + }, + "video": { + "time": 3.463853, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.437187, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": true + }, + { + "method": "GET", + "range": "bytes=98304-", + "start": 98304, + "end": 251537, + "sent": 153234, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.045467, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.045467 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "chromium", + "status": "passed", + "durationMs": 5320, + "phase": "complete", + "video": { + "time": 4.8409, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.799491, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.520094, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.573281 + }, + { + "trusted": true, + "time": 3.720923, + "readyState": 1, + "audioPaused": false, + "videoTime": 3.721186 + }, + { + "trusted": true, + "time": 4.777407, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.778493 + } + ], + "browser": "153.0.8010.12", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6550, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1064, + "settledAt": 1082 + }, + "video": { + "time": 3.493939, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.500608, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.089734, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.089734 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5351, + "phase": "complete", + "video": { + "time": 4.755758, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.715324, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.462305, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.463106 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6491, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 999, + "settledAt": 1019 + }, + "video": { + "time": 3.488731, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.490329, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 0, + "readyState": 1, + "audioPaused": true, + "videoTime": 0 + }, + { + "trusted": true, + "time": 3.083822, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.083822 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5554, + "phase": "complete", + "video": { + "time": 4.860968, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.858932, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.485747, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.486046 + }, + { + "trusted": true, + "time": 4.77841, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.77841 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6606, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 1066, + "settledAt": 1087 + }, + "video": { + "time": 3.489504, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.493752, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.084457, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.084457 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5592, + "phase": "complete", + "video": { + "time": 4.870417, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.867951, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.493249, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.493691 + }, + { + "trusted": true, + "time": 4.787317, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.787317 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 6323, + "phase": "complete", + "switch": { + "status": "fulfilled", + "startedAt": 981, + "settledAt": 1001 + }, + "video": { + "time": 3.508877, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 3.515531, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 251538, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.104714, + "readyState": 2, + "audioPaused": true, + "videoTime": 3.104714 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "firefox", + "status": "passed", + "durationMs": 5651, + "phase": "complete", + "video": { + "time": 4.874999, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 4.872577, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 132436, + "wasHeld": true, + "closed": true + } + ], + "waitingEvents": [ + { + "trusted": true, + "time": 3.458196, + "readyState": 2, + "audioPaused": false, + "videoTime": 3.458332 + }, + { + "trusted": true, + "time": 4.791666, + "readyState": 1, + "audioPaused": false, + "videoTime": 4.791666 + } + ], + "browser": "155.0", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8189, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "pending", + "startedAt": 1266 + }, + "video": { + "time": 0, + "paused": true, + "readyState": 2, + "ended": false, + "error": null + }, + "audio": { + "time": 0.3828744, + "paused": true, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9018, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.1300552, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0428527, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "published core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8327, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "pending", + "startedAt": 1363 + }, + "video": { + "time": 0, + "paused": true, + "readyState": 2, + "ended": false, + "error": null + }, + "audio": { + "time": 0, + "paused": true, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "published core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9116, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.1497204, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0433545, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "published", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + published audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8500, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1491, + "settledAt": 1809 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 6.0495623, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + published audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 9044, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 7.2113846, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 7.0696768, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "published", + "selectedPlugin": { + "kind": "published", + "sha256": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683" + } + }, + { + "title": "candidate core + source audio: real video starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8477, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "switch": { + "status": "fulfilled", + "startedAt": 1526, + "settledAt": 1843 + }, + "video": { + "time": 0, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "audio": { + "time": 5.9970415, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "limit": 98304, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 251537, + "sent": 98304, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + }, + { + "title": "candidate core + source audio: real audio starvation resumes after network release", + "project": "webkit", + "status": "failed", + "durationMs": 8942, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: true\nReceived: false\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "phase": "native-starvation", + "video": { + "time": 6.9909619, + "paused": false, + "readyState": 4, + "ended": false, + "error": null + }, + "audio": { + "time": 6.8273659, + "paused": false, + "readyState": 3, + "ended": false, + "error": null + }, + "limit": 32768, + "requests": [ + { + "method": "GET", + "range": "bytes=0-", + "start": 0, + "end": 132435, + "sent": 32768, + "wasHeld": true, + "closed": false + } + ], + "waitingEvents": [], + "browser": "26.6", + "platform": "win32", + "core": "candidate", + "plugin": "source", + "selectedPlugin": { + "kind": "source-build", + "file": null, + "sha256": "c4b37388ecf38c4c33dc172895d2d76d1ffca2587628c01b11b38cfe1852c713" + } + } + ], + "note": "The original 24 starvation cases and their shared switch helper are unchanged by the final metadata-only held-switch fixture correction. These are two separate runs, not a claim of one fully green 36-case suite." + }, + "checks": { + "gateTests": { + "command": "node --test test/media-gate.test.js", + "exitCode": 0, + "pass": 3, + "durationMs": 161.9328, + "log": { + "path": "refactor/.cache/audio-buffer-order-gate-tests.log", + "sha256": "94f00463cba5f7b5b7e9d9ea3a063a134a31eb2f041c84f712af0adec0c35ddf" + } + }, + "lint": { + "command": "node node_modules/eslint/bin/eslint.js test/browser/audio-buffering.spec.js", + "exitCode": 0 + } + }, + "result": { + "heldSwitchPass": 12, + "starvationPass": 16, + "starvationFail": 8, + "retries": 0, + "skipped": 0, + "knownFailure": "AUDIO-BUFFER-01", + "runtimeChanged": false, + "installedArtifactsVerified": false, + "physicalDeviceEvidence": false, + "fullAudioAcceptance": false, + "publicationAuthorized": false + } +} diff --git a/refactor/changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md b/refactor/changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md new file mode 100644 index 000000000..4b3c0eca6 --- /dev/null +++ b/refactor/changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md @@ -0,0 +1,46 @@ +# PKG-AUDIO-BUFFER-01: observe source switching while the network is held + +The buffering test awaited `switchUrl` before checking starvation and releasing +the withheld response. Switching can await `canplay` and resumed playback, so +this could stop the test from releasing the bytes needed to complete the switch. +Earlier installed WebKit traces stopped at this await. The initial current-source +rerun instead reached the existing native-starvation failure; these observations +are preserved separately. + +`beginAudioSwitch` now starts the real switch without returning its Promise to +Playwright. It records pending/fulfilled/rejected status and timestamps. The test +can observe the actual HTTP gate while switching, then requires fulfillment after +release. Rejections cannot produce a passing result. Original trusted `waiting`, +nonzero time, stalled-audio behavior, recovery, synchronization and media-error +assertions remain. Phase, switch and media observations are attached before cleanup. + +A new regression withholds every encoded frame while sending complete `ftyp` and +`moov` boxes from the existing MP4: 1,605 bytes derived from box sizes. It requires +a held request and pending switch, then releases the network and checks fulfillment +and resumed video/audio clocks. This tests orchestration, not ongoing playback +starvation. An initial one-byte fixture caused all four Firefox combinations to +reject with a native media error; that failed run is retained. The final fixture +sends complete format/metadata boxes instead of accepting those errors. + +With the final fixture, reinstating the exact old await expression reproduced a +20-second Chromium timeout in `begin-switch`, with 1,605 bytes sent and the request +held. The corrected source was restored byte for byte. All 12 corrected cases +pass: published/current core crossed with published/current Audio Track in +Chromium 153.0.8010.12, Firefox 155.0 and Windows WebKit 26.6, without retry/skip. + +The separate original starvation matrix remains 16 passed and 8 failed. All +failures are Windows WebKit at the trusted native-starvation assertion; two video +cases have pending switches and two have fulfilled switches. Completion and +starvation therefore remain separate observations. AUDIO-BUFFER-01 is not waived. +The final metadata correction changes only the new case; original starvation +inputs/assertions and the shared helper retain the tested bytes. These separate +runs must not be described as a fully green 36-case suite. + +Canonical Node 24.21.0/Yarn 1.22.22 were used. Three real HTTP gate unit tests and +read-only spec lint pass. The [validation record](../baselines/audio-buffer-order-validation.json) +retains run summaries, input provenance, report hashes and phase/media/request +evidence. Candidate browser inputs are source builds, not installed npm tarballs. +No production API/code, media fixture, gate server, timeout, dependency or +distribution changed. This closes test ordering only; PKG-AUDIO-05/06 and native +buffering/device acceptance remain outstanding. No formal review, push, +deployment or publication was performed. diff --git a/refactor/plan.md b/refactor/plan.md index 01a2dce9e..75a9fb3a2 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -2,9 +2,9 @@ > 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。 -基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 284 项,范围 22 个包及工作区/示例。 +基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 285 项,范围 22 个包及工作区/示例。 -状态:todo 41 / doing 20 / blocked 0 / done 223 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 41 / doing 20 / blocked 0 / done 224 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -18,7 +18,7 @@ | artplayer-plugin-ads | 2.1.0 | PKG-ADS-01, PKG-ADS-02, PKG-ADS-03, PKG-ADS-04, PKG-ADS-05, PKG-ADS-06 | | artplayer-plugin-ambilight | 1.1.0 | PKG-AMBILIGHT-01, PKG-AMBILIGHT-02, PKG-AMBILIGHT-03, PKG-AMBILIGHT-04, PKG-AMBILIGHT-PROXY-01, PKG-AMBILIGHT-05, PKG-AMBILIGHT-06, PKG-FACTORY-01 | | artplayer-plugin-asr | 2.1.0 | PKG-ASR-01, PKG-ASR-02, PKG-ASR-03, PKG-ASR-04, PKG-ASR-05, PKG-ASR-06, PKG-ASR-07, PKG-ASR-08, PKG-ASR-09, PKG-ASR-10 | -| artplayer-plugin-audio-track | 1.1.0 | PKG-AUDIO-01, PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-04, PKG-AUDIO-05, PKG-AUDIO-06, SITE-AUDIO-01, CI-TYPES-01 | +| artplayer-plugin-audio-track | 1.1.0 | PKG-AUDIO-01, PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-04, PKG-AUDIO-05, PKG-AUDIO-06, SITE-AUDIO-01, CI-TYPES-01, PKG-AUDIO-BUFFER-01 | | artplayer-plugin-auto-thumbnail | 1.1.0 | PKG-AUTO-THUMB-01, PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-03, PKG-AUTO-THUMB-04, PKG-AUTO-THUMB-05, PKG-AUTO-THUMB-06, PKG-AUTO-THUMB-07, PKG-AUTO-THUMB-08, PKG-AUTO-THUMB-09, PKG-AUTO-THUMB-10, PKG-AUTO-THUMB-11, PKG-AUTO-THUMB-12, PKG-AUTO-THUMB-13 | | artplayer-plugin-chapter | 1.1.0 | PILOT-01, PKG-CHAPTER-01, PKG-CHAPTER-02, PKG-CHAPTER-03, PKG-CHAPTER-04, PKG-CHAPTER-05, PKG-CHAPTER-06, PKG-CHAPTER-HOVER-01 | | artplayer-plugin-chromecast | 1.1.0 | PKG-CAST-01, PKG-CAST-02, PKG-CAST-03, PKG-CAST-04, PKG-CAST-05, PKG-CAST-06 | @@ -174,8 +174,9 @@ | PKG-AUDIO-02 | artplayer-plugin-audio-track
建立特有行为与错误测试 | PKG-AUDIO-01, ENG-03, ENG-05 | 偏移、倍率、seek、waiting/playing、加载错误和 autoplay 拒绝 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-AUDIO-03 | artplayer-plugin-audio-track
整理内部职责与资源 | PKG-AUDIO-02, CORE-10 | 外部 audio 的同步策略、监听与源更新生命周期 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done | | PKG-AUDIO-04 | artplayer-plugin-audio-track
迁移自有源码和公开类型 | PKG-AUDIO-03, ENG-04, ENG-06, CORE-07 | Option/Result/audio、update 输入和事件类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done | -| PKG-AUDIO-05 | artplayer-plugin-audio-track
验证新旧核心和组合 | PKG-AUDIO-04, CORE-22, CORE-24 | 主视频切源和缓冲恢复,多实例独立音频、旧核心 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | doing | +| PKG-AUDIO-05 | artplayer-plugin-audio-track
验证新旧核心和组合 | PKG-AUDIO-04, CORE-22, CORE-24, PKG-AUDIO-BUFFER-01 | 主视频切源和缓冲恢复,多实例独立音频、旧核心 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | doing | | PKG-AUDIO-06 | artplayer-plugin-audio-track
验证分发并同步文档 | PKG-AUDIO-05, ENG-07 | audio.track.js 示例与运行返回值一致的声明 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo | +| PKG-AUDIO-BUFFER-01 | artplayer-plugin-audio-track
修正断流测试的切源等待顺序 | PKG-AUDIO-04, CORE-22 | 网络扣留时独立观察切源Promise;完整元数据扣帧回归与阶段诊断 | 旧顺序复现死等,三浏览器新旧组合可放行并验证恢复;保留真实缓冲失败,不以本项关闭Audio-05或设备门槛 | M | done | ## 5 包迁移:artplayer-plugin-auto-thumbnail @@ -746,3 +747,4 @@ - DOC-REVIEW-01: [记录](changes/2026-09-15-DOC-REVIEW-01-user-guidance.md) [记录](release-reviews.md) [记录](ai-workflow.md) - PKG-DANMUKU-START-01: [记录](baselines/ci-installed-webkit-validation.json) [记录](changes/2026-09-16-PKG-DANMUKU-START-01-first-sample.md) [记录](baselines/danmuku-start-validation.json) - CI-NPM-02: [记录](changes/2026-09-16-CI-NPM-02-verify-bundle.md) [记录](baselines/npm-bundle-verification.json) +- PKG-AUDIO-BUFFER-01: [记录](changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md) [记录](baselines/audio-buffer-order-validation.json) diff --git a/refactor/progress.md b/refactor/progress.md index 118bd3ae2..5e7e6c1df 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,15 @@ # 进度与证据 +## PKG-AUDIO-BUFFER-01 断流测试等待顺序修复 + +修正switchUrl与网络放行互相等待的问题;完整MP4元数据/无编码帧的回归用旧顺序 +复现20秒死等,修正后新旧核心/插件三浏览器12项通过,HTTP gate单测3项和lint通过。 +原真实断流矩阵仍16通过、Windows WebKit8失败,未放宽断言或修改生产行为。 +初版1字节夹具导致Firefox错误的失败报告也保留;最终按媒体结构发送完整元数据。 +见[记录](changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md)和[证据](baselines/audio-buffer-order-validation.json)。 +本子项done,Audio-05/06与AUDIO-BUFFER-01保持未完成;224 done、20 doing、41 todo, +共285项。没有复盘、推送、部署或发布。 + ## CI-NPM-02 下载候选内容核验 新增`release:verify-bundle`,以独立提供的源码SHA、manifest摘要、包批次/tag diff --git a/refactor/risks.json b/refactor/risks.json index 94b0bc80e..4fc54a2ee 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "task": "BASE-07", "sourceCommit": "e01f39ff", - "updatedAt": "2026-09-14T07:23:15.393Z", + "updatedAt": "2026-09-15T17:18:32.442Z", "note": "Open means closure evidence is outstanding; source-observed and unverified are not reproduced runtime bugs. A source issue already mitigated in the workspace still requires candidate regression evidence. No accepted-with-scope item is implied by baseline task completion.", "items": [ { @@ -3005,9 +3005,11 @@ "refactor/changes/2026-09-15-CI-01-source-webkit.md", "refactor/baselines/ci-source-webkit-validation.json", "refactor/changes/2026-09-15-CI-01-installed-webkit.md", - "refactor/baselines/ci-installed-webkit-validation.json" + "refactor/baselines/ci-installed-webkit-validation.json", + "refactor/changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md", + "refactor/baselines/audio-buffer-order-validation.json" ], - "compatibleResolution": "保留真实 waiting 断言;使用独立原生对照和其他实际支持环境/输入继续验证,不将没有播放推进的诊断当成缓冲通过,也不凭此改变插件 API 或否定真实 Safari 支持。", + "compatibleResolution": "保留真实 waiting 断言;使用独立原生对照和其他实际支持环境/输入继续验证,不将没有播放推进的诊断当成缓冲通过,也不凭此改变插件 API 或否定真实 Safari 支持。 PKG-AUDIO-BUFFER-01已修正测试等待顺序;独立切源放行12项通过,原WebKit真实缓冲8项仍失败,本风险不关闭。", "closureCriteria": "受影响的缓冲/恢复得到真实媒体证据;与原生能力和测试夹具差异分开,发布环境的剩余范围经显式处理。", "workspaceState": "CI-01 九包安装扩展的首轮 336 项中,Windows WebKit 八项新旧音频受限媒体组合继续失败。七项未观察到目标可信 waiting,一项受限视频路径耗尽整体时间并在最终状态读取中报页面关闭。其他引擎均通过;保留原始失败,不以销毁后状态反推初始解码错误,不推断新的共同底层原因。 Same-file prefix controls now show Windows WebKit can start before releasing the tail with larger prefixes (video188653/audio65536), but four committed native diagnostics still record no trusted waiting. Default three-engine diagnostics retain Chromium/Firefox8 progression+waiting and WebKit4 no progression/no waiting. Before-release request copies distinguish held bytes from final sent counters; no production fix or waiver. Complete WebKit source run ae56937d3: all eight initial dual-clock assertions pass, then all eight fail the original trusted waiting/time>0.3 assertion at line30. Seven record no waiting; one has only a trusted time0 event. Held prefixes remain96KiB/32KiB. Recovery assertions are not reached; no production fix or waiver." }, diff --git a/refactor/tasks.json b/refactor/tasks.json index 19a8eaba4..506a4189e 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -1756,7 +1756,8 @@ "dependsOn": [ "PKG-AUDIO-04", "CORE-22", - "CORE-24" + "CORE-24", + "PKG-AUDIO-BUFFER-01" ], "status": "doing", "risk": "H", @@ -6159,6 +6160,26 @@ "changes/2026-09-16-CI-NPM-02-verify-bundle.md", "baselines/npm-bundle-verification.json" ] + }, + { + "id": "PKG-AUDIO-BUFFER-01", + "phase": "5 包迁移:artplayer-plugin-audio-track", + "title": "修正断流测试的切源等待顺序", + "scope": [ + "artplayer-plugin-audio-track" + ], + "dependsOn": [ + "PKG-AUDIO-04", + "CORE-22" + ], + "status": "done", + "risk": "M", + "deliverable": "网络扣留时独立观察切源Promise;完整元数据扣帧回归与阶段诊断", + "acceptance": "旧顺序复现死等,三浏览器新旧组合可放行并验证恢复;保留真实缓冲失败,不以本项关闭Audio-05或设备门槛", + "evidence": [ + "changes/2026-09-16-PKG-AUDIO-BUFFER-01-order.md", + "baselines/audio-buffer-order-validation.json" + ] } ] } diff --git a/test/browser/audio-buffering.spec.js b/test/browser/audio-buffering.spec.js index d473f5886..ff41fc459 100644 --- a/test/browser/audio-buffering.spec.js +++ b/test/browser/audio-buffering.spec.js @@ -6,14 +6,70 @@ import { expect, test } from './fixtures.js' const { openAudio } = useAudioFixture() +async function beginAudioSwitch(page, url) { + // switchUrl may await canplay/play; do not return its pending Promise to + // Playwright before the test can observe or release the real network gate. + await page.evaluate((url) => { + window.starvationSwitch = { status: 'pending', startedAt: performance.now() } + window.art.switchUrl(url).then(() => { + window.starvationSwitch.status = 'fulfilled' + window.starvationSwitch.settledAt = performance.now() + }, (error) => { + window.starvationSwitch.status = 'rejected' + window.starvationSwitch.error = String(error) + window.starvationSwitch.settledAt = performance.now() + }) + }, url) +} + for (const core of ['published', 'candidate']) { for (const plugin of ['published', 'source']) { + test(`${core} core + ${plugin} audio: held switch can release before its Promise settles`, async ({ page }, testInfo) => { + const bytes = fs.readFileSync(new URL('./media/pattern.mp4', import.meta.url)) + const metadata = bytes.readUInt32BE(0) + expect(bytes.toString('ascii', 4, 8)).toBe('ftyp') + expect(bytes.toString('ascii', metadata + 4, metadata + 8)).toBe('moov') + // Send complete format/metadata boxes, but withhold all encoded frames. + const limit = metadata + bytes.readUInt32BE(metadata) + const gate = await createMediaGate(bytes, 'video/mp4', limit) + let phase = 'initial-playback' + try { + await openAudio(page, core, plugin, testInfo) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.art.currentTime > 0.3 && window.audioPlugin.audio.currentTime > 0.3)).toBe(true) + phase = 'begin-switch' + await beginAudioSwitch(page, gate.url) + phase = 'held-request' + await expect.poll(() => gate.blocked).toBeGreaterThan(0) + expect(await page.evaluate(() => window.starvationSwitch.status)).toBe('pending') + expect(gate.requests.some(request => request.wasHeld && request.sent === limit)).toBe(true) + phase = 'network-release' + gate.release() + await expect.poll(() => page.evaluate(() => window.starvationSwitch)).toMatchObject({ status: 'fulfilled' }) + await expect.poll(() => page.evaluate(() => window.art.currentTime > 0.3 && window.audioPlugin.audio.currentTime > 0.3 && !window.art.video.paused && !window.audioPlugin.audio.paused)).toBe(true) + expect(await page.evaluate(() => [window.art.video.error, window.audioPlugin.audio.error])).toEqual([null, null]) + phase = 'complete' + } + finally { + try { + const state = page.isClosed() ? { closed: true } : await page.evaluate(() => ({ switch: window.starvationSwitch, hostEvents: window.audioHostEvents })) + await testInfo.attach('held-switch', { contentType: 'application/json', body: JSON.stringify({ phase, ...state, sha256: hash(bytes), limit, requests: gate.requests }) }) + if (!page.isClosed()) + await page.evaluate(() => window.art?.destroy()) + } + finally { + await gate.close() + } + } + }) + for (const owner of ['video', 'audio']) { test(`${core} core + ${plugin} audio: real ${owner} starvation resumes after network release`, async ({ page }, testInfo) => { const file = owner === 'video' ? 'pattern.mp4' : 'audio-tone.m4a' const bytes = fs.readFileSync(new URL(`./media/${file}`, import.meta.url)) const limit = owner === 'video' ? 96 * 1024 : 32 * 1024 const gate = await createMediaGate(bytes, owner === 'video' ? 'video/mp4' : 'audio/mp4', limit) + let phase = 'initial-playback' try { await openAudio(page, core, plugin, testInfo, owner === 'audio' ? gate.url : '/test/audio-tone.m4a') await page.evaluate((owner) => { @@ -25,8 +81,10 @@ for (const core of ['published', 'candidate']) { }, owner) await page.locator('#play').click() await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime > 0.3 && window.art.currentTime > 0.3)).toBe(true) - if (owner === 'video') - await page.evaluate(url => window.art.switchUrl(url), gate.url) + if (owner === 'video') { + await beginAudioSwitch(page, gate.url) + } + phase = 'native-starvation' await expect.poll(() => page.evaluate(() => window.starvation.some(event => event.trusted && event.time > 0.3 && event.readyState < 3))).toBe(true) expect(gate.blocked).toBeGreaterThan(0) const stalled = await page.evaluate(() => ({ audio: window.audioPlugin.audio.currentTime, video: window.art.currentTime })) @@ -37,18 +95,31 @@ for (const core of ['published', 'candidate']) { await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(stalled.video + 0.3) expect(await page.evaluate(() => window.art.video.paused)).toBe(false) } + phase = 'network-release' gate.release() + if (owner === 'video') { + await expect.poll(() => page.evaluate(() => window.starvationSwitch)).toMatchObject({ status: 'fulfilled' }) + } + phase = 'playback-recovery' await expect.poll(() => page.evaluate(() => !window.audioPlugin.audio.paused && !window.art.video.paused)).toBe(true) await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeGreaterThan(stalled.audio + 0.3) await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(stalled.video + 0.3) await expect.poll(() => page.evaluate(() => Math.abs(window.audioPlugin.audio.currentTime - window.art.currentTime))).toBeLessThan(0.5) expect(await page.evaluate(() => [window.art.video.error, window.audioPlugin.audio.error])).toEqual([null, null]) + phase = 'complete' } finally { try { await testInfo.attach('media-gate-requests', { contentType: 'application/json', body: JSON.stringify({ file, sha256: hash(bytes), bytes: bytes.length, limit, requests: gate.requests }) }) const events = page.isClosed() ? { closed: true } : await page.evaluate(() => window.starvation) await testInfo.attach('media-gate', { contentType: 'application/json', body: JSON.stringify({ file, sha256: hash(bytes), bytes: bytes.length, limit, requests: gate.requests, events }) }) + const state = page.isClosed() + ? { closed: true } + : await page.evaluate(() => { + const media = element => element && ({ time: element.currentTime, paused: element.paused, readyState: element.readyState, ended: element.ended, error: element.error?.code ?? null }) + return { switch: window.starvationSwitch, video: media(window.art?.video), audio: media(window.audioPlugin?.audio), hostEvents: window.audioHostEvents } + }) + await testInfo.attach('audio-buffering-phase', { contentType: 'application/json', body: JSON.stringify({ phase, ...state }) }) if (!page.isClosed()) await page.evaluate(() => window.art?.destroy()) }