mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-24 14:41:20 -08:00
test(asr): [PKG-ASR-01] freeze published interfaces and source contracts
This commit is contained in:
1 parent
3b016970f2
commit
a22586a172
16 files changed
+543
-7
No files matched your search
@@ -5,6 +5,11 @@
|
||||
|
||||
AI 用于源码分析、任务拆分、实现、测试和差异审查。现代化的验收是可验证的类型、行为和构建质量,不以生成代码量为指标。
|
||||
|
||||
2026-09-13 用户授权使用子代理加快重构。按独立包或不重叠文件划分有界任务,
|
||||
主代理负责集成、共享任务台账和每任务提交;子代理不得同时改同一生产模块或
|
||||
自行批量提交。测试可与契约核对并行,依赖未满足的实现不得提前宣布完成。
|
||||
按实际影响范围验证,完整回归保留在跨包变更和阶段验收节点;不承诺线性加速。
|
||||
|
||||
## 开始任务
|
||||
|
||||
1. 阅读根 AGENTS.md、本目录 README、progress、quality-contract.md,以及所选任务关联的契约/设计。
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# ASR 发布契约
|
||||
|
||||
PKG-ASR-01 于 2026-09-13 固定 npm 2.0.0、2.1.0 的实际归档,每包 6 个成员。
|
||||
[来源与逐文件指纹](asr-release.json)另保存工作区提交的 9 个 Git 文本输入。
|
||||
运行 `node --test test/asr.test.js refactor/scripts/asr-contract.test.mjs`:32 项通过。
|
||||
首次下载使用固定 npm URL;缓存后离线复核 SHA-512、SHA-256、成员与历史 Git 输入。
|
||||
|
||||
## 支持范围与入口
|
||||
|
||||
- registry gitHead 对应核心 manifest 为 5.3.1-beta.1 / 5.3.1;这是来源关联,
|
||||
不是已完成这些核心的播放器组合验证,更不是最低核心版本声明。
|
||||
- 两个发布包没有 engines/peerDependencies;工作区 2.1.0 不等于发布 tarball。
|
||||
- main/legacy 可在 CJS 读取并作为普通 script 暴露 artplayerPluginAsr;2.0.0 的 CJS
|
||||
是只有 default 可枚举成员的对象,2.1.0 是无可枚举成员的函数。测试同时断言这些
|
||||
原始形状,再从函数或 default 成员取得工厂;迁移必须分别保留历史调用路径。
|
||||
- 两个实际 ESM 文件均在无 DOM 环境导入,仅导出 default,调用工厂仍不创建音频资源。
|
||||
- 旧 TS 工厂替换和安装消费者验收归 PKG-ASR-04;不能以本次
|
||||
VM 运行通过替代实际 tarball 安装验证。
|
||||
|
||||
## 公开行为
|
||||
|
||||
| 项目 | 既有行为 |
|
||||
| --- | --- |
|
||||
| 工厂 | option 可省略;在调用工厂时解构,之后更改 option 不影响注册 |
|
||||
| 默认值 | length=3、interval=100ms、sampleRate=16000、autoHideTimeout=10000ms |
|
||||
| 注册 | 同步创建 name=asr 的 layer,返回 name/stop/hide/append;无公开 start |
|
||||
| 事件 | 注册 video:volumechange、play、pause、destroy;播放事件启动采集 |
|
||||
| append | 同步返回 undefined;非字符串忽略,字符串替换全部内容 |
|
||||
| 行拆分 | 按 、。!?!?. 断句,trim/filter,保留最后 length 段;length=0 保留全部 |
|
||||
| 内容 | div.art-asr-line 包裹,通过 innerHTML 接受 HTML;不能静默改为纯文本 |
|
||||
| hide | 只隐藏显示,不清内容;下一次字符串 append 恢复并重置自动隐藏定时器 |
|
||||
| stop | 实际返回 Promise<void>,调用完整音频销毁;保留播放订阅,可随后重启 |
|
||||
| 样式 | 模块加载时按 artplayer-plugin-asr ID 去重;沿用 art-layer-asr/CSS 变量 |
|
||||
|
||||
32 项测试包括两个发布版本的 main/legacy、冻结源码以及冻结工作区 main/legacy,
|
||||
分别观察 CJS/global 工厂、返回值、选项快照、字幕行为、样式去重;另有归档与 ESM 检查。
|
||||
冻结源码用 esbuild 转换,仅把 LESS import 换为测试字符串;该项不验证真实 CSS 编译。
|
||||
真实发布和冻结工作区 bundle 使用其实际内嵌样式。
|
||||
|
||||
## 已发现的差异及后续处理
|
||||
|
||||
1. 两版及工作区声明把 stop 写成 void,onAudioChunk 写成 void | Promise<void>;
|
||||
实际 stop 是异步,并等待回调结果交给 append。类型迁移需保留旧函数赋值能力,
|
||||
补充精确异步消费,不能只改返回类型就宣布兼容。由 PKG-ASR-04 处理。
|
||||
2. 源码每次 tick 取队列再截断,未满一块的样本和超过块长的尾部均没有放回;
|
||||
这是源码事实,PKG-ASR-02 用准确 PCM 样本序列复现,PKG-ASR-03 修复。
|
||||
3. 初始化最后才置 started;停止及异常清理依赖 started,addModule 失败没有 finally
|
||||
回收 URL;停止不能使在途回调失效。PKG-ASR-02 复现后再作独立生命周期修复。
|
||||
4. pause 后 sourceNode 仍存在,而 setupAudioSource 仅在不存在时直接返回节点;
|
||||
再次启动可能进入 captureStream 分支。需验证重复启动与恢复,不能只测一次播放。
|
||||
5. README 误写 Ads;本次改正包功能描述。demo 使用外部 ASR HTTP/WebSocket,服务
|
||||
不是本包依赖或已验证能力。本包只产出 PCM/WAV,不请求麦克风,也不自带识别模型。
|
||||
|
||||
## 下一步与限制
|
||||
|
||||
PKG-ASR-02 建立 PCM/WAV、Worklet 消息、失败、乱序和资源的受控回归;PKG-ASR-03
|
||||
拆分字幕、编码、队列和音频资源职责;PKG-ASR-04 完成严格 TS 与旧消费者。
|
||||
PKG-ASR-05 使用本地媒体与本地 onAudioChunk 验证真实 WebAudio/Worklet、音频持续性、
|
||||
新旧核心与三个浏览器。WebAudio mock 不代替实际音频/采样率/静音/CORS/设备验证。
|
||||
本任务没有运行真实识别服务,不增加依赖,不改生产源码/分发版本。
|
||||
@@ -0,0 +1,138 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"registry": "https://registry.npmjs.org/artplayer-plugin-asr",
|
||||
"capturedAt": "2026-09-13T05:57:08.117Z",
|
||||
"sourceCommit": "3b016970f24fea603706a2f4bd50026846f5d939",
|
||||
"sourceNormalization": "Git text normalized to LF; archive members hashed as bytes.",
|
||||
"source": {
|
||||
"packages/artplayer-plugin-asr/package.json": "f0c9fc6c294376c7ed8974556672b077e31fae480bd8e3ecc8b2a060811b29cd",
|
||||
"packages/artplayer-plugin-asr/README.md": "8bc731990d7ab32837af8382a99759ee14b6872dd24065929054a69fdcea2e4e",
|
||||
"packages/artplayer-plugin-asr/src/index.js": "af24a6334298d636235d3af417bdea83444d200563ba6df054b66c53cdaef47f",
|
||||
"packages/artplayer-plugin-asr/src/style.less": "ed40939c1db527bddf98c3e08b8c2e0b1d5a3581804fe2084d1070c9d50af0d6",
|
||||
"packages/artplayer-plugin-asr/types/artplayer-plugin-asr.d.ts": "2d1ecb04f285b5835744d80dbde3c4a2a124bf1f5ffc995d0d775f5725309d0f",
|
||||
"packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.js": "7f975b131a9ea207f88a157aafec778bc4906230500db9b30f5bbfbf327b251d",
|
||||
"packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.legacy.js": "8b9f07ce97a8ce2e4f29e41e79257be530fd7a76558369d34c3d7497ea606c33",
|
||||
"packages/artplayer-plugin-asr/dist/artplayer-plugin-asr.mjs": "f1c4274541e86544b65936ff470413cfc7001999ebc193969f95c123be48cd61",
|
||||
"docs/assets/example/asr.js": "bb7fd5eee3df887b7e0c72a6f42f74f0253350f9bc884f73cb9c2996f0e35724"
|
||||
},
|
||||
"release": {
|
||||
"name": "artplayer-plugin-asr",
|
||||
"version": "2.1.0",
|
||||
"tarball": "https://registry.npmjs.org/artplayer-plugin-asr/-/artplayer-plugin-asr-2.1.0.tgz",
|
||||
"integrity": "sha512-15gXff458PAx9LeJxKzZEvmpFhfwKUfSLgb1Mfr7Xb/ZGsnE+6EA7ezTnO5S55W5mFExjv/e95iOIXP4ijuruQ==",
|
||||
"sha256": "8bc3cd93f78ce99e5c09cc546c770a63e8aea5729d3d584134ce04d826b7708b",
|
||||
"registryGitHead": "daf133b22630b4a0eecfa3336bbddab0e9119d96",
|
||||
"files": {
|
||||
"package/README.md": "8bc731990d7ab32837af8382a99759ee14b6872dd24065929054a69fdcea2e4e",
|
||||
"package/dist/artplayer-plugin-asr.js": "7f975b131a9ea207f88a157aafec778bc4906230500db9b30f5bbfbf327b251d",
|
||||
"package/dist/artplayer-plugin-asr.legacy.js": "8b9f07ce97a8ce2e4f29e41e79257be530fd7a76558369d34c3d7497ea606c33",
|
||||
"package/dist/artplayer-plugin-asr.mjs": "f1c4274541e86544b65936ff470413cfc7001999ebc193969f95c123be48cd61",
|
||||
"package/package.json": "f0c9fc6c294376c7ed8974556672b077e31fae480bd8e3ecc8b2a060811b29cd",
|
||||
"package/types/artplayer-plugin-asr.d.ts": "2d1ecb04f285b5835744d80dbde3c4a2a124bf1f5ffc995d0d775f5725309d0f"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "artplayer-plugin-asr",
|
||||
"version": "2.1.0",
|
||||
"description": "Asr plugin for ArtPlayer",
|
||||
"author": "Harvey Zhao <laozhaochaguan@gmail.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://artplayer.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"html5",
|
||||
"video",
|
||||
"player"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"import": "./dist/artplayer-plugin-asr.mjs",
|
||||
"require": "./dist/artplayer-plugin-asr.js"
|
||||
},
|
||||
"./legacy": {
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"import": "./dist/artplayer-plugin-asr.legacy.js",
|
||||
"require": "./dist/artplayer-plugin-asr.legacy.js"
|
||||
}
|
||||
},
|
||||
"main": "./dist/artplayer-plugin-asr.js",
|
||||
"module": "./dist/artplayer-plugin-asr.mjs",
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"legacy": "./dist/artplayer-plugin-asr.legacy.js",
|
||||
"browserslist": "last 1 Chrome version"
|
||||
},
|
||||
"historicalCore": {
|
||||
"commit": "daf133b22630b4a0eecfa3336bbddab0e9119d96",
|
||||
"file": "packages/artplayer/package.json",
|
||||
"version": "5.3.1",
|
||||
"sha256LF": "862f3697876fe915dd0ada178da766ce823aae7563ed30b3e5b11b811202929c"
|
||||
}
|
||||
},
|
||||
"previous": [
|
||||
{
|
||||
"name": "artplayer-plugin-asr",
|
||||
"version": "2.0.0",
|
||||
"tarball": "https://registry.npmjs.org/artplayer-plugin-asr/-/artplayer-plugin-asr-2.0.0.tgz",
|
||||
"integrity": "sha512-nXTf2drMSKnHRbyU9CQ+3o7Jsf1Meam2O9T8LqYakIr18ag/+i71p2x9zdFrLz16Xa6jfQgKeddmU5r3sXp4LA==",
|
||||
"sha256": "faa726b9536306664d935c95367230e0c622bd046faf636fc2dcef4bbce4cd47",
|
||||
"registryGitHead": "ca34b47180c94048ee765ab7e146face737eac1c",
|
||||
"files": {
|
||||
"package/README.md": "24446684a782c4c179516917a42862809164aac1ae9746e21a09da738e19ca42",
|
||||
"package/dist/artplayer-plugin-asr.js": "30c7b1fc92a262cda8c3aba63afea9c6c038f52c057039d1c6aa957baed155b6",
|
||||
"package/dist/artplayer-plugin-asr.legacy.js": "2c2bf48751e4d3cfa88f7313f092d395b61bc0564f6cc44f2c76f0fbcfc66412",
|
||||
"package/dist/artplayer-plugin-asr.mjs": "98ebdec2c66cecd9d19904a2e54e4b645f7c267b569e560d9bcbeee6028b2267",
|
||||
"package/package.json": "7545d9bb95b48aedec45c0345f39dd8f0728a24ffe148a04e3740e1ef50239df",
|
||||
"package/types/artplayer-plugin-asr.d.ts": "2d1ecb04f285b5835744d80dbde3c4a2a124bf1f5ffc995d0d775f5725309d0f"
|
||||
},
|
||||
"manifest": {
|
||||
"name": "artplayer-plugin-asr",
|
||||
"version": "2.0.0",
|
||||
"description": "Asr plugin for ArtPlayer",
|
||||
"author": "Harvey Zack <laozhaochaguan@gmail.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://artplayer.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/zhw2590582/ArtPlayer.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/zhw2590582/ArtPlayer/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"html5",
|
||||
"video",
|
||||
"player"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"import": "./dist/artplayer-plugin-asr.mjs",
|
||||
"require": "./dist/artplayer-plugin-asr.js"
|
||||
},
|
||||
"./legacy": {
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"import": "./dist/artplayer-plugin-asr.legacy.js",
|
||||
"require": "./dist/artplayer-plugin-asr.legacy.js"
|
||||
}
|
||||
},
|
||||
"main": "./dist/artplayer-plugin-asr.js",
|
||||
"module": "./dist/artplayer-plugin-asr.mjs",
|
||||
"types": "./types/artplayer-plugin-asr.d.ts",
|
||||
"legacy": "./dist/artplayer-plugin-asr.legacy.js",
|
||||
"browserslist": "last 1 Chrome version"
|
||||
},
|
||||
"historicalCore": {
|
||||
"commit": "ca34b47180c94048ee765ab7e146face737eac1c",
|
||||
"file": "packages/artplayer/package.json",
|
||||
"version": "5.3.1-beta.1",
|
||||
"sha256LF": "e1a0a390ec10cd8c1c12006ac6515414ae98a964300dd3e9c288377def948497"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# PKG-ASR-01:固定 ASR 公开契约
|
||||
|
||||
源起点为 3b016970f24fea603706a2f4bd50026846f5d939。冻结实际 npm 2.0.0/2.1.0、
|
||||
12 个归档成员、9 个工作区 Git 文本及各自历史核心 manifest;不覆盖初始 BASE 快照。
|
||||
交付物为 [契约](../baselines/asr-contract.md)、[来源](../baselines/asr-release.json)、
|
||||
可重跑的 asr-contract 校验器与 test/asr.test.js。生产行为未改动。
|
||||
|
||||
确认接口同步注册、异步 stop、工厂参数快照、字幕替换/HTML/隐藏行为及样式去重。
|
||||
公开声明与异步行为不一致、队列丢样本及初始化清理疑点分别登记到后续任务,
|
||||
未把源码观察写成已修复问题。README 的 Ads 误写修正并链接包内维护说明。
|
||||
|
||||
验证:`node --test test/asr.test.js refactor/scripts/asr-contract.test.mjs` 32 项通过;
|
||||
定向 ESLint、计划与风险台账检查通过。未运行全量 CI、真实浏览器、安装消费者或外部 ASR。
|
||||
本批只固定后续迁移依据,真实音频、旧类型消费与发行验收仍由 ASR-02 至 ASR-06 负责。
|
||||
|
||||
无新依赖。增加 test:asr 命令并把公开行为测试接入 test:unit;来源检查在既有
|
||||
test:baseline 通配入口执行。每次重跑都会校验归档,不静默重写基线。
|
||||
回退本任务提交可移除这些基线、测试、文档与任务状态,不影响当前播放器运行时。
|
||||
+3
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 225 项,范围 22 个包及工作区/示例。
|
||||
|
||||
状态:todo 86 / doing 16 / blocked 0 / done 123 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
状态:todo 85 / doing 16 / blocked 0 / done 124 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
|
||||
|
||||
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
|
||||
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| PKG-ASR-01 | artplayer-plugin-asr<br>核对包契约与历史用法 | BASE-05 | length/interval/sampleRate/onAudioChunk、append/hide/stop 的真实能力 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | todo |
|
||||
| PKG-ASR-01 | artplayer-plugin-asr<br>核对包契约与历史用法 | BASE-05 | length/interval/sampleRate/onAudioChunk、append/hide/stop 的真实能力 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done |
|
||||
| PKG-ASR-02 | artplayer-plugin-asr<br>建立特有行为与错误测试 | PKG-ASR-01, ENG-03, ENG-05 | PCM/WAV、chunk 时序、回调慢/拒绝、重复初始化与停止 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | todo |
|
||||
| PKG-ASR-03 | artplayer-plugin-asr<br>整理内部职责与资源 | PKG-ASR-02, CORE-10, CORE-18 | AudioContext/Worklet/Stream 生命周期和背压分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo |
|
||||
| PKG-ASR-04 | artplayer-plugin-asr<br>迁移自有源码和公开类型 | PKG-ASR-03, ENG-04, ENG-06, CORE-07 | 主线程/Worklet/音频 buffer 与异步回调类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
|
||||
@@ -526,6 +526,7 @@
|
||||
- PKG-MULTI-SUB-04: [记录](baselines/multiple-subtitles-runtime-types.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-04-runtime-types.md) [记录](baselines/multiple-subtitles-public-types.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-04-public-types.md)
|
||||
- PKG-MULTI-SUB-07: [记录](baselines/multiple-subtitles-timestamps.json) [记录](changes/2026-09-13-PKG-MULTI-SUB-07-timestamps.md)
|
||||
- PKG-JASSUB-01: [记录](baselines/jassub-release.json) [记录](baselines/jassub-vendor.json) [记录](baselines/jassub-font-metadata.json) [记录](baselines/jassub-contract.md) [记录](baselines/jassub-contract-validation.json) [记录](changes/2026-09-13-PKG-JASSUB-01-baseline.md)
|
||||
- PKG-ASR-01: [记录](changes/2026-09-13-PKG-ASR-01-contracts.md) [记录](baselines/asr-contract.md) [记录](baselines/asr-release.json)
|
||||
- PKG-ADS-01: [记录](baselines/ads-release.json) [记录](baselines/ads-contract.md) [记录](baselines/ads-contract-validation.json) [记录](changes/2026-09-12-PKG-ADS-01-contract.md) [记录](scripts/ads-contract.test.mjs)
|
||||
- PKG-ADS-02: [记录](changes/2026-09-12-PKG-ADS-02-tests.md) [记录](ads-validation.md) [记录](baselines/ads-validation.json)
|
||||
- PKG-ADS-03: [记录](changes/2026-09-12-PKG-ADS-03-lifecycle.md) [记录](ads-validation.md) [记录](baselines/ads-lifecycle-validation.json)
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# 进度与证据
|
||||
|
||||
## PKG-ASR-01 发布契约完成
|
||||
|
||||
冻结实际 npm 2.0.0/2.1.0 共 12 成员及工作区 9 个 Git 输入;32 项契约测试通过,
|
||||
包含 CJS/global、实际 ESM、字幕 HTML/行数/隐藏、异步 stop 和工厂选项快照。
|
||||
声明异步差异、音频丢样本及生命周期疑点已分别登记,未将源码疑点写成已修复。
|
||||
修正 README 的 Ads 误写并增加包内维护地图;无生产源码、依赖或版本变化。
|
||||
见[契约](baselines/asr-contract.md)和[变更](changes/2026-09-13-PKG-ASR-01-contracts.md)。
|
||||
225 项:124 done、16 doing、85 todo;205 风险。下一步 ASR 受控音频测试与源码拆分。
|
||||
用户已授权子代理;当前子代理只写独立音频测试文件,主代理负责契约、台账和提交。
|
||||
实际浏览器、旧类型消费者和全包发布仍待完成;没有运行外部识别服务。
|
||||
|
||||
|
||||
## CORE-25 无 navigator 默认选项修复完成
|
||||
|
||||
defaults.ts 使用 typeof 保护不存在的全局绑定,保留浏览器语言小写、lang 自有字段及每次
|
||||
|
||||
@@ -206,3 +206,6 @@
|
||||
| JASSUB-EXPORT-01 | open / 已复现 | JASSUB historical CommonJS object.default changes to a direct factory in 1.1.0 | PKG-JASSUB-04, PKG-JASSUB-06 |
|
||||
| CORE-DEFAULTS-SSR-01 | resolved / 已复现 | Reading static defaults throws when navigator is absent | CORE-25 |
|
||||
| ENG-DIST-PUBLIC-01 | resolved / 已复现 | Vite copied authored declarations into library distribution | ENG-12 |
|
||||
| ASR-TYPE-01 | open / 源码/产物事实 | ASR declarations omit asynchronous stop and callback text results | PKG-ASR-04 |
|
||||
| ASR-CHUNK-01 | open / 源码/产物事实 | ASR tick discards underfilled chunks and overrun samples in source | PKG-ASR-02, PKG-ASR-03 |
|
||||
| ASR-LIFE-01 | open / 源码/产物事实 | ASR partial initialization, pause resume and stale callback cleanup need controlled evidence | PKG-ASR-02, PKG-ASR-03, PKG-ASR-05 |
|
||||
@@ -4541,6 +4541,54 @@
|
||||
"refactor/changes/2026-09-13-ENG-12-library-public.md"
|
||||
],
|
||||
"resolutionRationale": "Three-format disk fixture and actual core archive prove removal; all other package members remain byte-identical. Full 21-library and docs build passed. CORE-25 runtime work was present but is not closed by this task."
|
||||
},
|
||||
{
|
||||
"id": "ASR-TYPE-01",
|
||||
"title": "ASR declarations omit asynchronous stop and callback text results",
|
||||
"confirmation": "source-observed",
|
||||
"status": "open",
|
||||
"owners": [
|
||||
"PKG-ASR-04"
|
||||
],
|
||||
"evidence": [
|
||||
"refactor/baselines/asr-contract.md",
|
||||
"refactor/baselines/asr-release.json"
|
||||
],
|
||||
"compatibleResolution": "Keep historical assignment compatibility while supplying accurate asynchronous consumption.",
|
||||
"closureCriteria": "Actual old/new installed TS consumers cover void callback, Promise<void>, returned text and factory substitution."
|
||||
},
|
||||
{
|
||||
"id": "ASR-CHUNK-01",
|
||||
"title": "ASR tick discards underfilled chunks and overrun samples in source",
|
||||
"confirmation": "source-observed",
|
||||
"status": "open",
|
||||
"owners": [
|
||||
"PKG-ASR-02",
|
||||
"PKG-ASR-03"
|
||||
],
|
||||
"evidence": [
|
||||
"refactor/baselines/asr-contract.md",
|
||||
"refactor/baselines/asr-release.json"
|
||||
],
|
||||
"compatibleResolution": "Reproduce exact sample loss and retain queue remainders with bounded, ordered callback delivery.",
|
||||
"closureCriteria": "Exact PCM/WAV byte sequence and slow/rejected callback regression tests pass without losing or reordering accepted input."
|
||||
},
|
||||
{
|
||||
"id": "ASR-LIFE-01",
|
||||
"title": "ASR partial initialization, pause resume and stale callback cleanup need controlled evidence",
|
||||
"confirmation": "source-observed",
|
||||
"status": "open",
|
||||
"owners": [
|
||||
"PKG-ASR-02",
|
||||
"PKG-ASR-03",
|
||||
"PKG-ASR-05"
|
||||
],
|
||||
"evidence": [
|
||||
"refactor/baselines/asr-contract.md",
|
||||
"refactor/baselines/asr-release.json"
|
||||
],
|
||||
"compatibleResolution": "Own pending setup, URLs, source nodes and callbacks across pause, stop, restart and terminal destruction.",
|
||||
"closureCriteria": "Failure/race regression tests plus native WebAudio playback and cleanup evidence prove resource ownership."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { archiveFiles, ensureArchive, hash, readMember, refactorDir } from './releases.mjs'
|
||||
|
||||
export async function verifyAsrContract() {
|
||||
const baseline = JSON.parse(fs.readFileSync(path.join(refactorDir, 'baselines/asr-release.json'), 'utf8'))
|
||||
const archives = new Map()
|
||||
for (const release of [baseline.release, ...baseline.previous]) {
|
||||
const archive = await ensureArchive(release)
|
||||
assert.deepEqual(archiveFiles(archive), Object.keys(release.files).sort())
|
||||
for (const [file, expected] of Object.entries(release.files))
|
||||
assert.equal(hash(readMember(archive, file)), expected, `${release.version}/${file}`)
|
||||
assert.deepEqual(JSON.parse(readMember(archive, 'package/package.json')), release.manifest)
|
||||
for (const field of ['main', 'module', 'types', 'legacy'])
|
||||
assert(Object.hasOwn(release.files, `package/${release.manifest[field].replace(/^\.\//, '')}`))
|
||||
const core = release.historicalCore
|
||||
const source = execFileSync('git', ['show', `${core.commit}:${core.file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(source), core.sha256LF)
|
||||
assert.equal(JSON.parse(source).version, core.version)
|
||||
archives.set(release.version, archive)
|
||||
}
|
||||
const sources = new Map()
|
||||
for (const [file, expected] of Object.entries(baseline.source)) {
|
||||
const source = execFileSync('git', ['show', `${baseline.sourceCommit}:${file}`], { encoding: 'utf8' }).replaceAll('\r\n', '\n')
|
||||
assert.equal(hash(source), expected, file)
|
||||
sources.set(file, source)
|
||||
}
|
||||
return { baseline, archives, sources }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { Buffer } from 'node:buffer'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Frozen published package evidence uses the repository runner.
|
||||
import test from 'node:test'
|
||||
import { verifyAsrContract } from './asr-contract.mjs'
|
||||
import { readMember } from './releases.mjs'
|
||||
|
||||
const { baseline, archives, sources } = await verifyAsrContract()
|
||||
const releases = [baseline.release, ...baseline.previous]
|
||||
test('ASR verifies both releases, twelve archive members, nine Git inputs and historical core references', () => {
|
||||
assert.deepEqual(releases.map(r => r.version), ['2.1.0', '2.0.0'])
|
||||
assert.equal(releases.reduce((n, r) => n + Object.keys(r.files).length, 0), 12)
|
||||
assert.equal(sources.size, 9)
|
||||
assert.deepEqual(releases.map(r => r.historicalCore.version), ['5.3.1', '5.3.1-beta.1'])
|
||||
for (const release of releases) {
|
||||
assert.equal(release.manifest.peerDependencies, undefined)
|
||||
assert.equal(release.manifest.engines, undefined)
|
||||
}
|
||||
})
|
||||
test('ASR old declarations describe void callback/stop despite runtime consuming returned text and returning a Promise', () => {
|
||||
for (const release of releases) {
|
||||
const types = readMember(archives.get(release.version), 'package/types/artplayer-plugin-asr.d.ts').toString()
|
||||
assert.match(types, /onAudioChunk\?: \(chunk: AudioChunk\) => void \| Promise<void>/)
|
||||
assert.match(types, /stop: \(\) => void/)
|
||||
assert.match(types, /export default artplayerPluginAsr/)
|
||||
assert.match(types, /option\?: AsrPluginOption/)
|
||||
}
|
||||
})
|
||||
test('ASR actual published ESM exposes a lazy default factory without requiring a browser', async () => {
|
||||
for (const release of releases) {
|
||||
const source = readMember(archives.get(release.version), 'package/dist/artplayer-plugin-asr.mjs')
|
||||
const module = await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`)
|
||||
assert.deepEqual(Object.keys(module), ['default'])
|
||||
assert.equal(typeof module.default(), 'function')
|
||||
}
|
||||
})
|
||||
test('ASR source ships an inline Worklet; network transcription is caller-owned example behavior', () => {
|
||||
const source = sources.get('packages/artplayer-plugin-asr/src/index.js')
|
||||
assert.match(source, /registerProcessor\('recorder-processor'/)
|
||||
assert.doesNotMatch(source, /\bfetch\(|new WebSocket\(/)
|
||||
const demo = sources.get('docs/assets/example/asr.js')
|
||||
assert.match(demo, /await fetch\(api\)/)
|
||||
assert.match(demo, /new WebSocket\(url\)/)
|
||||
for (const release of releases)
|
||||
assert(!Object.keys(release.files).some(file => /worklet|worker|\.wasm/.test(file)))
|
||||
})
|
||||
+6
-2
@@ -2617,11 +2617,15 @@
|
||||
"dependsOn": [
|
||||
"BASE-05"
|
||||
],
|
||||
"status": "todo",
|
||||
"status": "done",
|
||||
"risk": "H",
|
||||
"deliverable": "length/interval/sampleRate/onAudioChunk、append/hide/stop 的真实能力",
|
||||
"acceptance": "源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结",
|
||||
"evidence": []
|
||||
"evidence": [
|
||||
"changes/2026-09-13-PKG-ASR-01-contracts.md",
|
||||
"baselines/asr-contract.md",
|
||||
"baselines/asr-release.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PKG-ASR-02",
|
||||
|
||||
Reference in new issue
Block a user