refactor(ambilight): [PKG-AMBILIGHT-03] split typed lifecycle and recover native canvas sampling

This commit is contained in:
Harvey Zhao committed 2026-09-12 11:35:13 +08:00
1 parent 43f0e9a8c6
commit 6caee44dbf
25 files changed
+1680 -306

No files matched your search

+23 -1
View File
@@ -14,7 +14,7 @@ stop保留最后画面,核心destroy终止资源。zIndex仍忽略,参数省
## 02历史回归
`yarn test:ambilight`运行30项Node回归并接入test:unit;正常参数/频率/暂停与已确认的
`node --test test/ambilight.test.js`运行30项Node回归并接入test:unit;正常参数/频率/暂停与已确认的
历史问题分别断言。`yarn test:browser test/browser/ambilight.spec.js`运行三实现/三核心/
三引擎真实媒体;核心标签published是实际npm5.4.0,published-5.1.7是实际npm5.1.7,
candidate是当前源码;以browser-evidence的manifest和实际version为准。
@@ -24,3 +24,25 @@ candidate是当前源码;以browser-evidence的manifest和实际version为准
02最终30项Node、54项三引擎/三核心浏览器通过,未skip;新建Canvas能读取已恢复的
同源视频,而旧插件Canvas仍抛SecurityError。主CI955项通过(另44项重复观察)。
完整报告与输入来源见baselines/ambilight-behavior-validation.json。03开始修复这些问题。
## 03候选生命周期
`yarn test:ambilight`现在执行30项历史及16项候选测试。候选直接构建当前src入口,
不读取旧dist作回退。设置ARTPLAYER_AMBILIGHT_BASELINE=1可把同一16项要求交给冻结
工作区:14项失败、2项正常语义对照通过;候选16项通过。环境变量只应用于独立负向
命令,正常CI不得设置。另7项发布契约继续通过,专项共53项。
`yarn test:browser test/browser/ambilight-lifecycle.spec.js`在实际npm核心5.1.7/5.4.0和
候选核心、Chromium/Firefox/WebKit中执行18项,无skip。原生视频/Canvas不模拟;
词法RAF观察器只跟踪插件自己的帧,调用仍交给原生RAF,核心和测试等待帧不计入。
验证ready自动取色、stop保色、destroy(false)移除DOM/清空帧、逃逸方法不复活,及真实
跨origin失败后切回同源在同一插件/视图内恢复,不调用stop/start来协助恢复。
首次宽度重置方案15/18通过,Firefox全部3项恢复失败。独立诊断证明新Canvas能读取
已恢复视频,原Canvas重设宽度仍抛SecurityError,随后改为下次有效取色创建新Canvas。
保留失败与通过报告;最终18/18通过。持续跨域素材仍不可取色,失败期间的分配成本
需在性能复盘评估。正式构建更新三种分发及docs/compiled,未手改生成内容。
03证据见 [生命周期验证](baselines/ambilight-lifecycle-validation.json) 和
[实施记录](changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md)。04公开声明及CJS.default、
05代理/实际设备、06安装包和8082 demo仍未完成;三浏览器通过不能代替这些验收。
@@ -0,0 +1,196 @@
{
"schemaVersion": 1,
"task": "PKG-AMBILIGHT-03",
"status": "done",
"parentCommit": "43f0e9a8c66402e628f358602220aaa854b100e2",
"checks": [
{
"command": "node --test test/ambilight-lifecycle.test.js test/ambilight.test.js refactor/scripts/ambilight-contract.test.mjs",
"result": "pass",
"tests": 53,
"candidate": 16,
"historical": 30,
"publishedContract": 7
},
{
"command": "ARTPLAYER_AMBILIGHT_BASELINE=1 node --test test/ambilight-lifecycle.test.js",
"result": "expected-negative-control",
"tests": 16,
"failed": 14,
"passedNormalSemantics": 2,
"source": "immutable frozen-workspace from ambilight-release.json"
},
{
"command": "playwright test test/browser/ambilight-lifecycle.spec.js",
"result": "pass",
"tests": 18,
"skipped": 0,
"stats": {
"startTime": "2026-09-12T03:28:59.484Z",
"duration": 28092.341,
"expected": 18,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"versions": [
"chromium: 153.0.8010.12",
"firefox: 155.0",
"webkit: 26.6"
],
"coreSources": [
"npm 5.1.7",
"npm 5.4.0",
"candidate source"
],
"report": "refactor/.cache/ambilight03-final-results/report.json",
"archivedResults": "refactor/.cache/ambilight03-final-results/results",
"originalResultsPrefix": "refactor/.cache/browser/results"
},
{
"command": "yarn build artplayer-plugin-ambilight",
"result": "pass",
"outputs": [
"main es2020",
"legacy es2015",
"esm es2020",
"docs/compiled copies"
]
},
{
"command": "focused eslint --no-fix and tsc -p packages/artplayer-plugin-ambilight/tsconfig.json",
"result": "pass"
},
{
"command": "yarn ci:check",
"result": "pass",
"tests": {
"unit": 878,
"engineering": 14,
"baseline": 79,
"mainTotal": 971,
"repeatedContractExecutions": 44
}
}
],
"failedIterations": [
{
"report": "refactor/.cache/ambilight03-first-results/report.json",
"archivedResults": "refactor/.cache/ambilight03-first-results/results",
"pass": 15,
"fail": 3,
"reason": "Firefox retained canvas taint after width reset in all three core combinations"
},
{
"report": "refactor/.cache/ambilight03-firefox-probe-results/report.json",
"archivedResults": "refactor/.cache/ambilight03-firefox-probe-results/results",
"pass": 0,
"fail": 1,
"reason": "Fresh native canvas read recovered video but reset old canvas still threw SecurityError; native-canvas-reset-control attachment records it"
}
],
"inputs": [
{
"file": "packages/artplayer-plugin-ambilight/src/index.ts",
"sha256LF": "e5df94a5a541530533ccbf91f4365fcaa9965d6727fee0c67cef50dc967e22cb"
},
{
"file": "packages/artplayer-plugin-ambilight/src/sampler.ts",
"sha256LF": "b6a2ac951ddd162099d39aadaaca3b9fafe7929c5c12a857934d4b9c884edf5e"
},
{
"file": "packages/artplayer-plugin-ambilight/src/scheduler.ts",
"sha256LF": "2c87328cfa8d916c64e8eed26802116867f9d731991a6cddf871d53808261268"
},
{
"file": "packages/artplayer-plugin-ambilight/src/view.ts",
"sha256LF": "e30ec83e0a8f1b471c4f04cc436d550b3fed3f75d8042ddfd73be98705103e8b"
},
{
"file": "packages/artplayer-plugin-ambilight/tsconfig.json",
"sha256LF": "712a3fa32ed57692d16bf854a0e77ffaecd04236efa0f557905aab7291e0aef6"
},
{
"file": "packages/artplayer-plugin-ambilight/types/artplayer-plugin-ambilight.d.ts",
"sha256LF": "a36998b4d96d9a3200022029bf92918cc516d5ae4f38dc78a1a76b53a736d086"
},
{
"file": "packages/artplayer-plugin-ambilight/dist/artplayer-plugin-ambilight.js",
"sha256LF": "56735a767696fe2cbe11b04db9a8af32fc814be58a5664395a8888bb31c7e046"
},
{
"file": "packages/artplayer-plugin-ambilight/dist/artplayer-plugin-ambilight.legacy.js",
"sha256LF": "51ed35cffc43ac1748556210af1cee1a5e0b867e48e269e4c477bc45962203b6"
},
{
"file": "packages/artplayer-plugin-ambilight/dist/artplayer-plugin-ambilight.mjs",
"sha256LF": "7c6b35fa873d4498fabf8ef7097e56664ab7ecd6a2d0efb884b4de0a3055f99d"
},
{
"file": "test/helpers/ambilight.js",
"sha256LF": "8cb80dba5270860afc121e3a02336a6cdb20b0a6a41e058cde11efe9174fba4f"
},
{
"file": "test/ambilight-lifecycle.test.js",
"sha256LF": "cc4a7a4068709f1c9f5be49ea4d51784f3ccfd22ca6f99bb15314b5032ff8395"
},
{
"file": "test/browser/ambilight-lifecycle.spec.js",
"sha256LF": "321693a24d33f0c7aee02fd4137b55175386562a645ba138e15c3a51d6348d2c"
},
{
"file": "test/browser/server.mjs",
"sha256LF": "af513e1e64f875668b6a7cbd060276d85d930e0cc1715577e97907cc26c3b58d"
},
{
"file": "refactor/baselines/ambilight-release.json",
"sha256LF": "6acbea40a26397ffa36549fbecb1a12c057cfb3fc932f7cb83181ad5fa37bd2f"
},
{
"file": "package.json",
"sha256LF": "415ee02f3c38691475c619b1f874c68ee0484630f805f9d835981d421fbbda84"
}
],
"logs": [
{
"file": "refactor/.cache/ambilight03-targeted-final.log",
"sha256": "5524ffd95993fd31600b6f51ae4ae8297fd8a92b5b01670386b9c7a61b0700bb"
},
{
"file": "refactor/.cache/ambilight03-baseline-negative.log",
"sha256": "20d82258de1bababe503ada70b95b8295126502f9d9fc26deaa8d8a25ccd3ec8"
},
{
"file": "refactor/.cache/ambilight03-browser.log",
"sha256": "9f230d7cc02d6b038f26e7bd64968580b876b4146697c5ecf9d1511958dfb79f"
},
{
"file": "refactor/.cache/ambilight03-firefox-probe.log",
"sha256": "8f90b54c0be91571f0070608f7b0f0b1ff02ff4c8ac3c973aaf1a1451ddee6ed"
},
{
"file": "refactor/.cache/ambilight03-browser-fixed.log",
"sha256": "9cdb32d658b245fb8efea98b638f1afb0966bfde8b018cdba016b67e49665d2b"
},
{
"file": "refactor/.cache/ambilight03-build.log",
"sha256": "a642ae2431cb33e10aa98f6520853f4c51077e5d2fe05659e8297100a81a0c8f"
},
{
"file": "refactor/.cache/ambilight03-lint-final.log",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
{
"file": "refactor/.cache/ambilight03-ci.log",
"sha256": "e5dbb40a578179624b5b394887d23f0164db4fd47c938e07de93070d16c044d7"
}
],
"limitations": [
"Public declarations and historical CJS.default compatibility remain task 04; no API approval inferred from Ads.",
"Proxy and real device combinations remain task 05; package installation and local 8082 demo remain task 06.",
"Browser tests consume a direct candidate source bundle; production artifacts are built but not yet packed-consumer validated.",
"A permanently unreadable cross-origin source retries with at most one new canvas per eligible sample; performance review remains required.",
"VAST alone has user-authorized persistent VPN external-script exception. No skip or exception was used here.",
"Full CI retains the known generated docs lint warning and Yarn url.parse deprecation; remote workflows have not run."
]
}
@@ -0,0 +1,44 @@
# PKG-AMBILIGHT-03 TS职责拆分与生命周期修复
## 结构变化
原单文件JS拆为严格TS入口、视图、取色和RAF调度四个模块;新增包tsconfig并纳入现有
自动发现的严格类型检查。入口负责订阅和终止,视图只维护9格样式,取色一次收集9色,
调度使用运行/停止/销毁状态和代次,避免重入和过期帧重复挂载。包ARCHITECTURE.md说明
所有权、失败处理、兼容约束和后续AI应运行的检查;公开声明留给04单独验收。
## 缺陷修复
RAF id为0也能停止;destroy移除视图/订阅、释放Canvas,逃逸start不能复活;初始化
失败回滚,部分订阅/上下文错误保留原异常;销毁中某一步抛错仍继续其他清理。
取色中stop/destroy立刻放弃旧批次,stop/start留到新帧;空context与无效尺寸跳过。
绘制/读像素失败不再卡死调度,下一次有效取色重新创建Canvas,同源切源后恢复。
首轮真实浏览器18项中15通过,Firefox三核心恢复断言失败。补充独立新Canvas对照后,
确认同源视频可读,但旧原生Canvas改宽度仍抛SecurityError;据此将仅重置宽度改为
丢弃出错Canvas并在下次满足频率/播放/尺寸条件时替换。初次失败和诊断报告均归档,
没有扩大超时或skip来绕过问题。永久跨域时最多每个有效采样分配一次替代Canvas;
默认10Hz,高频选项仍按历史算式执行,该成本留给后续性能复盘。
## 兼容与范围
保留factory/options读取时机、start/stop同步返回、ready启动、暂停不采样、stop保留
颜色、3x3位置/默认样式、ignored zIndex和特殊frequency语义。destroy终止与错误恢复
是已复现缺陷修正;没有增加公共方法、修改声明或宣称npm分发和设备全部验收。
真实npm1.0.0/1.1.0与冻结工作区历史测试不改写;核心版本以实际归档5.1.7/5.4.0为准。
## 验证与提交
16项候选回归在冻结工作区上14项失败、2项正常语义通过;修复后与30项历史及7项发布
契约合计53项通过。最终三引擎/三核心18项浏览器全部通过,无skip。严格类型、专项
lint及三格式正式构建通过;完整CI971项通过(878单元+14工程+79基线),另44项契约
报告重复执行不作新增计数;全仓278个生产TS文件纳入严格检查。已知生成文档lint
warning和Yarn弃用提示保留。结果与输入哈希见
[验证证据](../baselines/ambilight-lifecycle-validation.json)。
03完成并独立本地commit,随后审计自身完成提交;无推送或发布。04公开类型/旧
CJS.default、05代理和设备、06分发/demo仍待实施。AMBILIGHT-LIFE-01保留open以追踪
05代理组合的终止/能力边界,不能把本步原生video验收扩展到所有proxy。
用户更正已核对:VPN外部脚本加载例外只适用于VAST,不适用于Ads。本次Ambilight验证
使用本地媒体,不涉及该例外。VAST初始化兼容选择仍是独立待决项。
+3 -2
View File
@@ -4,7 +4,7 @@
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 220 项,范围 22 个包及工作区/示例。
状态:todo 128 / doing 6 / blocked 0 / done 86 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 127 / doing 6 / blocked 0 / done 87 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -150,7 +150,7 @@
| --- | --- | --- | --- | --- | --- | --- |
| PKG-AMBILIGHT-01 | artplayer-plugin-ambilight<br>核对包契约与历史用法 | BASE-05 | blur/opacity/frequency/duration、start/stop 与挂载样式 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | M | done |
| PKG-AMBILIGHT-02 | artplayer-plugin-ambilight<br>建立特有行为与错误测试 | PKG-AMBILIGHT-01, ENG-03, ENG-05 | 跨域 canvas 失败、零尺寸、暂停、重复 start/stop 和 destroy | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | M | done |
| PKG-AMBILIGHT-03 | artplayer-plugin-ambilight<br>整理内部职责与资源 | PKG-AMBILIGHT-02, CORE-03, CORE-12 | 取色计算与绘帧分离,统一 RAF 和 DOM 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | todo |
| PKG-AMBILIGHT-03 | artplayer-plugin-ambilight<br>整理内部职责与资源 | PKG-AMBILIGHT-02, CORE-03, CORE-12 | 取色计算与绘帧分离,统一 RAF 和 DOM 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | done |
| PKG-AMBILIGHT-04 | artplayer-plugin-ambilight<br>迁移自有源码和公开类型 | PKG-AMBILIGHT-03, ENG-04, ENG-06, CORE-07 | canvas 上下文、参数及 start/stop 的明确类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | M | todo |
| PKG-AMBILIGHT-05 | artplayer-plugin-ambilight<br>验证新旧核心和组合 | PKG-AMBILIGHT-04, CORE-22 | 原生 video、canvas proxy 的能力边界及销毁无帧循环 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
| PKG-AMBILIGHT-06 | artplayer-plugin-ambilight<br>验证分发并同步文档 | PKG-AMBILIGHT-05, ENG-07 | ambilight.js 示例及样式/分发验证 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | M | todo |
@@ -478,6 +478,7 @@
- PKG-CHAPTER-05: [记录](changes/2026-09-12-PKG-CHAPTER-05-combinations.md) [记录](baselines/chapter-combinations-checkpoint.json)
- PKG-AMBILIGHT-01: [记录](changes/2026-09-12-PKG-AMBILIGHT-01-contract.md) [记录](baselines/ambilight-contract.md) [记录](baselines/ambilight-release.json) [记录](baselines/ambilight-contract-validation.json)
- PKG-AMBILIGHT-02: [记录](changes/2026-09-12-PKG-AMBILIGHT-02-tests.md) [记录](baselines/ambilight-behavior-validation.json) [记录](ambilight-validation.md)
- PKG-AMBILIGHT-03: [记录](changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md) [记录](ambilight-validation.md) [记录](baselines/ambilight-lifecycle-validation.json)
- PKG-AUDIO-01: [记录](changes/2026-09-12-PKG-AUDIO-01-contract.md) [记录](baselines/audio-track-contract.md) [记录](baselines/audio-track-release.json)
- PKG-AUDIO-02: [记录](changes/2026-09-12-PKG-AUDIO-02-tests.md) [记录](audio-validation.md) [记录](baselines/audio-validation.json)
- PKG-AUDIO-03: [记录](changes/2026-09-12-PKG-AUDIO-03-lifecycle.md) [记录](baselines/audio-lifecycle-validation.json)
+11
View File
@@ -1,5 +1,16 @@
# 进度与证据
## 最新完成:Ambilight-03 TS模块与生命周期修复
生产源码已拆成入口、视图、取色、帧调度4个严格TS模块,修复销毁残留、重入旧帧、
初始化回滚和Canvas异常卡死。16项候选要求在旧源码14失败/2正常通过,候选与历史
及发布契约共53项通过。首次真实浏览器发现Firefox宽度重置仍污染,加入独立对照后
修复为下次有效取色替换Canvas,最终三核心/三引擎18项通过、无skip。正式三格式构建
及完整CI971项通过,另44项重复观察;全仓278个生产TS文件严格检查。当前220项:
87 done、6 doing、127 todo。04公开类型/历史CJS.default、05代理/设备、06包消费/demo
未完成。见 [实施记录](changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md) 和
[验证证据](baselines/ambilight-lifecycle-validation.json)。本任务独立本地提交,无推送/发布。
## 最新完成:Ambilight-02 行为与失败回归
30项Node复现RAF id零、异常后卡住、销毁/重入/晚注册和初始化回滚问题。54项三引擎/
+4 -2
View File
@@ -3270,9 +3270,11 @@
"refactor/changes/2026-09-12-PKG-AMBILIGHT-01-contract.md",
"refactor/changes/2026-09-12-PKG-AMBILIGHT-02-tests.md",
"refactor/baselines/ambilight-behavior-validation.json",
"refactor/ambilight-validation.md"
"refactor/ambilight-validation.md",
"refactor/changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md",
"refactor/baselines/ambilight-lifecycle-validation.json"
],
"workspaceState": "30 Node historical tests reproduce RAF id zero, terminal/escaped method, sampling/context, reentrant stop/destroy and setup rollback failures. Native browser sampling of a cross-origin video throws SecurityError and stays tainted after same-origin source recovery. No production fixes in this task."
"workspaceState": "Candidate source split into four strict TS modules. RAF zero, terminal cleanup, rollback and reentrant frames repaired; 16 candidate tests pass (14 fail against frozen source). Eighteen native video/canvas tests pass across three cores and three engines after reproducing Firefox width-reset taint and replacing failed canvas. Risk remains open for proxy lifecycle/capability checks in PKG-AMBILIGHT-05; do not extend native video evidence to proxies."
},
{
"id": "AMBILIGHT-TYPE-01",
+6 -2
View File
@@ -1503,11 +1503,15 @@
"CORE-03",
"CORE-12"
],
"status": "todo",
"status": "done",
"risk": "M",
"deliverable": "取色计算与绘帧分离,统一 RAF 和 DOM 清理",
"acceptance": "结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过",
"evidence": []
"evidence": [
"changes/2026-09-12-PKG-AMBILIGHT-03-lifecycle.md",
"ambilight-validation.md",
"baselines/ambilight-lifecycle-validation.json"
]
},
{
"id": "PKG-AMBILIGHT-04",