refactor(auto-thumbnail): [PKG-AUTO-THUMB-10] own JPEG encoding cancellation and deadlines

This commit is contained in:
Harvey Zhao committed 2026-09-14 11:55:05 +08:00
1 parent afb632d16f
commit 4acf85ea69
21 files changed
+652 -35

No files matched your search

@@ -0,0 +1,172 @@
{
"task": "PKG-AUTO-THUMB-10",
"date": "2026-09-14",
"baselineCommit": "afb632d16fec59aaa871d7efb116e2817b81032f",
"node": "v24.21.0",
"yarn": "1.22.22",
"platform": "win32",
"before": {
"artifact": {
"path": "refactor/.cache/auto-thumbnail-encoding-before.js",
"sha256": "67dbd91228888e1a19d055b1cf2f6514f51fa63c2dfc36aa485c220631383f98"
},
"log": {
"path": "refactor/.cache/auto-encoding-before.log",
"sha256": "40d6d9aa4e960ce0a53a573679a684257663ab6b302229bc4d43ff59fc66279e"
},
"passed": 0,
"failed": 6,
"interpretation": "Controlled callback withholding; missing encoding deadline, not spontaneous native encoder failure",
"finalTests": {
"path": "refactor/.cache/auto-encoding-before-final-tests.log",
"sha256": "86e73e5c30fde4bab7636629e6cb6d669834c313de8da23699030d717523f2d3",
"exitCode": 1,
"passed": 1,
"failed": 8
}
},
"policy": {
"encodingDeadlineMs": 30000,
"starts": "Immediately before canvas.toBlob",
"timeout": "Dispose job and warn; retain previous preview; ignore late Blob",
"underlyingEncoderCancellation": false,
"initialMetadataDeadline": false
},
"sources": [
{
"path": "packages/artplayer-plugin-auto-thumbnail/src/encoding.ts",
"sha256": "5fc75397162c86f5906c19c94c9aba873c45ec8a370bc4489570ca653ff73300"
},
{
"path": "packages/artplayer-plugin-auto-thumbnail/src/extraction.ts",
"sha256": "9d6867fda068f60f3dde51db67cc86486da1fc0cfc0d17cb166dd417c7b55567"
}
],
"tests": [
{
"path": "test/auto-thumbnail-encoding.test.js",
"sha256": "f47c7dca135253c125b6fe569b0252db019c6ad1059571152c9a7929735299f3"
},
{
"path": "test/auto-thumbnail-frames.test.js",
"sha256": "0b635d194a76a2934181e806e35f1e9086cdda906738f4149e3ebecda6d7c3f5"
},
{
"path": "test/browser/auto-thumbnail-lifecycle.spec.js",
"sha256": "125bd6fafe3c4ff5dc9c4799755d6557c51918689fcb37d6945c2e53ba298df8"
}
],
"results": [
{
"path": "refactor/.cache/auto-encoding-final-tests.log",
"sha256": "5eea1838306cff9404cda7522ad4642de19d8a22315770f8068f559161e78c6d",
"passed": 174,
"failed": 0,
"skipped": 0
},
{
"path": "refactor/.cache/auto-encoding-artifact.log",
"sha256": "ef295aec9ba6612ab81b54c731e3928290fbe51bcaf8224a9a2289003c78ccf5",
"passed": 11,
"failed": 0,
"skipped": 0
},
{
"path": "refactor/.cache/auto-encoding-ci.log",
"sha256": "220c84faf14a65929d194a54a4990dddae0c947e1b7f568d71435f8eb8f6aa86",
"passed": 50,
"failed": 0,
"skipped": 0
}
],
"browsers": [
{
"path": "refactor/.cache/auto-encoding-browser/report.json",
"sha256": "a7cca4a03097db41aaa45e0728c7e76d0d9abe70f8dbe9fed562b74b90d51aef",
"stats": {
"startTime": "2026-09-14T03:48:18.577Z",
"duration": 31836.841,
"expected": 27,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"scope": "21 lifecycle and6 pixel cases; callback-less first-frame limitation retained"
},
{
"path": "refactor/.cache/auto-encoding-artifact-browser/report.json",
"sha256": "bc09dfaedcb4f47b97c45a905e9ba4db69512d9249c5394068374eb529d61306",
"stats": {
"startTime": "2026-09-14T03:51:07.923Z",
"duration": 12860.902999999998,
"expected": 9,
"skipped": 0,
"unexpected": 0,
"flaky": 0
},
"scope": "Actual built UMD: complete, default-alias complete and controlled encoding-timeout in all3 engines"
}
],
"artifacts": [
{
"path": "packages/artplayer-plugin-auto-thumbnail/dist/artplayer-plugin-auto-thumbnail.js",
"sha256": "a9a1704f39ebd2ef6612cc146acf4ebd0d8eeb73764cb852320a85d31438ab01",
"docs": {
"path": "docs/compiled/artplayer-plugin-auto-thumbnail.js",
"sha256": "a9a1704f39ebd2ef6612cc146acf4ebd0d8eeb73764cb852320a85d31438ab01"
}
},
{
"path": "packages/artplayer-plugin-auto-thumbnail/dist/artplayer-plugin-auto-thumbnail.legacy.js",
"sha256": "452b1c0d4d6658fa96b4bff57ad0f40fa60ad309caaca1fd81d0a75aadb89325",
"docs": {
"path": "docs/compiled/artplayer-plugin-auto-thumbnail.legacy.js",
"sha256": "452b1c0d4d6658fa96b4bff57ad0f40fa60ad309caaca1fd81d0a75aadb89325"
}
},
{
"path": "packages/artplayer-plugin-auto-thumbnail/dist/artplayer-plugin-auto-thumbnail.mjs",
"sha256": "5e5020abcbee5a5a260ea657ec123bfe50bb8d926f0131431b42c21f8bec5d43",
"docs": {
"path": "docs/compiled/artplayer-plugin-auto-thumbnail.mjs",
"sha256": "5e5020abcbee5a5a260ea657ec123bfe50bb8d926f0131431b42c21f8bec5d43"
}
}
],
"checks": [
{
"path": "refactor/.cache/auto-encoding-types.log",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"exitCode": 0
},
{
"path": "refactor/.cache/auto-encoding-lint-final.log",
"sha256": "b66f33ce5b38fbf22d5b05efd1cdb9b47e5278aca38ad0e37aff64e5fbd0d6b8",
"exitCode": 0
},
{
"path": "refactor/.cache/auto-encoding-build.log",
"sha256": "c66ec03fdd0ca2c75912b6f6a1be3a65dba27b023e1d69197849519d2e28e716",
"exitCode": 0
},
{
"path": "refactor/.cache/auto-encoding-final.log",
"sha256": "56acd0fdc584d70e39cdc84da9e7a27d2be06fb3b8296775e275e2d42a294b23",
"exitCode": 0
}
],
"initialLintFailure": {
"path": "refactor/.cache/auto-encoding-lint.log",
"sha256": "93b74fb75b81ade20affb57e9de7ad99183a7f699e8dc58604f34dcdb6ec42ca"
},
"limits": [
"Native browser timeout case deliberately withholds an actual JPEG callback and invokes the captured timer; no measured30s stall claim",
"AUTO-THUMB-PIXEL-01 and task03 remain open",
"Windows local evidence, not remote CI or physical devices",
"No new dependency, public declaration or version change; no publication"
],
"initialRiskValidationFailure": {
"path": "refactor/.cache/auto-encoding-risk-initial.log",
"sha256": "8af6f39925880a154278e1688fcde0883bd8ef17c9bb78b8414cc2780721ee14"
}
}
@@ -0,0 +1,88 @@
# PKG-AUTO-THUMB-10: bounded JPEG encoding ownership
Baseline: afb632d16fec59aaa871d7efb116e2817b81032f. Split this resource task from
unfinished task03 so that its delivery does not imply the native first-frame
problem is fixed. Task04 depends on this task as well as task03 and the separate
type/alias tasks.
## Previous behavior and intentional policy change
Frame readiness had a30-second deadline, cleared before canvas encoding began.
If the toBlob callback never arrived, no deadline remained and the current job
kept its decoder/canvas until restart, another metadata load or destruction.
The source boundary is verified; withholding callbacks in the controlled harness
reproduces that ownership state. This is not evidence that a real browser encoder
spontaneously hangs. Six initial tests fail against a bundle frozen before this
change because encoding has no registered timeout.
The new encoding wait has its own30-second deadline, starting immediately before
toBlob and independent of the frame wait. Timeout disposes the job and reports
through the existing warning path, preserving the last usable preview. A very
slow encoding that formerly completed after30 seconds may now be discarded.
This is an explicit bounded-resource policy change for the private async job,
not an unchanged-behavior claim or a new public API. Initial metadata/network
acquisition, total extraction duration and browser background scheduling remain
outside this per-encode limit.
## Implementation and compatibility
`src/encoding.ts` owns a single pending operation token, timer and Blob callback.
Its once-per-job cleanup avoids accumulating one closure per frame. Completion
invalidates the token and clears its timer before publication or the next seek.
Late/duplicate callbacks cannot affect a newer operation. Timer registration that
reenters destruction releases the newly returned handle and never starts encoding.
Synchronous native callback delivery is handled without retaining a timer. Timer
cleanup failure still reaches job-owned video and canvas cleanup.
`extraction.ts` now coordinates frame read, draw, encoding, publish and next sample;
it delegates callback identity and timeout ownership to the encoder. Existing
`session.ts` retains URL replacement/cleanup and error reporting. The browser's
underlying toBlob work is not cancellable: disposal zeros the private canvas and
releases the decoder, while late encoded bytes cannot publish. GPU/encoder memory
reclamation timing is not claimed.
Normal JPEG MIME, serial progressive publication, ten-column layout, options,
sample-time formula, factory/default alias, registration Promise and public type
entrypoints remain unchanged. Null Blob and synchronous encoding errors follow the
existing job failure path. No dependency or lockfile change; the new regression
file joins existing test:auto-thumbnail/test:unit scripts. The actual module map
and maintenance boundaries are updated in the package ARCHITECTURE.md.
## Validation
Full evidence and file fingerprints:
[auto-thumbnail-encoding-validation.json](../baselines/auto-thumbnail-encoding-validation.json).
- Frozen pre-change bundle: initial6 new tests fail on missing encoding deadline.
The final9-case file is also rerun unchanged against that frozen bundle:8 fail
and the synchronous-completion control passes; all9 pass on the candidate.
- Current package suite:174 pass, including9 encoding cases, historical
contracts/failures, lifecycle/frame/canvas/exports and public-type regressions.
- Strict package TypeScript passes. Lint's initial new-test single-line if error
is fixed; final lint retains only the existing generated docs type warning.
- Real package build regenerates UMD/legacy/ESM and docs copies. New encoding and
existing export checks also run against the actual produced main artifact:
11 Node checks and9 three-browser complete/alias/timeout cases pass.
- Windows browser suite:27 pass.21 lifecycle cases cover completion, alias,
cancellation, frame cancellation and new encoding timeout;6 pixel cases retain
their existing explicit callback-less first-frame limitation. They do not close
AUTO-THUMB-PIXEL-01. The new timeout case performs native HTTP decode/seek/JPEG,
deliberately holds its Blob callback and invokes the captured30-second timer.
It proves real resource cleanup and ignored late delivery, not a measured native
timeout. Natural complete cases still decode the resulting JPEG after cleanup.
-50 CI regressions plus final plan/risk validation; remote workflows and physical
device acceptance are not claimed. Entire unrelated package suites are not
repeated for this isolated encoder change.
Adding this new task as an unfinished dependency to already-doing task03 initially
failed the plan validator. It is instead attached to future task04, preserving
the plan's startup rule without changing any existing acceptance requirement.
## Delivery and remaining work
Complete and commit only task10 with its code, generated artifacts, tests, docs
and status. Task03 remains doing; native first-frame readiness, aggregate
resource limits and later package combinations/distribution acceptance remain
open. This change completes the bounded encoding responsibility only. Revert this
dedicated commit, including regenerated outputs, to restore the previous unbounded
encoding behavior. Local commit only; no push, version change or publication.
+6 -4
View File
@@ -2,9 +2,9 @@
> 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 245 项,范围 22 个包及工作区/示例。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 246 项,范围 22 个包及工作区/示例。
状态:todo 56 / doing 16 / blocked 0 / done 173 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 56 / doing 16 / blocked 0 / done 174 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -19,7 +19,7 @@
| artplayer-plugin-ambilight | 1.1.0 | PKG-AMBILIGHT-01, PKG-AMBILIGHT-02, PKG-AMBILIGHT-03, PKG-AMBILIGHT-04, PKG-AMBILIGHT-PROXY-01, PKG-AMBILIGHT-05, PKG-AMBILIGHT-06, PKG-FACTORY-01 |
| artplayer-plugin-asr | 2.1.0 | PKG-ASR-01, PKG-ASR-02, PKG-ASR-03, PKG-ASR-04, PKG-ASR-05, PKG-ASR-06, PKG-ASR-07, PKG-ASR-08, PKG-ASR-09 |
| artplayer-plugin-audio-track | 1.1.0 | PKG-AUDIO-01, PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-04, PKG-AUDIO-05, PKG-AUDIO-06 |
| artplayer-plugin-auto-thumbnail | 1.1.0 | PKG-AUTO-THUMB-01, PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-03, PKG-AUTO-THUMB-04, PKG-AUTO-THUMB-05, PKG-AUTO-THUMB-06, PKG-AUTO-THUMB-07, PKG-AUTO-THUMB-08, PKG-AUTO-THUMB-09 |
| artplayer-plugin-auto-thumbnail | 1.1.0 | PKG-AUTO-THUMB-01, PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-03, PKG-AUTO-THUMB-04, PKG-AUTO-THUMB-05, PKG-AUTO-THUMB-06, PKG-AUTO-THUMB-07, PKG-AUTO-THUMB-08, PKG-AUTO-THUMB-09, PKG-AUTO-THUMB-10 |
| artplayer-plugin-chapter | 1.1.0 | PILOT-01, PKG-CHAPTER-01, PKG-CHAPTER-02, PKG-CHAPTER-03, PKG-CHAPTER-04, PKG-CHAPTER-05, PKG-CHAPTER-06 |
| artplayer-plugin-chromecast | 1.1.0 | PKG-CAST-01, PKG-CAST-02, PKG-CAST-03, PKG-CAST-04, PKG-CAST-05, PKG-CAST-06 |
| artplayer-plugin-danmuku | 5.3.0 | PKG-DANMUKU-01, PKG-DANMUKU-02, PKG-DANMUKU-03, PKG-DANMUKU-04, PKG-DANMUKU-05, PKG-DANMUKU-06, PKG-DANMUKU-07, PKG-DANMUKU-08, PKG-DANMUKU-09, PKG-DANMUKU-10, PKG-DANMUKU-11, PKG-DANMUKU-12 |
@@ -175,12 +175,13 @@
| PKG-AUTO-THUMB-01 | artplayer-plugin-auto-thumbnail<br>核对包契约与历史用法 | BASE-05 | url/width/number/scale、异步工厂和渐进缩略图更新 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done |
| PKG-AUTO-THUMB-02 | artplayer-plugin-auto-thumbnail<br>建立特有行为与错误测试 | PKG-AUTO-THUMB-01, ENG-03, ENG-05 | 抽帧边界、短视频、失败、连续来源和销毁中的抽帧 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done |
| PKG-AUTO-THUMB-03 | artplayer-plugin-auto-thumbnail<br>整理内部职责与资源 | PKG-AUTO-THUMB-02, CORE-09, CORE-19, PKG-AUTO-THUMB-07 | 隐藏 video、seek 队列、canvas 编码与 Blob URL 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | doing |
| PKG-AUTO-THUMB-04 | artplayer-plugin-auto-thumbnail<br>迁移自有源码和公开类型 | PKG-AUTO-THUMB-03, ENG-04, ENG-06, CORE-07, PKG-AUTO-THUMB-08, PKG-AUTO-THUMB-09 | 抽帧结果和真实异步插件返回类型兼容 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
| PKG-AUTO-THUMB-04 | artplayer-plugin-auto-thumbnail<br>迁移自有源码和公开类型 | PKG-AUTO-THUMB-03, ENG-04, ENG-06, CORE-07, PKG-AUTO-THUMB-08, PKG-AUTO-THUMB-09, PKG-AUTO-THUMB-10 | 抽帧结果和真实异步插件返回类型兼容 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
| PKG-AUTO-THUMB-05 | artplayer-plugin-auto-thumbnail<br>验证新旧核心和组合 | PKG-AUTO-THUMB-04, CORE-22 | 旧核心/候选核心预览、多次加载无过期缩略图覆盖 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo |
| PKG-AUTO-THUMB-06 | artplayer-plugin-auto-thumbnail<br>验证分发并同步文档 | PKG-AUTO-THUMB-05, ENG-07 | auto.thumbnail.js、三种产物和内存/URL 证据 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
| PKG-AUTO-THUMB-07 | artplayer-plugin-auto-thumbnail<br>终止抽帧时清空私有画布像素尺寸 | PKG-AUTO-THUMB-02, CORE-09, CORE-19 | 将私有 canvas 尺寸归入 job 清理;完成、取消、失败及分配重入均有回归,保留已编码 JPEG | 旧红新绿证明保留回调时画布归零,单项清理失败不阻断其他资源;原生取消和完成后 JPEG 仍可解码,原 API/时间公式/类型不变 | M | done |
| PKG-AUTO-THUMB-08 | artplayer-plugin-auto-thumbnail<br>保留旧声明并提供准确异步类型入口 | PKG-AUTO-THUMB-02, ENG-04, ENG-06, CORE-07 | 保留实际 npm 1.1.0 根声明;新增同实现 /runtime 类型、编辑器声明及隔离安装消费者 | 原 Parameters/ReturnType/替代函数不变;准确 Promise 类型正反例、CJS/ESM 条件入口和声明解析通过;不把像素与设备缺口计为通过 | M | done |
| PKG-AUTO-THUMB-09 | artplayer-plugin-auto-thumbnail<br>兼容旧 CommonJS default 与直接工厂调用 | PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-08 | 同一 callable 上的 default 自别名,保留最新根声明并补准确 runtime 别名类型;旧/新实际包入口证据 | 旧红新绿、直接/default/ESM/legacy/global 调用一致;旧根类型提取不变,公开准确类型与实际别名匹配;不关闭抽帧像素和设备缺口 | M | done |
| PKG-AUTO-THUMB-10 | artplayer-plugin-auto-thumbnail<br>为渐进 JPEG 编码建立取消时限与独立资源归属 | PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-07 | 拆分私有 canvas 编码模块,一次一帧的30秒编码时限,完成/失败/切源/销毁取消;迟到和重复回调无副作用 | 受控回调未返回的旧红新绿、正常JPEG和前一预览保持、同步重入/清理失败有回归;真实三浏览器编码/取消通过,公开时间公式与入口不变,首帧风险独立保留 | M | done |
## 5 包迁移:artplayer-plugin-vtt-thumbnail
@@ -639,4 +640,5 @@
- PKG-AUTO-THUMB-07: [记录](changes/2026-09-14-PKG-AUTO-THUMB-07-canvas.md) [记录](baselines/auto-thumbnail-canvas-validation.json)
- PKG-AUTO-THUMB-08: [记录](changes/2026-09-14-PKG-AUTO-THUMB-08-types.md) [记录](baselines/auto-thumbnail-types-validation.json)
- PKG-AUTO-THUMB-09: [记录](changes/2026-09-14-PKG-AUTO-THUMB-09-alias.md) [记录](baselines/auto-thumbnail-alias-validation.json)
- PKG-AUTO-THUMB-10: [记录](changes/2026-09-14-PKG-AUTO-THUMB-10-encoding.md) [记录](baselines/auto-thumbnail-encoding-validation.json)
- ENG-LINT-01: [记录](changes/2026-09-14-ENG-LINT-01-manifest-order.md) [记录](baselines/manifest-lint-validation.json)
+14
View File
@@ -1,5 +1,19 @@
# 进度与证据
## PKG-AUTO-THUMB-10 编码归属与取消时限完成
JPEG编码拆为独立TS模块,原来帧等待结束后编码无时限,现有独立30秒编码时限。
完成时先撤销该时限再发布/取下一帧,切源/销毁/超时清理资源,迟到和重复Blob
不再产生后续动作;保留最后可用预览。此项明确限制极慢编码,不声称原生编码器
已复现自发卡死,也不改变公开时间公式/类型/工厂。初始六项旧红,候选九项编码
回归并入174项插件检查全部通过;严格TS通过,lint保留1既有warning。实际构建
三格式及docs副本,产物11项Node与9项三浏览器通过;源码27项浏览器与50项CI
回归通过。超时浏览器用例执行真实JPEG但受控扣留回调/触发时限,像素测试原有
首帧缺口仍独立保留。见[记录](changes/2026-09-14-PKG-AUTO-THUMB-10-encoding.md)及
[证据](baselines/auto-thumbnail-encoding-validation.json)。新增任务10独立提交,246项:
174 done、16 doing、56 todo;任务03/首帧风险仍开放。没有依赖/版本变化或发布。
下一步继续未完成包的资源、类型收尾与组合验证,不重复已失败的原生首帧等待方案。
## Auto Thumbnail 原生首帧边界检查点
新增独立 video/canvas 诊断,完全不加载 ArtPlayer 或插件。冻结原视频不变,另用
+1
View File
@@ -263,3 +263,4 @@
| VTT-CORE-NAME-01 | open / 已复现 | Published VTT 1.0.1 control name conflicts with the core placeholder introduced in 5.1.7 | PKG-VTT-THUMB-05, REL-08 |
| SCAFFOLD-OUTPUT-01 | resolved / 已复现 | Plugin generation overwrites existing examples and links to a different example name | MOD-PLUGIN-01 |
| DEV-SERVOR-PORT-01 | resolved / 已复现 | Servor exits the entire dev process with status zero when the requested port is occupied | MOD-DEV-01 |
| AUTO-THUMB-ENCODE-TIMEOUT-01 | resolved / 源码/产物事实 | Pending JPEG encoding has no bounded lifetime after frame readiness finishes | PKG-AUTO-THUMB-10 |
+22
View File
@@ -5940,6 +5940,28 @@
"test/browser/library-development.spec.js"
],
"resolutionRationale": "Exact port binding rejects with EADDRINUSE; CLI propagates exit1. Explicit close/done owns HTTP sockets, file pipelines, source/docs watchers, SSE heartbeat and active builds. Eight node tests and six Windows real-browser cases cover the stated defect and lifecycle scope without stopping unrelated services."
},
{
"id": "AUTO-THUMB-ENCODE-TIMEOUT-01",
"title": "Pending JPEG encoding has no bounded lifetime after frame readiness finishes",
"confirmation": "source-observed",
"status": "resolved",
"owners": [
"PKG-AUTO-THUMB-10"
],
"evidence": [
"refactor/changes/2026-09-14-PKG-AUTO-THUMB-10-encoding.md",
"refactor/baselines/auto-thumbnail-encoding-validation.json"
],
"compatibleResolution": "Preserve normal progressive JPEG publication and prior previews; add an explicit30-second encoding deadline with cancellation and stale callback protection.",
"closureCriteria": "Withheld callback ownership, timeout/late delivery, completion/restart/destroy and registration/cleanup reentry have regression coverage; native JPEG/resource and built artifact checks pass without waiving pixel/device gates.",
"workspaceState": "Source inspection and six controlled old failures show no encoding deadline. Dedicated encoder now owns one30-second timer, clears it before publication and releases the job on expiry. This is a bounded-resource policy, not proof of a spontaneous native encoder hang. Initial metadata/network and aggregate budgets remain separate.",
"resolutionEvidence": [
"refactor/baselines/auto-thumbnail-encoding-validation.json",
"test/auto-thumbnail-encoding.test.js",
"test/browser/auto-thumbnail-lifecycle.spec.js"
],
"resolutionRationale": "Nine controlled cases and real native JPEG tests cover held/late callbacks and decoder/canvas disposal. Actual production UMD passes11 Node and9 browser checks; previous preview survives timeout. Very slow encoding can now be discarded explicitly; public options, registration and frame-time formula remain intact."
}
]
}
+22 -1
View File
@@ -1819,7 +1819,8 @@
"ENG-06",
"CORE-07",
"PKG-AUTO-THUMB-08",
"PKG-AUTO-THUMB-09"
"PKG-AUTO-THUMB-09",
"PKG-AUTO-THUMB-10"
],
"status": "todo",
"risk": "H",
@@ -5071,6 +5072,26 @@
"baselines/auto-thumbnail-alias-validation.json"
]
},
{
"id": "PKG-AUTO-THUMB-10",
"phase": "5 包迁移:artplayer-plugin-auto-thumbnail",
"title": "为渐进 JPEG 编码建立取消时限与独立资源归属",
"scope": [
"artplayer-plugin-auto-thumbnail"
],
"dependsOn": [
"PKG-AUTO-THUMB-02",
"PKG-AUTO-THUMB-07"
],
"status": "done",
"risk": "M",
"deliverable": "拆分私有 canvas 编码模块,一次一帧的30秒编码时限,完成/失败/切源/销毁取消;迟到和重复回调无副作用",
"acceptance": "受控回调未返回的旧红新绿、正常JPEG和前一预览保持、同步重入/清理失败有回归;真实三浏览器编码/取消通过,公开时间公式与入口不变,首帧风险独立保留",
"evidence": [
"changes/2026-09-14-PKG-AUTO-THUMB-10-encoding.md",
"baselines/auto-thumbnail-encoding-validation.json"
]
},
{
"id": "ENG-LINT-01",
"phase": "2 工程基础",