diff --git a/packages/artplayer-plugin-dash-control/ARCHITECTURE.md b/packages/artplayer-plugin-dash-control/ARCHITECTURE.md index 13a904e54..876e12ce5 100644 --- a/packages/artplayer-plugin-dash-control/ARCHITECTURE.md +++ b/packages/artplayer-plugin-dash-control/ARCHITECTURE.md @@ -151,8 +151,12 @@ devices and installed package acceptance remain separate release gates. `dash-sdk.spec.js` now separately loads hash-pinned npm dash.js 4.5.2/5.2.1 and local multi-quality/multi-audio DASH segments. It covers decoding, explicit update after external selection, source topology replacement, retained callbacks and SDK ownership. -It also includes a native SDK control without an ArtPlayer instance. Early SDK 4.5.2 -paused-seek stalls remain open; later passes do not resolve them. Unsupported MSE is +It also includes a native SDK control without an ArtPlayer instance. SDK 4.5.2 +paused-seek stalls reproduce independently: its empty buffer-clear path preserves +stale buffer metrics and can prevent further scheduling. A diagnostic backport of +the SDK 5 buffer-level refresh confirms the cause; no production workaround ships. +See the [diagnosis](../../refactor/changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md). +The compatibility risk remains open. Unsupported MSE is recorded as a playback capability gap, not acceptance. SDK event tests also cover external selections without explicit update, same-SDK source replacement, asynchronous formatter error/recovery, and actual setting clicks during SDK refresh. diff --git a/refactor/baselines/dash-seek-diagnosis.json b/refactor/baselines/dash-seek-diagnosis.json new file mode 100644 index 000000000..cdfa0fa81 --- /dev/null +++ b/refactor/baselines/dash-seek-diagnosis.json @@ -0,0 +1,3705 @@ +{ + "schemaVersion": 1, + "task": "PKG-DASH-05", + "risk": "DASH-SEEK-01", + "sourceCommit": "a9cf50bc", + "status": "root cause identified; production mitigation and release acceptance remain open", + "inputs": [ + { + "file": "test/browser/dash-sdk.spec.js", + "sha256LF": "51a11287230b7b8a2f392c939cda1c2f8da356208dc8de5966e8cb2c4c69999f" + }, + { + "file": "test/browser/dash-buffer-observer.js", + "sha256LF": "37d8e8ab67155a99a233afa35a82da777fdfb3f691e47a4b0016a46b09b3daa0" + } + ], + "sources": [ + { + "version": "4.5.2", + "archiveSHA256": "9a0944c48deb0fd8f92b0eea436c5b0d0aea9237c7da0078c0310f1430d0a31f", + "member": "package/dist/dash.all.debug.js", + "sha256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "methodLine": 41184, + "emptyBranchRefreshesLevel": false + }, + { + "version": "5.2.1", + "archiveSHA256": "4eacb0cc3525276666ca3f084611cdabb5a2264d128dfe0750fe106fbddd088f", + "member": "package/dist/modern/umd/dash.all.debug.js", + "sha256": "94a3c83e8c78da6f4f29ecca2403d6c4114c7edca79349a092e7df87c5d9aa53", + "methodLine": 44777, + "emptyBranchRefreshesLevel": true + } + ], + "artifacts": [ + { + "file": "packages/artplayer-plugin-dash-control/dist/artplayer-plugin-dash-control.js", + "bytes": 7410, + "sha256": "a594009be5c17406844f817c5a79930c6ed60add4a5ef0578783f163a1bae012", + "unchangedFrom": "a9cf50bc" + }, + { + "file": "packages/artplayer-plugin-dash-control/dist/artplayer-plugin-dash-control.legacy.js", + "bytes": 7881, + "sha256": "b00a837a99f7a7cccd415af335cbf0c68f1e4267fa7cfd8d91e945e3dc634151", + "unchangedFrom": "a9cf50bc" + }, + { + "file": "packages/artplayer-plugin-dash-control/dist/artplayer-plugin-dash-control.mjs", + "bytes": 14070, + "sha256": "0c5a7e4d84e9641778e0a22ff9c78db9bd4ac2f08f51358519443046a528fb93", + "unchangedFrom": "a9cf50bc" + } + ], + "browser": [ + { + "name": "buffers", + "scope": "Native SourceBuffer and SDK metric observations", + "stats": { + "startTime": "2026-09-11T22:36:15.479Z", + "duration": 30924.601, + "expected": 9, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "cases": [ + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.408181, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.765, + "audio": 3.603 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3567.4000000059605, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.434266, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.774, + "audio": 3.611 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3760.5, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "failed", + "diagnostic": null, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 5.999999 + ] + ], + "levels": { + "video": 2.975, + "audio": 4.975 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 5.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3534.5999999940395, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.437749, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.784, + "audio": 3.601 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4081.199999988079, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.359367, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.786, + "audio": 1.786 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3633.5, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.375507, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.75, + "audio": 3.713 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4006, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 7.166897, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 2.916, + "audio": 4.916 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4112, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.3752, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.748, + "audio": 3.714 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4128, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.333826, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.75, + "audio": 3.713 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4211, + "time": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 7.125407, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 3.208, + "audio": 5.208 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3218, + "time": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-buffers/failure-state.json", + "bytes": 31613, + "sha256": "ab0e30676cb639a000d315d41bde841ad2dd1141cdd9acaa06617c3c850a507a" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/report.json", + "bytes": 1388170, + "sha256": "da752ed6840627432c648f99289020bc8ae7345b60e960ea99292a079dd24e84" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/.last-run.json", + "bytes": 96, + "sha256": "588ae594105f2a249eccafe9a431e03cde8b797116851e13f027f3e68af66397" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 4024477, + "sha256": "de9a8de2c28b549fe24a588acf1b771948fadfe2c0f4e54b15953a0a58862d58" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3518902, + "sha256": "3c2711532beb0cdbaea9b0816c939ed8cbb5675a4932c273e48d9b7f6f8b5824" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/error-context.md", + "bytes": 2810, + "sha256": "1126e51a0f974d03562e46238bbff892a78f8ec33a1c2767ab25e12775ca06ee" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/test-failed-1.png", + "bytes": 81060, + "sha256": "c207eb4365f3ea45dc7c1ac4a06157098523ae8279e40e8988c2b80ceb9d715d" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 7378293, + "sha256": "13f1388223c475f50602c7541bb0250ea0439c69343bbe52671a6b532e92dec6" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3345774, + "sha256": "2906a604f98901f7b3a761081237e8b7560c3de8ed4ffc4ae15a41e6468dca71" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1571039, + "sha256": "c7d3fe9c5a6691d50902463c1fa17d35d166087711964b695434c8e7f96aa4a5" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 2000414, + "sha256": "7956fec614aba608b9e7344be3a4554620d365986f34dbc4e4fb28f22e5597bf" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3953322, + "sha256": "f55d85371a25cbee6a4524eb0073f32e0cd4ac7a7514c495ece1747317a236c5" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 4091893, + "sha256": "ce60f8ed99975a089eb48b212f580bb2a14f4f8ffe3dc341cfb3e4f2d62d2509" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3524426, + "sha256": "b21126f77ac701bdb9029f1455312191c983eeb56cbe8f1b1cdef270143d1815" + }, + { + "file": "refactor/.cache/dash05-seek-buffers/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3316923, + "sha256": "66e5e751fdd5ae63924765f4ccf2c3cfe57bee917a0c70923ccb6de7f65dd48e" + } + ] + }, + { + "name": "target", + "scope": "Added SDK seekTime and matched native pre-seek playback/track state", + "stats": { + "startTime": "2026-09-11T22:39:05.265Z", + "duration": 27174.761000000002, + "expected": 10, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.400397, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.776, + "audio": 3.639 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3582.600000023842, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.39478, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.78, + "audio": 3.616 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3981.7999999821186, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.440784, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.784, + "audio": 3.593 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3566.2999999821186, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.416456, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.786, + "audio": 3.593 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4014.199999988079, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.357378, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.78, + "audio": 1.78 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3668.5999999940395, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.417065, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.748, + "audio": 3.63 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4047, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.24906, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 2, + "audio": 3.839 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4159, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.417128, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.708, + "audio": 3.672 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4160, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.667146, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 3.46, + "audio": 5.375 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4013, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.337044, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.75, + "audio": 1.75 + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 8 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4021, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-target/report.json", + "bytes": 1491641, + "sha256": "e056e077996666dadb1f2c4448f71408891777b902d9637202f0cbd1d028f135" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/.last-run.json", + "bytes": 45, + "sha256": "91d1c43004802cd49950d78eb11c8fa7d05da8ffffe219a8b13b2f561bc00903" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3882084, + "sha256": "f8c36576dfeec14532840ef6f470792b12540bdfa37913bfcca9aa692434abfe" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3469509, + "sha256": "494af31e7bab29db4ed80a42d3cd7ca951cd506533e2dda96f5135a8e3ffafb6" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3610196, + "sha256": "9dfe2d751bcd9cac716db35c7e8b45427afd6b1402be3904520f90dea233cdd0" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3081639, + "sha256": "ddde7e467c1a6e259016ef003819d0054de416b0e447fe02b8bcafcc001b1d89" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1583495, + "sha256": "040ad28b2dff9edd80f267fac120c342e665a7b4793aa7dba8b3de0e3c98f1c1" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 1766986, + "sha256": "eae44077cc10a3fe8fe3ee8bda4996b6ebc2c4c815a862bd0990cbbabfbc9f96" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3662832, + "sha256": "1a1ee5683a2858974ecc69c60dc87d44d1d38890438d1ace4706771333d6e290" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3073013, + "sha256": "ddd75dda700a7ab15fbf742eed8b99c313bc3db61463f08db07e561e64433381" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3565548, + "sha256": "757621c79307557cf3e67f9a342421d07323e4b30cf0019c796267e9b672aad7" + }, + { + "file": "refactor/.cache/dash05-seek-target/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3186597, + "sha256": "461c13e2f91c55c4188a66f40efa7a86566424d56a320667b2897d7beaf2a91a" + } + ] + }, + { + "name": "processors", + "scope": "Added timeupdate, buffer-level events and processor state", + "stats": { + "startTime": "2026-09-11T22:41:56.779Z", + "duration": 35714.394, + "expected": 8, + "skipped": 0, + "unexpected": 2, + "flaky": 0 + }, + "cases": [ + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "failed", + "diagnostic": null, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 5.999999 + ] + ], + "levels": { + "video": 2.956, + "audio": 4.956 + }, + "processors": [ + { + "type": "video", + "level": 2.956085, + "complete": false, + "pruning": false, + "hasTarget": false + }, + { + "type": "audio", + "level": 4.956085, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 5.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3541.300000011921, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.391721, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.787, + "audio": 3.618 + }, + "processors": [ + { + "type": "video", + "level": 1.7866429999999998, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6181140000000003, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3906.5, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "failed", + "diagnostic": null, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 5.999999 + ] + ], + "levels": { + "video": 2.958, + "audio": 4.958 + }, + "processors": [ + { + "type": "video", + "level": 2.958488, + "complete": false, + "pruning": false, + "hasTarget": false + }, + { + "type": "audio", + "level": 4.958488, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 5.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3555.600000023842, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.433495, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.782, + "audio": 3.581 + }, + "processors": [ + { + "type": "video", + "level": 1.782311, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.5812170000000005, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4045.699999988079, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.358472, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.786, + "audio": 1.786 + }, + "processors": [ + { + "type": "video", + "level": 1.7855289999999995, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 1.7855289999999995, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3644.800000011921, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.37519, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.709, + "audio": 3.715 + }, + "processors": [ + { + "type": "video", + "level": 1.7092289999999997, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.714562, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4097, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 7.208875, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 2.916, + "audio": 4.916 + }, + "processors": [ + { + "type": "video", + "level": 2.9162229999999996, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 4.916223, + "complete": true, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4061, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.37546, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.75, + "audio": 3.672 + }, + "processors": [ + { + "type": "video", + "level": 1.7496039999999997, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.671734, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4107, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.625234, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 3.416, + "audio": 5.416 + }, + "processors": [ + { + "type": "video", + "level": 3.416221, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 5.416221, + "complete": true, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3992, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.375162, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.749, + "audio": 3.671 + }, + "processors": [ + { + "type": "video", + "level": 1.749383, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6713890000000005, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3981, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-processors/failure-1.json", + "bytes": 70510, + "sha256": "65ccd76c89af9d663601e1e0c1cc0ed9777de206e53358592a81af5d344d1cbe" + }, + { + "file": "refactor/.cache/dash05-seek-processors/failure-2.json", + "bytes": 70360, + "sha256": "e85212df420a9f7854340f004bbad1418b2f4c0c9669ace85fde679bc8fc4d25" + }, + { + "file": "refactor/.cache/dash05-seek-processors/report.json", + "bytes": 1599305, + "sha256": "2330111e353e5bb6f7c5fd532b79fbe717f9d48f56cdd526d744b266562537c0" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/.last-run.json", + "bytes": 145, + "sha256": "ed5339338a98f1795ffeec9a7fddb0d074bd7bc42eaf852630c3f68dd63bf4c9" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 4049494, + "sha256": "48ae0e430cc4797a6cc36ada570bef71aec5a756ed05acd41c677568ceb3ebe2" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3480144, + "sha256": "cc4c21ee0719d545f21a6a119966c84effe134c77345ed80bdb444574e61f1c2" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/error-context.md", + "bytes": 2810, + "sha256": "1126e51a0f974d03562e46238bbff892a78f8ec33a1c2767ab25e12775ca06ee" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/test-failed-1.png", + "bytes": 80172, + "sha256": "3a1ce97130c1f0da97b4cd79b30d6a097a6913177d90625537e51cfbdc2556e6" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 7456553, + "sha256": "0e881d099222a3e1c50ed9e9d3894a28658dfbc4f9c35cca5a5cd9b2272124b1" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3339032, + "sha256": "8da05cb5556ceba96c6b2a3b5dcd38aa5638727ad7fb47c09a2ad41d3ee3c0be" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1611817, + "sha256": "193803cdefba79ee92d6e4fca314d4d527fc0e6b4f28a4009539a9773ddf0417" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 1771648, + "sha256": "39e4ba95e5a7bd300b35df0967518da9c401b837cebd91048b0b7bbcd3a4cbb4" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3861308, + "sha256": "c33003d899615b0614388bba1ac8ef8a91c63512de4c04de071515aaae9ca948" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 4142555, + "sha256": "fcc414a06857f28b1ab8f6f2cc9554028a98cdefbf3756fa080b7d3cd217456d" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/error-context.md", + "bytes": 2810, + "sha256": "bd283e6a4cf0f4c0e12eb3462b326af07fae6b9055d212bd92eefb490eca3e5c" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/test-failed-1.png", + "bytes": 80394, + "sha256": "7767e9550f86ae687fb94b0edc2396c3a91b1a53bdbed0dc83a9da91da9ee21e" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 7669973, + "sha256": "d2a2d8d715b496564895223b01dacfe23f37c02cba943e0ac29447d3e3006e0c" + }, + { + "file": "refactor/.cache/dash05-seek-processors/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3088463, + "sha256": "004b0c202833f4e5ef42135ff4b251709d88f9d7350956d34e32c22b4de4f984" + } + ] + }, + { + "name": "native-held", + "scope": "Real SDK 4/5 without ArtPlayer, pause quiescence; failed cases receive diagnostic synthetic timeupdate after failure", + "stats": { + "startTime": "2026-09-11T22:43:58.712Z", + "duration": 18313.77, + "expected": 2, + "skipped": 0, + "unexpected": 2, + "flaky": 0 + }, + "cases": [ + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "failed", + "diagnostic": null, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 5.999999 + ] + ], + "levels": { + "video": 2.81, + "audio": 4.81 + }, + "processors": [ + { + "type": "video", + "level": 2.809717, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": false + }, + { + "type": "audio", + "level": 4.809717, + "target": 3.81, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 5.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4161.9000000059605, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": { + "before": { + "video": 2.81, + "audio": 4.81 + }, + "after": { + "video": 0, + "audio": 2 + }, + "advanced": true, + "finalTime": 6.204735, + "finalSeeking": false + } + }, + { + "title": "dash.js 5.2.1: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.347007, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 3.989333, + 7.999999 + ] + ], + "levels": { + "video": 1.781, + "audio": 3.786 + }, + "processors": { + "unavailable": "TypeError: dash?.getActiveStream(...)?.getProcessors is not a function" + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 3.989333, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 5711.199999988079, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "failed", + "diagnostic": null, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 6 + ] + ], + "levels": { + "video": 2.748, + "audio": 4.748 + }, + "processors": [ + { + "type": "video", + "level": 2.74811, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 4.7481100000000005, + "target": 3.748, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 6 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 8 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4515, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": { + "before": { + "video": 2.748, + "audio": 4.748 + }, + "after": { + "video": 0, + "audio": 2 + }, + "advanced": true, + "finalTime": 6.207506, + "finalSeeking": false + } + }, + { + "title": "dash.js 5.2.1: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": null, + "bufferState": { + "time": 6.374188, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.751, + "audio": 1.751 + }, + "processors": { + "unavailable": "TypeError: dash.getActiveStream().getProcessors is not a function" + }, + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 8 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4562, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-native-held/recovery-chromium.json", + "bytes": 3579, + "sha256": "ac99577f92026a11358460ee08579c6bfd971558390e401d978a5c70851f7a61" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/recovery-firefox.json", + "bytes": 3475, + "sha256": "70a7d85ff70086f096db55d781563d3ced0328dd6b697dbe0b70859d15254563" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/report.json", + "bytes": 290452, + "sha256": "afe9dd35cab36d4a60cc8d18f5e1aec403baf0ec3ecbac70c360735053b71952" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/.last-run.json", + "bytes": 145, + "sha256": "e46e8801e09e4e803f44da9c71e6f8555a8094ebf5eb5e7e19c237b09bc53f0d" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/error-context.md", + "bytes": 15703, + "sha256": "e75d3e1a29ff0b31d023d1be067cbc512c679e0b4569df173f86ea96e72dc6ef" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/test-failed-1.png", + "bytes": 28232, + "sha256": "6e74653092b0a251d952ab4a7d595e2fa176ceeafe89fa928436c996cf4f7820" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1613180, + "sha256": "167515c4f2855f7298b6a66cd8339d8a8336fb57dc4e16c6bb2591ca88dcace6" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/error-context.md", + "bytes": 15703, + "sha256": "e75d3e1a29ff0b31d023d1be067cbc512c679e0b4569df173f86ea96e72dc6ef" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/test-failed-1.png", + "bytes": 35407, + "sha256": "ef5e17fcab4bc6125380efb2fb317eb929c75e3797871bdbf5d7e4c6034159f6" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 2738168, + "sha256": "fea46c67368c54437283738d07014fd5e43d3c569f1fc431bbb80e0dea5751e1" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-5-2-1-nat-95d9f-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1841985, + "sha256": "e574ee85bccad458e67defea4fd96de5752220373adadb5b44cc85ffb47a0cc7" + }, + { + "file": "refactor/.cache/dash05-seek-native-held/results/dash-sdk-dash-js-5-2-1-nat-95d9f-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 1958502, + "sha256": "97e26dd3fd1b621996b1cf573ebe618a080f6b0024440430d820d6d159762725" + } + ] + }, + { + "name": "debug-control", + "scope": "Unmodified SDK 4 debug member, native held pause", + "stats": { + "startTime": "2026-09-11T22:45:58.964Z", + "duration": 15415.101, + "expected": 1, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + }, + "cases": [ + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "failed", + "diagnostic": { + "mode": "upstream4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "acceptance": false + }, + "bufferState": { + "time": 6, + "paused": false, + "seeking": true, + "readyState": 1, + "video": [ + [ + 1.984, + 5.999999 + ] + ], + "levels": { + "video": 2.811, + "audio": 4.811 + }, + "processors": [ + { + "type": "video", + "level": 2.81091, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": false + }, + { + "type": "audio", + "level": 4.81091, + "target": 3.811, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 5.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 7.999999 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4287.4000000059605, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "upstream4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "acceptance": false + }, + "bufferState": { + "time": 6.372414, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 3.989333, + 8 + ] + ], + "levels": { + "video": 1.791, + "audio": 3.797 + }, + "processors": [ + { + "type": "video", + "level": 1.7912730000000003, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.7966060000000006, + "target": 2.791, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 3.989333, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 6045, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-debug-control/report.json", + "bytes": 148796, + "sha256": "d91c2f412267282b56879e9c87dc9e9144d21d7b8e624cf917810e8e20577847" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control/results/.last-run.json", + "bytes": 96, + "sha256": "13a2fcfd48a5bf705ca36ffbf6b3b710ffff4b3035f77aa94be0812c98dc913b" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/error-context.md", + "bytes": 15703, + "sha256": "eb1e0d68efb8e86073a8ca43177f9dacb973c6c0c6703db0f93a4d116c058d33" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/test-failed-1.png", + "bytes": 28854, + "sha256": "fc59193858bbfaa3f6e66d63643c0491e462849e234e5af3e1d037ea8c48ad63" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1657845, + "sha256": "67582bd6b258031dead280aad9c8278bba0f3fef2ee8a91a7d81bca1693ff50a" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 2317206, + "sha256": "ac5ef4ae16ce13e72e1c4b612d9ba70fef3058c783594c20f4a3c4609a466646" + } + ] + }, + { + "name": "patch-counterfactual", + "scope": "Diagnostic SDK 4 debug member with one empty-clear buffer-level update; NOT unmodified SDK acceptance", + "stats": { + "startTime": "2026-09-11T22:46:48.896Z", + "duration": 27637.845999999998, + "expected": 10, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.41513, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.76, + "audio": 3.627 + }, + "processors": [ + { + "type": "video", + "level": 1.7598479999999999, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6266180000000006, + "target": 2.76, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3685.5999999940395, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.405209, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.711, + "audio": 3.646 + }, + "processors": [ + { + "type": "video", + "level": 1.7106810000000001, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6458060000000003, + "target": 2.7110000000000003, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3996, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.406743, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.78, + "audio": 3.603 + }, + "processors": [ + { + "type": "video", + "level": 1.7795649999999998, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6032160000000006, + "target": 2.7800000000000002, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3749.4000000059605, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "chromium", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.422353, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.789, + "audio": 3.648 + }, + "processors": [ + { + "type": "video", + "level": 1.7893289999999995, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6478790000000005, + "target": 2.7889999999999997, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 3984.0999999940395, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "chromium", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.367564, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 7.999999 + ] + ], + "levels": { + "video": 1.783, + "audio": 3.647 + }, + "processors": [ + { + "type": "video", + "level": 1.782794, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.64715, + "target": 2.783, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 7.999999 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4329.300000011921, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.376463, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.664, + "audio": 3.669 + }, + "processors": [ + { + "type": "video", + "level": 1.6640540000000001, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6693870000000004, + "target": 2.6639999999999997, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4096, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "published core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.624618, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 3.501, + "audio": 5.458 + }, + "processors": [ + { + "type": "video", + "level": 3.5010060000000003, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 5.45801, + "target": 4.5009999999999994, + "complete": true, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4149, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / published DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.375405, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.625, + "audio": 3.63 + }, + "processors": [ + { + "type": "video", + "level": 1.6245950000000002, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 3.6299280000000005, + "target": 2.625, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 10.005333 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4202, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "candidate core / candidate DASH / 4.5.2: real MPD decoding and UI selection", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.625537, + "paused": false, + "seeking": false, + "readyState": 4, + "video": [ + [ + 1.984, + 10 + ] + ], + "levels": { + "video": 3.5, + "audio": 5.416 + }, + "processors": [ + { + "type": "video", + "level": 3.499554, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 5.416118, + "target": 4.5, + "complete": true, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 10 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 12 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4047, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + }, + { + "title": "dash.js 4.5.2: native SDK track switch and paused seek without ArtPlayer", + "engine": "firefox", + "status": "passed", + "diagnostic": { + "mode": "bufferlevel4", + "member": "package/dist/dash.all.debug.js", + "upstreamSHA256": "90bc26d2d3ba5a204a97d21bcfe246aab60f13f60ad75840c7f1fcc909986769", + "effectiveSHA256": "11fdf4dd33f63f4cd06036da59c13de0fe6e0db691eedb4feb488204e2643f95", + "acceptance": false + }, + "bufferState": { + "time": 6.292211, + "paused": false, + "seeking": false, + "readyState": 3, + "video": [ + [ + 1.984, + 8 + ] + ], + "levels": { + "video": 1.75, + "audio": 1.75 + }, + "processors": [ + { + "type": "video", + "level": 1.74986, + "target": 2, + "complete": false, + "pruning": false, + "hasTarget": true + }, + { + "type": "audio", + "level": 1.74986, + "target": 2.75, + "complete": false, + "pruning": false, + "hasTarget": true + } + ], + "buffers": [ + { + "mime": "video/mp4;codecs=\"avc1.42c01e\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 0, + 8 + ] + ], + "timestampOffset": 0 + }, + { + "mime": "audio/mp4;codecs=\"mp4a.40.2\"", + "sourceState": "open", + "updating": false, + "ranges": [ + [ + 1.984, + 8 + ] + ], + "timestampOffset": 0 + } + ] + }, + "sdkSeek": [ + { + "name": "PLAYBACK_SEEKING", + "at": 4678, + "time": 6, + "seekTime": 6 + } + ], + "syntheticRecovery": null + } + ], + "evidence": [ + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/report.json", + "bytes": 1844217, + "sha256": "0824af993097545140cf8c1c888ae09ce5ea591642ef4c359367e25979bcf798" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/.last-run.json", + "bytes": 45, + "sha256": "91d1c43004802cd49950d78eb11c8fa7d05da8ffffe219a8b13b2f561bc00903" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 4144006, + "sha256": "0de3763558a36a5e446771ce5c5059cab4790b86000f01673736061985739aef" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-candidate-core-ca-69287-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3886992, + "sha256": "3d9e9708f254c5c46991534bf5b12e628320d4dd7132bb6540a011e2dfe1458e" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3818123, + "sha256": "7e5f4b61d8b6ef66a329a8493ec7f3668d1af6081f597d36223e5bc0b93926dd" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-candidate-core-pu-83e89-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3425251, + "sha256": "a42872a162ff88010ea835506b1ef82490e86189fbb52e43a927d1c33e4c8659" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-chromium/trace.zip", + "bytes": 1941033, + "sha256": "50ea9d110a166ff9b29d8e67a2f32724adbf59d4d5bba76bc064a02370197eee" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-dash-js-4-5-2-nat-cf307-used-seek-without-ArtPlayer-firefox/trace.zip", + "bytes": 2069679, + "sha256": "197c6a5584679582999387db497dc7883033d32dc9261d06cf8561fa3a2df3cb" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 4182679, + "sha256": "b932625b616c0779b99bc04fa867a39097113c452135b2fd4c69f7fd83330036" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-published-core-ca-870f4-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3918287, + "sha256": "da515449a656d7d7be60ce729f575322b7d61f0af64161a57e250e144d94f193" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-chromium/trace.zip", + "bytes": 3913205, + "sha256": "b93434bac318bb274f3a5168ff7d6a3e42f334bdf4219a5e5868b6623b75c022" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual/results/dash-sdk-published-core-pu-c466c-D-decoding-and-UI-selection-firefox/trace.zip", + "bytes": 3265337, + "sha256": "c5a0a0d44940eb46dc4f7369009de460e44860911bdb2826d6dc12139c159b46" + } + ] + } + ], + "logs": [ + { + "file": "refactor/.cache/dash05-seek-baseline-check.log", + "bytes": 354, + "sha256": "70f4bef48d69ec8ed94fd79bdc9f5adcc8712c10b9a53e83dbd7e90315ba0c66" + }, + { + "file": "refactor/.cache/dash05-seek-buffers.log", + "bytes": 6973, + "sha256": "c5815de4855c37dd825302425ab53989cd2c4361f3dea40c340375fad347b885" + }, + { + "file": "refactor/.cache/dash05-seek-debug-control.log", + "bytes": 4096, + "sha256": "421540f62ef24389fca054550dce3d7bd246f9a4160f7fe22a440df7c833b0e0" + }, + { + "file": "refactor/.cache/dash05-seek-native-held.log", + "bytes": 7342, + "sha256": "15508383a33234f1f9c5eb5e263757d6c7559974bf91d7764f9b23307d92bbfc" + }, + { + "file": "refactor/.cache/dash05-seek-patch-counterfactual.log", + "bytes": 3195, + "sha256": "ee6e4f18cc8e948c74b57dbff0a12af7b27456c3d82570486266816fae4d0dbc" + }, + { + "file": "refactor/.cache/dash05-seek-processors.log", + "bytes": 10619, + "sha256": "4c9ff06f3a5156aedc08a6330396b5ae45c4bc979d7ddda688728d25657480b1" + }, + { + "file": "refactor/.cache/dash05-seek-target-after.log", + "bytes": 3196, + "sha256": "5534ff0471bbbeb923d0216de947f4df5f499cae351784cb4adf47360a9526d6" + }, + { + "file": "refactor/.cache/dash05-seek-target.log", + "bytes": 2496, + "sha256": "350a70c414bc35fc08cccac6841f349e40d28581d8e5de23b8f207be41b981f4" + } + ], + "conclusion": "SDK 4 empty buffer-clear branch preserves stale pre-seek metrics above scheduling target; with no later progress/timeupdate event, loading cannot resume. Native SDK 4 reproduces on both engines; synthetic metric refresh and one-line diagnostic backport restore playback. SDK 5 includes the refresh and passes the held-pause native cases.", + "exclusions": [ + "No runtime, declaration, dependency or SDK upgrade shipped", + "No synthetic timeupdate in production or default validation", + "Diagnostic patched SDK is not official SDK acceptance", + "SDK 4 risk stays open until compatible mitigation or reviewed release disposition", + "One intermediate syntax error prevented test discovery; original log retained", + "No complete browser matrix or full CI claimed for this diagnostic-only change" + ] +} diff --git a/refactor/changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md b/refactor/changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md new file mode 100644 index 000000000..3953bdbfe --- /dev/null +++ b/refactor/changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md @@ -0,0 +1,68 @@ +# PKG-DASH-05:暂停 seek 停滞的 SDK 根因 + +起点 `a9cf50bc`。本批没有修改生产源码、公开声明、依赖或产物。DASH-SEEK-01 从 +“偶发且来源未知”推进到可独立复现的 SDK 4.5.2 调度缺陷;**风险仍 open**,不能把诊断 +补丁的通过当成实际发布 SDK 或本项目的修复。DASH-05 继续 doing。 + +## 证据链 + +1. 给现有真实 SDK 测试增加原生 SourceBuffer 观测。原生 addSourceBuffer 仍以相同 this、 + 参数执行一次,返回原对象;额外监听 updateend 并读取缓冲,不改写媒体时间或片段。 + 首次 10 项中 9 通过、1 失败,再次复现新核心/已发布插件的 6 秒停滞。 +2. 失败时视频 SourceBuffer 与 video.buffered 均止于 5.999999 秒,排除 Chromium 上 + “SourceBuffer 其实已覆盖 6 秒”的猜测。SDK 仍保留暂停前约 2.975 秒的视频缓冲指标。 +3. 加入实际 SDK seekTime、timeupdate、bufferLevelUpdated 和处理器状态:10 项中 + 8 通过、2 失败,新旧核心搭配发布插件均失败。SDK 收到的目标为 6;视频 hasTarget=false、 + pruning=false、complete=false,旧缓冲量约 2.96 秒;seek 后没有后续时间/缓冲更新。 +4. 原生 SDK 对照不创建 ArtPlayer,只使用同一媒体、相同 SDK 设置和选择顺序。等待音轨 + 渲染完成,在约 3 秒暂停,并观察半秒内没有时钟/追加事件,再 seek 到 6 秒。 + 实际 npm 4.5.2 在 Chromium/Firefox 都失败,5.2.1 两边通过。该等待用于建立真实暂停 + 稳态、排除仍排队的进度更新,没有延长恢复超时或改变目标。 +5. 仅在上述断言失败后,启用诊断开关注入一次原生元素 timeupdate:SDK 4 视频指标立即 + 从 2.81/2.748 变成 0,随后请求下一视频片段,buffered 延长到约 8 秒,播放越过 6.2。 + 原测试仍记为失败,合成事件没有进入生产实现或默认验证路径。 +6. 读取校验过完整 npm 归档的 debug 成员:4.5.2 的 BufferController.clearBuffers 在 + ranges 为空时直接 resolve;5.2.1 同一分支先调用 _updateBufferLevel。 + 4.x ScheduleController 以缓存指标是否小于目标决定请求;失败时视频指标约 2.8 而 + 目标为 2,即使当前位置实际缺帧也不会下载。无后续 progress/timeupdate 时形成停滞。 +7. 保持 SDK 4 debug 字节不变的原生对照 1 通过/1 失败;仅在空裁剪分支增加 + _updateBufferLevel 的诊断补丁,原生及新旧核心/插件组合 10 项全部通过。 + 这是因果对照,不是正式 SDK 的发布准入。 + +Firefox 的视频范围恰好止于 6,SDK 的包含端点判断返回 true,但解码下一帧仍需下一片段。 +该路径的 pruneBuffer 也经过空 clearBuffers;相同缓冲量刷新解释了两引擎的恢复。 +这批证据说明是 SDK 调度所需数据未更新,不是 ArtPlayer 新核心修改了 seek 目标;历史 +Firefox/候选插件失败仍保留,不能据此声称所有其他 DASH 风险已经解决。 + +## 测试入口与隔离 + +默认 `yarn test:browser test/browser/dash-sdk.spec.js` 仍加载原始固定 npm min 产物。 +新增 `test/browser/dash-buffer-observer.js` 保存浏览器缓冲、SDK 指标及可用处理器状态。 +SDK 内部诊断 getter 不可用时只标记 unavailable;不通过修改 SDK 来模拟这些状态。 +每页新建后安装观测器,页面关闭释放资源,不复用到产品 demo。 + +原生复现可用 `--grep 'native SDK' --project chromium --project firefox --trace on`。 +诊断环境变量(用完应清空;每次运行前后归档共享报告和 traces): + +| 变量 | 值与用途 | +| --- | --- | +| ARTPLAYER_DASH_DIAGNOSE_STALL | 1:已失败且停在 6 秒时,保存合成时间更新的前后状态,不改变失败结果 | +| ARTPLAYER_DASH_DIAGNOSTIC_SDK | none/未设置:原始 min;upstream4:原始 SDK 4 debug;bufferlevel4:单分支诊断补丁 | + +debug 成员来自完整性校验后的 npm 归档;补丁仅在内存替换唯一匹配的完整分支,匹配数 +不是一就报错。输入附件记录原始/有效代码 SHA256、member、模式和 acceptance=false。 +不得在正式报告中省略诊断模式,不得把补丁归档冒充上游包,也不得将合成事件作为产品修复。 + +过程中一次括号笔误导致测试发现失败,日志保留;修正语法后继续取证。加入 seekTime 的 +中间运行 10 项通过,但没有以它关闭风险。全部失败、通过和对照的报告/trace 分别冻结, +见 [机器证据](../baselines/dash-seek-diagnosis.json)。本地缓存不提交,测试和摘要可重跑。 + +## 后续与回退 + +旧 SDK 合法调用仍须兼容;不能要求用户升级 SDK 后才算重构完成。后续应评审隔离且不改变 +调用方媒体事件/SDK 所有权的兼容处置,或正式记录第三方边界与发布处理。在此之前,风险和 +设备/完整分发门槛保持开放。不得在核心伪造 timeupdate、偏移 seek 或全局放宽测试。 + +局部 lint、既有 SDK/媒体来源测试及计划/风险链接校验用于本批验证;没有改生产代码, +不重复宣称完成全项目 CI 或 114 项完整浏览器验收。回退本批仅涉及诊断测试与文档, +生产产物与 a9cf50bc 的指纹保持一致。 diff --git a/refactor/dash-validation.md b/refactor/dash-validation.md index 78f869534..86fa40d76 100644 --- a/refactor/dash-validation.md +++ b/refactor/dash-validation.md @@ -79,3 +79,11 @@ UMD 测试 VM 显式注入宿主 console,以检查原始错误身份;没有 纯配置修改但没有 SDK 事件时,保留同步 update 为即时刷新入口;播放 tick 仅检查 Auto 布尔值变化,没有新定时器。真实 SDK/媒体验证与剩余 seek/设备边界见 [事件改造记录](changes/2026-09-12-PKG-DASH-05-sdk-events.md)。历史失败证据保留,后续通过不抹去它们。 + +## 05 暂停 seek 诊断 + +实际 SDK 4.5.2 在不创建 ArtPlayer 的稳定暂停用例中也会停滞,SDK 5.2.1 的对应用例通过。 +根因与空裁剪分支漏更新缓冲指标有关,DASH-SEEK-01 仍 open;没有发布兼容补丁。 +`dash-buffer-observer.js` 记录原生 SourceBuffer/SDK 指标,两个显式诊断环境变量只用于 +失败后的合成事件和内存 SDK 补丁对照,不能用于正式验收。命令、证据、限制和回退见 +[seek 根因记录](changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md)。 diff --git a/refactor/plan.md b/refactor/plan.md index 5d159ff67..d45e20aea 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -483,4 +483,4 @@ - PKG-DASH-02: [记录](changes/2026-09-12-PKG-DASH-02-tests.md) [记录](dash-validation.md) [记录](baselines/dash-validation.json) - PKG-DASH-03: [记录](changes/2026-09-12-PKG-DASH-03-runtime.md) [记录](baselines/dash-runtime.json) [记录](dash-validation.md) - PKG-DASH-04: [记录](changes/2026-09-12-PKG-DASH-04-types.md) [记录](baselines/dash-types-validation.json) [记录](dash-validation.md) -- PKG-DASH-05: [记录](changes/2026-09-12-PKG-DASH-05-sdk-checkpoint.md) [记录](baselines/dash-sdk.json) [记录](baselines/dash-sdk-checkpoint.json) [记录](dash-validation.md) [记录](changes/2026-09-12-PKG-DASH-05-sdk-types.md) [记录](baselines/dash-sdk-types-validation.json) [记录](changes/2026-09-12-PKG-DASH-05-sdk-events.md) [记录](baselines/dash-sdk-events-validation.json) +- PKG-DASH-05: [记录](changes/2026-09-12-PKG-DASH-05-sdk-checkpoint.md) [记录](baselines/dash-sdk.json) [记录](baselines/dash-sdk-checkpoint.json) [记录](dash-validation.md) [记录](changes/2026-09-12-PKG-DASH-05-sdk-types.md) [记录](baselines/dash-sdk-types-validation.json) [记录](changes/2026-09-12-PKG-DASH-05-sdk-events.md) [记录](baselines/dash-sdk-events-validation.json) [记录](changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md) [记录](baselines/dash-seek-diagnosis.json) diff --git a/refactor/progress.md b/refactor/progress.md index adc2ef289..74d48c1ed 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,17 @@ # 进度与证据 +## 当前实施:DASH-05 暂停 seek 根因已定位 + +真实 SourceBuffer、SDK seekTime/缓冲事件和处理器状态表明,SDK 4.5.2 在空裁剪分支未更新 +暂停前缓冲量,调度器继续按旧值阻止下载。不创建 ArtPlayer 的稳定暂停用例在 Chromium/ +Firefox 都复现;失败后合成一次 timeupdate 能恢复,测试仍保留失败。SDK 5.2.1 原生用例 +两边通过;将其缓冲刷新移入 SDK 4 的单分支诊断补丁后,原生/新旧组合 10 项通过。 + +本批只增加诊断测试和证据,没有向生产注入事件、修补 SDK、增加依赖或改变产物。 +DASH-SEEK-01 根因已知但兼容处置尚未完成,仍 open。DASH-05 仍 doing,217 项仍为 +74 done、4 doing、139 todo。详见 [根因记录](changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md) +和 [执行证据](baselines/dash-seek-diagnosis.json)。其余包的独立源码迁移可继续,发布门槛不降低。 + ## 当前实施:DASH-05 SDK 事件刷新源码改造 新增第六个严格 TS 模块 sdk-events:按 SDK 质量/音轨/流事件合并刷新菜单,保留同步 diff --git a/refactor/risk-table.md b/refactor/risk-table.md index 4937abef3..46cc135f4 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -140,4 +140,4 @@ | DASH-STATE-01 | resolved / 已复现 | DASH 当前项高亮使用真值 ID、音轨身份和标签去重,边界待核实 | PKG-DASH-02, PKG-DASH-03, PKG-DASH-05 | | DASH-TYPE-01 | resolved / 源码/产物事实 | DASH 类型未表达默认工厂参数、SDK 回调对象和现代模块入口 | PKG-DASH-04 | | DASH-DEMO-01 | open / 源码/产物事实 | DASH 示例仅新 SDK 且重复安装会累积销毁回调 | PKG-DASH-06 | -| DASH-SEEK-01 | open / 已复现 | 真实 dash.js 4.5.2 暂停 seek 到缓冲片段边界后可能持续 waiting | PKG-DASH-05, REVIEW-02 | +| DASH-SEEK-01 | open / 已复现 | dash.js 4.5.2 空裁剪漏更新缓冲量,稳定暂停 seek 后调度停滞 | PKG-DASH-05, REVIEW-02 | diff --git a/refactor/risks.json b/refactor/risks.json index 4b09f8951..ef12a7bf7 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -2964,7 +2964,7 @@ }, { "id": "DASH-SEEK-01", - "title": "真实 dash.js 4.5.2 暂停 seek 到缓冲片段边界后可能持续 waiting", + "title": "dash.js 4.5.2 空裁剪漏更新缓冲量,稳定暂停 seek 后调度停滞", "confirmation": "reproduced", "status": "open", "owners": [ @@ -2974,9 +2974,12 @@ "evidence": [ "test/browser/dash-sdk.spec.js", "refactor/baselines/dash-sdk-checkpoint.json", - "refactor/changes/2026-09-12-PKG-DASH-05-sdk-checkpoint.md" + "refactor/changes/2026-09-12-PKG-DASH-05-sdk-checkpoint.md", + "refactor/changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md", + "refactor/baselines/dash-seek-diagnosis.json", + "test/browser/dash-buffer-observer.js" ], - "compatibleResolution": "先比较实际 SDK、SourceBuffer/video 缓冲与暂停 seek 调度;不偏移公开 seek 目标,不吞异常或增加超时伪造通过。", + "compatibleResolution": "已用原生 SDK、SourceBuffer/调度指标和 SDK 5 空裁剪刷新的一行诊断回植确认根因。兼容处置尚未落地;不在核心伪造 timeupdate、不偏移 seek、不强制所有旧用户升级 SDK,也不将诊断补丁计为正式上游通过。", "closureCriteria": "原失败的新旧核心/插件组合有确定根因与对应修复/可验证环境边界;原生对照及原顺序、原目标回归成立,后续偶然通过不能关闭。" } ] diff --git a/refactor/tasks.json b/refactor/tasks.json index d4633c7b8..17d1754f4 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -2070,7 +2070,9 @@ "changes/2026-09-12-PKG-DASH-05-sdk-types.md", "baselines/dash-sdk-types-validation.json", "changes/2026-09-12-PKG-DASH-05-sdk-events.md", - "baselines/dash-sdk-events-validation.json" + "baselines/dash-sdk-events-validation.json", + "changes/2026-09-12-PKG-DASH-05-seek-diagnosis.md", + "baselines/dash-seek-diagnosis.json" ] }, { diff --git a/refactor/third-party.json b/refactor/third-party.json index ceabb0960..d174c1d67 100644 --- a/refactor/third-party.json +++ b/refactor/third-party.json @@ -1054,7 +1054,7 @@ "refactor/scripts/dash-sdk-types.test.mjs" ], "contract": "Caller owns art.dash. Candidate adapts the released 4.x quality method surface and workspace 5.x stable representation ID surface. Controlled contracts and DOM validation pass; actual pinned 4.5.2/5.2.1 SDK media remains PKG-DASH-05.", - "validationStatus": "Pinned npm SDK 4.5.2/5.2.1 main/legacy media, automatic state refresh, same-SDK source replacement, settings selection and formatter recovery exercised. DASH-SEEK-01 and Windows WebKit MSE gap remain. Actual SDK declarations and exact peer closure tested across ten compiler/module configurations, with no added plugin errors and upstream-only Node10/old DOM limitations. Devices and full distribution remain incomplete; see refactor/baselines/dash-sdk-events-validation.json.", + "validationStatus": "Pinned npm SDK 4.5.2/5.2.1 main/legacy media, automatic state refresh, same-SDK source replacement, settings selection and formatter recovery exercised. DASH-SEEK-01 is isolated to SDK 4 stale buffer metrics in its empty-clear branch using native playback and a diagnostic SDK 5 backport; no production mitigation ships and the risk remains open (refactor/baselines/dash-seek-diagnosis.json). Windows WebKit MSE, devices and full distribution remain incomplete. Actual SDK declarations and peer closure retain the ten-configuration matrix and upstream-only Node10/old DOM limits.", "demoPathsSource": "refactor/baselines/demo-inventory.json" }, { diff --git a/test/browser/dash-buffer-observer.js b/test/browser/dash-buffer-observer.js new file mode 100644 index 000000000..ebd9a1cdd --- /dev/null +++ b/test/browser/dash-buffer-observer.js @@ -0,0 +1,50 @@ +// Runs inside the page. Every SDK operation still uses the native SourceBuffer. +export function observeDashBuffers() { + const buffers = [] + const events = [] + const ranges = value => Array.from({ length: value.length }, (_, index) => [value.start(index), value.end(index)]) + function snapshot() { + const video = window.art?.video || window.nativeVideo + const dash = window.art?.dash || window.nativeDash + const metrics = dash?.getDashMetrics() + let processors + try { + processors = dash?.getActiveStream()?.getProcessors().map((processor) => { + const buffer = processor.getBufferController() + return { type: processor.getType(), level: processor.getBufferLevel(), target: processor.getScheduleController().getBufferTarget(), complete: processor.isBufferingCompleted(), pruning: buffer.getIsPruningInProgress(), hasTarget: video ? buffer.hasBufferAtTime(video.currentTime) : null } + }) + } + catch (error) { + // SDK initialization/teardown and generations expose different internals. + processors = { unavailable: String(error) } + } + return { + time: video?.currentTime, + paused: video?.paused, + seeking: video?.seeking, + readyState: video?.readyState, + video: video ? ranges(video.buffered) : [], + levels: metrics ? { video: metrics.getCurrentBufferLevel('video'), audio: metrics.getCurrentBufferLevel('audio') } : null, + processors, + buffers: buffers.map(({ source, buffer, mime }) => { + try { + return { mime, sourceState: source.readyState, updating: buffer.updating, ranges: ranges(buffer.buffered), timestampOffset: buffer.timestampOffset } + } + catch (error) { + return { mime, sourceState: source.readyState, error: error.name } + } + }), + } + } + const mark = name => events.push({ name, at: performance.now(), ...snapshot() }) + for (const Source of new Set([window.MediaSource, window.ManagedMediaSource].filter(Boolean))) { + const addSourceBuffer = Source.prototype.addSourceBuffer + Source.prototype.addSourceBuffer = function (...args) { + const buffer = Reflect.apply(addSourceBuffer, this, args) + buffers.push({ source: this, buffer, mime: args[0] }) + buffer.addEventListener('updateend', () => mark('sourcebuffer:updateend')) + return buffer + } + } + window.dashBuffers = { snapshot, mark, events } +} diff --git a/test/browser/dash-sdk.spec.js b/test/browser/dash-sdk.spec.js index 905925ec8..73cc544f1 100644 --- a/test/browser/dash-sdk.spec.js +++ b/test/browser/dash-sdk.spec.js @@ -3,6 +3,7 @@ import fs from 'node:fs' import process from 'node:process' import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' import { compilePackage } from '../helpers/load.js' +import { observeDashBuffers } from './dash-buffer-observer.js' import { expect, test } from './fixtures.js' const sdks = new Map() @@ -11,6 +12,8 @@ let candidate let published let mediaManifest let pluginRelease +const diagnosticSDK = process.env.ARTPLAYER_DASH_DIAGNOSTIC_SDK || 'none' +assert(['none', 'upstream4', 'bufferlevel4'].includes(diagnosticSDK), 'Unknown diagnostic SDK mode') test.beforeAll(async () => { const baseline = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/dash-sdk.json', import.meta.url))) @@ -18,7 +21,20 @@ test.beforeAll(async () => { const archive = await ensureArchive(sdk.release) const bytes = readMember(archive, sdk.codeMember) assert.equal(hash(bytes), sdk.release.files[sdk.codeMember]) - sdks.set(sdk.release.version, { ...sdk, code: bytes.toString() }) + let code = bytes.toString() + let diagnostic + if (sdk.release.version === '4.5.2' && diagnosticSDK !== 'none') { + const member = 'package/dist/dash.all.debug.js' + code = readMember(archive, member).toString() + const upstreamSHA256 = hash(code) + if (diagnosticSDK === 'bufferlevel4') { + const before = 'function clearBuffers(ranges) {\n return new Promise(function (resolve, reject) {\n if (!ranges || !sourceBufferSink || ranges.length === 0) {\n resolve();' + assert.equal(code.split(before).length, 2, 'Diagnostic patch must match exactly one upstream branch') + code = code.replace(before, before.replace(' resolve();', ' _updateBufferLevel();\n resolve();')) + } + diagnostic = { mode: diagnosticSDK, member, upstreamSHA256, effectiveSHA256: hash(code), acceptance: false } + } + sdks.set(sdk.release.version, { ...sdk, code, diagnostic }) } pluginRelease = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/dash-control-release.json', import.meta.url))).release const bytes = readMember(await ensureArchive(pluginRelease), 'package/dist/artplayer-plugin-dash-control.js') @@ -50,9 +66,21 @@ test.afterEach(async ({ page }, testInfo) => { } const video = art?.video || window.nativeVideo const buffered = video ? Array.from({ length: video.buffered.length }, (_, index) => [video.buffered.start(index), video.buffered.end(index)]) : [] - return { errors: window.sdkErrors, events: window.sdkEvents, mediaEvents: window.mediaEvents, nativePlay: window.nativePlay, tracks, levels, buffered, paused: video?.paused, seeking: video?.seeking, time: video?.currentTime, ready: art?.isReady, width: video?.videoWidth, height: video?.videoHeight, error: video?.error?.code, readyState: video?.readyState, destroyed: window.sdkDestroyed } + return { errors: window.sdkErrors, events: window.sdkEvents, mediaEvents: window.mediaEvents, nativePlay: window.nativePlay, tracks, levels, buffered, paused: video?.paused, seeking: video?.seeking, time: video?.currentTime, ready: art?.isReady, width: video?.videoWidth, height: video?.videoHeight, error: video?.error?.code, readyState: video?.readyState, destroyed: window.sdkDestroyed, bufferState: window.dashBuffers?.snapshot(), bufferEvents: window.dashBuffers?.events } }).catch(error => ({ error: error.message })) await testInfo.attach('dash-sdk-state', { contentType: 'application/json', body: JSON.stringify(state) }) + // Opt-in counterfactual after a failed assertion; it never turns a failure green. + if (process.env.ARTPLAYER_DASH_DIAGNOSE_STALL === '1' && testInfo.status !== testInfo.expectedStatus && state.seeking && state.time === 6) { + const recovery = await page.evaluate(() => { + const before = window.dashBuffers.snapshot() + const video = window.art?.video || window.nativeVideo + video.dispatchEvent(new Event('timeupdate')) + return { before, afterDispatch: window.dashBuffers.snapshot() } + }) + recovery.advanced = await page.waitForFunction(() => (window.art?.video || window.nativeVideo).currentTime > 6.2, null, { timeout: 3000 }).then(() => true, () => false) + recovery.final = await page.evaluate(() => window.dashBuffers.snapshot()) + await testInfo.attach('diagnostic-synthetic-timeupdate', { contentType: 'application/json', body: JSON.stringify(recovery) }) + } if (!page.isClosed()) { await page.evaluate(() => { if (window.art && !window.art.isDestroy) @@ -65,9 +93,10 @@ test.afterEach(async ({ page }, testInfo) => { async function loadSDK(page, version, core, testInfo) { const sdk = sdks.get(version) await page.goto(`/test/player.html?core=${core}`) + await page.evaluate(observeDashBuffers) await page.addScriptTag({ content: sdk.code }) const capability = await page.evaluate(() => ({ sdk: window.dashjs.supportsMediaSource(), mse: typeof window.MediaSource, managed: typeof window.ManagedMediaSource, avc: Boolean(window.MediaSource?.isTypeSupported('video/mp4; codecs="avc1.42c01e"')), aac: Boolean(window.MediaSource?.isTypeSupported('audio/mp4; codecs="mp4a.40.2"')) })) - await testInfo.attach('dash-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: sdk.release, codeMember: sdk.codeMember, pluginRelease, candidateSHA256: hash(candidate), candidate: process.env.ARTPLAYER_DASH_ARTIFACT || 'workspace source build', media: mediaManifest, capability }) }) + await testInfo.attach('dash-sdk-inputs', { contentType: 'application/json', body: JSON.stringify({ sdk: sdk.release, codeMember: sdk.diagnostic?.member || sdk.codeMember, diagnostic: sdk.diagnostic, pluginRelease, candidateSHA256: hash(candidate), candidate: process.env.ARTPLAYER_DASH_ARTIFACT || 'workspace source build', media: mediaManifest, capability }) }) return capability } @@ -98,16 +127,19 @@ async function openDash(page, version, core, plugin, testInfo) { dash.updateSettings({ debug: { logLevel: 0 }, streaming: { abr: { initialBitrate: { video: 150 } }, buffer: { fastSwitchEnabled: true, bufferTimeDefault: 2, bufferTimeAtTopQuality: 2 } } }) const events = window.dashjs.MediaPlayer.events dash.on(events.ERROR, event => window.sdkErrors.push({ code: event.error?.code, message: event.error?.message, event: event.type })) - for (const name of ['STREAM_INITIALIZED', 'QUALITY_CHANGE_REQUESTED', 'QUALITY_CHANGE_RENDERED', 'TRACK_CHANGE_RENDERED', 'STREAM_TEARDOWN_COMPLETE', 'BUFFER_LEVEL_STATE_CHANGED', 'FRAGMENT_LOADING_COMPLETED', 'PLAYBACK_SEEKING', 'PLAYBACK_SEEKED']) { + for (const name of ['STREAM_INITIALIZED', 'QUALITY_CHANGE_REQUESTED', 'QUALITY_CHANGE_RENDERED', 'TRACK_CHANGE_RENDERED', 'STREAM_TEARDOWN_COMPLETE', 'BUFFER_LEVEL_STATE_CHANGED', 'BUFFER_LEVEL_UPDATED', 'FRAGMENT_LOADING_COMPLETED', 'PLAYBACK_SEEKING', 'PLAYBACK_SEEKED']) { if (events[name]) - dash.on(events[name], event => window.sdkEvents.push({ name, at: performance.now(), mediaType: event.mediaType, oldQuality: event.oldQuality, newQuality: event.newQuality, state: event.state, url: event.request?.url, time: video.currentTime })) + dash.on(events[name], event => window.sdkEvents.push({ name, at: performance.now(), mediaType: event.mediaType, oldQuality: event.oldQuality, newQuality: event.newQuality, state: event.state, bufferLevel: event.bufferLevel, url: event.request?.url, time: video.currentTime, seekTime: event.seekTime })) } dash.initialize(video, url, false) } }, }) const art = window.art - for (const name of ['play', 'playing', 'pause', 'seeking', 'seeked', 'waiting', 'emptied', 'loadedmetadata', 'loadeddata', 'canplay', 'error']) { - art.video.addEventListener(name, () => window.mediaEvents.push({ name, at: performance.now(), time: art.video.currentTime, paused: art.video.paused, readyState: art.video.readyState, buffered: Array.from({ length: art.video.buffered.length }, (_, index) => [art.video.buffered.start(index), art.video.buffered.end(index)]) })) + for (const name of ['play', 'playing', 'pause', 'seeking', 'seeked', 'waiting', 'timeupdate', 'emptied', 'loadedmetadata', 'loadeddata', 'canplay', 'error']) { + art.video.addEventListener(name, () => { + window.mediaEvents.push({ name, at: performance.now(), time: art.video.currentTime, paused: art.video.paused, readyState: art.video.readyState, buffered: Array.from({ length: art.video.buffered.length }, (_, index) => [art.video.buffered.start(index), art.video.buffered.end(index)]) }) + window.dashBuffers.mark(`media:${name}`) + }) } art.on('destroy', () => { art.dash.destroy() @@ -164,7 +196,9 @@ for (const core of ['published', 'candidate']) { await page.locator('#pause').click() expect(await page.evaluate(() => window.art.video.paused)).toBe(true) await page.evaluate(() => { + window.dashBuffers.mark('before-seek') window.art.seek = 6 + window.dashBuffers.mark('assigned-seek') }) await page.locator('#play').click() await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(6.2) @@ -192,11 +226,14 @@ for (const version of ['4.5.2', '5.2.1']) { dash.updateSettings({ debug: { logLevel: 0 }, streaming: { abr: { initialBitrate: { video: 150 } }, buffer: { fastSwitchEnabled: true, bufferTimeDefault: 2, bufferTimeAtTopQuality: 2 } } }) const events = window.dashjs.MediaPlayer.events dash.on(events.ERROR, event => window.sdkErrors.push({ code: event.error?.code, message: event.error?.message })) - for (const name of ['FRAGMENT_LOADING_COMPLETED', 'TRACK_CHANGE_RENDERED', 'QUALITY_CHANGE_RENDERED', 'BUFFER_LEVEL_STATE_CHANGED', 'PLAYBACK_SEEKING', 'PLAYBACK_SEEKED']) { - dash.on(events[name], event => window.sdkEvents.push({ name, at: performance.now(), mediaType: event.mediaType, state: event.state, url: event.request?.url, time: video.currentTime })) + for (const name of ['FRAGMENT_LOADING_COMPLETED', 'TRACK_CHANGE_RENDERED', 'QUALITY_CHANGE_RENDERED', 'BUFFER_LEVEL_STATE_CHANGED', 'BUFFER_LEVEL_UPDATED', 'PLAYBACK_SEEKING', 'PLAYBACK_SEEKED']) { + dash.on(events[name], event => window.sdkEvents.push({ name, at: performance.now(), mediaType: event.mediaType, state: event.state, bufferLevel: event.bufferLevel, url: event.request?.url, time: video.currentTime, seekTime: event.seekTime })) } - for (const name of ['play', 'playing', 'pause', 'seeking', 'seeked', 'waiting']) { - video.addEventListener(name, () => window.mediaEvents.push({ name, at: performance.now(), time: video.currentTime, paused: video.paused, readyState: video.readyState, buffered: Array.from({ length: video.buffered.length }, (_, index) => [video.buffered.start(index), video.buffered.end(index)]) })) + for (const name of ['play', 'playing', 'pause', 'seeking', 'seeked', 'waiting', 'timeupdate']) { + video.addEventListener(name, () => { + window.mediaEvents.push({ name, at: performance.now(), time: video.currentTime, paused: video.paused, readyState: video.readyState, buffered: Array.from({ length: video.buffered.length }, (_, index) => [video.buffered.start(index), video.buffered.end(index)]) }) + window.dashBuffers.mark(`media:${name}`) + }) } dash.initialize(video, '/dash-fixture/master.mpd', false) document.querySelector('#play').onclick = () => { @@ -222,16 +259,27 @@ for (const version of ['4.5.2', '5.2.1']) { }) await expect.poll(() => page.evaluate(() => window.nativeVideo.videoHeight)).toBe(180) // Match the failed integrated run: video data ends at the next seek target. - await expect.poll(() => page.evaluate(() => window.nativeVideo.buffered.end(window.nativeVideo.buffered.length - 1))).toBeCloseTo(6, 4) + await expect.poll(() => page.evaluate(() => { + const video = window.nativeVideo + return video.currentTime >= 2.8 && Math.abs(video.buffered.end(video.buffered.length - 1) - 6) < 0.0001 + })).toBe(true) await page.evaluate(() => { const dash = window.nativeDash dash.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: true } } } }) dash.setCurrentTrack(dash.getTracksFor('audio').find(track => track.lang === 'fr')) }) await expect.poll(() => page.evaluate(() => window.nativeDash.getCurrentTrackFor('audio').lang)).toBe('fr') + // The recorded integrated stall happened after the audio switch was rendered. + await expect.poll(() => page.evaluate(() => window.sdkEvents.some(event => event.name === 'TRACK_CHANGE_RENDERED' && event.mediaType === 'audio'))).toBe(true) await page.locator('#pause').click() + // Observe a genuinely held pause: no clock/append events for half a second. + // This separates the seek from progress events still queued by the track switch. + await page.waitForFunction(() => window.nativeVideo.paused && performance.now() - window.dashBuffers.events.at(-1).at >= 500) + expect(await page.evaluate(() => window.nativeVideo.paused)).toBe(true) await page.evaluate(() => { + window.dashBuffers.mark('before-seek') window.nativeVideo.currentTime = 6 + window.dashBuffers.mark('assigned-seek') }) await page.locator('#play').click() await expect.poll(() => page.evaluate(() => window.nativeVideo.currentTime)).toBeGreaterThan(6.2)