8.7 KiB
Danmuku Mask 历史契约与 SDK-08 证据
任务 PKG-MASK-01。依据 真实归档 与
原始 npm 响应,捕获时全部稳定版为 1.0.0、1.1.0。
冻结工作区提交为 b0cfbfe3a09a84a295a257e45e4577847588d1cb。
源码文本以 LF 归一化;tarball、成员、已有模型资源均按原始字节计算哈希。
发布来源与公开形状
两版各有六个实际归档成员:README、manifest、main/legacy/module 三种产物和声明。
四个 manifest 入口以及 root/legacy exports 目标全部存在。源码由 .npmignore
排除;不能声称 npm 包含源码。1.1.0 六个成员与冻结工作区对应文件完全一致。
| 项目 | npm 1.0.0 | npm 1.1.0 |
|---|---|---|
| registry gitHead | b36f88db5f7fe0250285fd4f47229842231f402b |
daf133b22630b4a0eecfa3336bbddab0e9119d96 |
| gitHead 的插件 manifest | 1.0.0 | 1.0.1,与发布版本不一致 |
| 同提交核心 manifest | 5.3.1-beta.1 | 5.3.1 |
| 实际 CommonJS main/legacy | 对象的 .default 工厂 |
直接工厂,无 .default |
| 实际 script main/legacy | 全局 artplayerPluginDanmukuMask 工厂 |
同名工厂 |
| module | .mjs 中 default export |
.mjs 中 default export |
| 声明 | optional option、同步注册结果 | 与 1.0.0 字节一致 |
核心版本仅是 Git 关联,不是已经通过的兼容矩阵。main/legacy 的 CommonJS 与 script
导出已用实际归档字节在隔离 VM 验证,包括不启动模型的注册/stop;module 这里只做
成员与文本形状核实,尚未完成真实安装 ESM/NodeNext 消费。较早来源源码的额外
window.artplayerPluginDanmukuMask = ... 已在冻结工作区移除;归档全局仍保留。
公开工厂 artplayerPluginDanmukuMask(option?) 同步返回 registrar;registrar 同步
返回 { name: 'artplayerPluginDanmukuMask', start, stop }。start(): Promise<void>,
stop(): void,两版声明均如此。Option/Result 未作为命名导出发布。后续类型工作应
保持最新完整工厂赋值和 NodeNext 旧模块形状,遵守统一类型政策;旧 CJS .default
调用是实际合法 JS,不能因为最新声明没有属性而删掉兼容路径。
源码参数与样式
参数在 registrar 调用时快照为内部 config,之后修改原 option 不会重读。默认值:
| 字段 | 默认值 / 合并规则 |
|---|---|
| solutionPath | https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation,` |
| modelSelection | 1,` |
| smoothSegmentation | true,仅 undefined 使用默认,false 保留 |
| minDetectionConfidence / minTrackingConfidence | 各 0.5,` |
| selfieMode / drawContour | 各 false,` |
| foregroundThreshold | 0.5,` |
| opacity | 1,` |
| maskBlurAmount | 3,` |
这些是插件传给适配器的值,不是所有参数都对模型有效。源码始终指定
runtime: 'mediapipe'、modelType: 'general';先尝试 tf.setBackend('webgl'),
仅 rejection 时尝试 cpu。这不能证明 MediaPipe 自身推理切换成 CPU,也不能把
setBackend fulfilled false 视为已执行 fallback。
registrar 捕获 art.template.$video/$danmuku,订阅 ready→start、destroy→stop。
需要核心模板已经提供 $danmuku/$video;demo 使用先 Danmuku 再 Mask 的顺序。
2026-09-13(PKG-DANMUKU-07)纠正初始记录:$danmuku 由核心模板创建,
不是 Danmuku 插件创建,因此 demo 顺序本身不构成 Mask 对 Danmuku 注册的硬依赖。
Mask 源码不读取 Danmuku 队列、owner 或插件事件;完整模型组合仍待 Mask 验收。
start 建立 2D canvas 并设置 $danmuku.style:maskMode=alpha、maskSize=contain、
maskRepeat=no-repeat、backgroundSize=contain、backgroundRepeat=no-repeat。
每轮以视频固有尺寸推理,白色前景/黑色背景生成 binary mask,drawMask 后将 RGB
三个分量均 >250 的像素 alpha 置 0,以 canvas PNG data URL 写入 maskImage。
值等于 250 的边界不透明。stop 只写 maskImage=none 并取消所记住的一次 RAF;
其余样式不恢复。没有额外 public 事件或插件自建可见 DOM。
SDK-08:锁文件、适配器和模型资源是不同来源
| 依赖 | manifest 范围 | 冻结 Yarn / 当前安装 |
|---|---|---|
| @mediapipe/selfie_segmentation | ^0.1.1675465747 | 0.1.1675465747 |
| @tensorflow-models/body-segmentation | ^1.0.2 | 1.0.2 |
| @tensorflow/tfjs-backend-cpu | ^4.21.0 | 4.22.0 |
| @tensorflow/tfjs-backend-webgl | ^4.21.0 | 4.22.0 |
| @tensorflow/tfjs-converter | ^4.21.0 | 4.22.0 |
| @tensorflow/tfjs-core | ^4.21.0 | 4.22.0 |
范围、resolved、integrity、已安装 manifest 哈希、适配器关键文件哈希均在 JSON。
它们约束本仓库安装,不约束消费者重新解析的依赖,也不约束默认 CDN URL。
没有查询 CDN latest、下载远程模型或从 bundle 中猜出完整历史 TensorFlow 版本。
归档中出现 MediaPipe VERSION 字符串不等于整套 SDK/模型链已经认证。
body-segmentation 1.0.2 的
dist/selfie_segmentation_mediapipe/segmenter.js 已按已安装字节冻结。它以
config.modelType 映射 general → modelSelection=0、landscape → 1;不读取
插件额外传入的 config.modelSelection/smoothSegmentation/minDetectionConfidence/ minTrackingConfidence/selfieMode。构造时 selfieMode=false;segmentPeople 的
flipHorizontal 参数另有处理,而插件未传这个参数。后续不能直接把模型参数接通
当作等价重构;需先记录效果变化及兼容决策。
该 adapter 的 locateFile 去掉 solutionPath 尾部斜线再拼资源文件名。已安装
MediaPipe JS 选择 SIMD/普通 wasm loader、graph binarypb、general/landscape tflite,
loader 再加载 WASM 等资源。插件默认目录未带 @version,Yarn 固定 JS 依赖不能
固定这条额外下载链;自定义 solutionPath 必须继续保留。
demo 指向 /assets/@mediapipe/selfie_segmentation,注释要求从 node_modules 拷贝。
仓库已存在 12 个文件,package.json 为 0.1.1675465747;冻结 Git 中全部文件与
当前 node_modules 同名文件字节一致,包括两个 tflite、两个 wasm、loader JS、
binarypb、data、README/声明/manifest。未新增或执行这些模型;这是本地字节一致性,
不是对其获取链的独立真实性认证,也不是模型输出、离线网络闭包或 GPU 释放验证。
有依据的后续风险
| ID | 已确认事实与最小触发路径 | 归属 / 证据等级 |
|---|---|---|
| MASK-LIFETIME-01 | start 等待初始化或一次推理期间 stop/destroy 不使异步工作失效;后续 continuation 仍能写 mask 并再排 RAF。没有 segmenter.dispose 或事件 off | 02 复现、03 修复;源码路径确认,尚非原生模型复现 |
| MASK-START-01 | start 无 pending/running 守卫;并发启动可重复初始化,已初始化的多次 start 可建立多条 RAF 链,只有一个 animationFrameId | 02/03;源码路径确认 |
| MASK-MODEL-01 | 插件声明/传参和已安装 adapter 实际消费不同,general 始终选择 0;零值受历史 OR 默认影响 | 02/04/05;适配器文本确认,默认/零值有受控源码测试 |
| MASK-BACKEND-01 | WebGL 仅 rejection 时 fallback;MediaPipe runtime 与 TF backend 不等同;createSegmenter rejection 被吞掉后仍能进入等待 RAF | 02/03/05;源码路径确认,真实降级未验证 |
| MASK-DOM-01 | 缺少 Danmuku、2D context 或视频可读帧时无完整前置保护;CORS getImageData 失败被 catch 后下一轮继续 | 02/03/05;需受控失败及真实浏览器复现 |
| SDK-08 | 默认无版本 CDN 与 Yarn 安装分离;本地资源一致不证明真实模型、设备、跨源、断网与资源释放 | 05/06;保持开放 |
| MASK-NOTICE-01 | 当前 SDK manifest 标 Apache-2.0;两版 plugin 归档只有六个文件,无独立第三方通知,抽查 module bundle 无 Apache/Google copyright 字面标记,顶部只有项目 MIT | 06;需核查完整嵌入来源和通知义务,不作已获授权/合规结论 |
重放与边界
使用固定 Node/Yarn 环境:
node refactor/scripts/danmuku-mask-contract.mjs
node --test refactor/scripts/danmuku-mask-contract.test.mjs
verifier 校验缓存 tarball SHA512/SHA256、全部成员/入口、原始 registry 快照、Git 来源关系、冻结 Yarn 解析与已安装 SDK/已有资产字节。缓存缺失时只从固定 npm tarball 地址恢复插件发布包。测试六项:归档关系、两版声明、八个真实 main/legacy CJS/script 导出探针、受控自有源码默认/零值/像素边界、SDK-08 证据。 导出探针执行 bundle 顶层注册但不启动模型;源码行为探针用 TF/MediaPipe 替身。 没有远程模型请求、真实推理、设备、浏览器播放、npm 安装矩阵或发布验证。