DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

AlexZhou19871030 /

dsh-plugin-eva-unit01

Verified

EVA Unit-01 desktop pet for the DSH web GUI: draggable Unit-01 overlay, NERV sync-rate HUD driven by live session state, 32 actions, and a 50-kind Web Audio synthesizer with optional drop-in real audio.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@aba0a3e9

EVA 初号机桌宠(dsh web 常驻插件)

在 dsh Web GUI 里放一只可拖动的 Q 版(Funko Pop 风)EVA 初号机,带 NERV 同步率 HUD 与一套 离散动作。纯浏览器面插件:宿主半程是空 apply,浏览器半程通过 package.json 的 dsh.client 声明被 web 服务端发现并下发。

形体(T12 起换了表现形式):机体不再是手写矢量块面,而是参考插画本身。pet-ref/slice-rig.py 把 pet-ref/reference.png 沿实测装甲缝切成 16 层刚体部件(切缝取自逐行游程间隙与颜色族连通域, 不是目测),16 层并集与描出的躯体掩膜完全相等:0 像素丢失、0 像素臆造。每层按 2 倍屏幕尺寸导出并以 data URI 内嵌,插件仍是单文件、无需资源路由。viewBox 0 0 300 340、渲染 240x272,躯体占 227.68 x 291 单位、宽高比 0.782 —— 就是参考图自己的比例。眼睛保留矢量(画在切片器补绘过的眼窝上), 情绪变色/发光/眨眼照旧;脐带电缆保留矢量,因为它必须弯折。

挂载位置与层级(不要随便改)

桌宠注册在 shell.overlay slot,但渲染内容用 react-dom 的 createPortal 投到 document.body > div.eva01-portal。这不是为了好看,是必须的:shell.overlay 的祖先 overlayLayer 是 z-index:20,而 dsh-better-sidebar 的右侧面板 .W-zNGW_panel 与底部面板 .W-zNGW_bottomPanel 都是 z-index:50 且 88% 不透明 —— 桌宠在那个层叠上下文里无论把自己的 z-index 抬到多高都会被盖住(实测 z-index:2147483000 同样无效),连点击事件都被面板吃掉。

层级取值 60,有实测依据:全页常驻层只有 toggleCluster 55 / panel 50 / bottomPanel 50, 而宿主的模态框、遮罩、toast 在 100–1100。所以 60 恰好压过所有常驻面板,又仍在所有模态类 UI 之下(报错弹窗永远盖在桌宠之上)。容器 pointer-events:none + 桌宠本体 pointer-events:auto, 保证这个全屏容器不吃任何页面事件。默认落点在左下 left:24px;bottom:84px,避开右侧面板内容; 初始朝向即镜像(is-left),与「左半边镜像」规则一致,避免第一次拖拽时凭空翻面。

交互

操作 结果
拖动 移动,限制在窗口内;窗口缩放后自动钳回视口;跨过屏幕中线整体镜像
松手 落地压扁回弹 + 低频落地音
单击 按当前情绪随机台词 + 机体回弹 + blip,34% 概率点头
双击 暴走 8 秒:蓄力 → 咆哮(下颌张开)→ 红眼、剧烈抖动、红色 AT 场、线缆火花、同步率 400%、内部电源倒计时
悬停右上 ♪ 开关音效(Web Audio 现场合成,无音频资源;不可用时静默降级)
悬停右上 – 收成小紫球,点球体恢复
什么都不做 每 7–18s 随机插一个 idle break 动作(见下)

动作系统

两层:情绪循环(永不停,float 整体浮动 13px / sway 摆头 ±5° / breathe 呼吸 1.055 / 双臂 ±7° / 线缆 ±6° / 肩甲反相 ±2° / 头侧绿鳍 ±4°(BERSERK 下改为 0.34s steps 抽动)/ 地面阴影跟随),叠加离散一次性动作。只有循环时,旁人 会觉得「没在动」——离散动作才是能被一眼看见的节拍。

共 26 个离散动作。每个动作都是「三件套」:ACTIONS 表项 + @keyframes eva01-* + .eva01-root.is-act-<名字> 选择器(注意是 is-act- 前缀,组件里拼的是 cls += " is-act-" + act)。 下表的时长/优先级/门控/权重/音效 kind 均取自 lib/client.js 的 ACTIONS 表实际值。

动作 时长 优先级 情绪门控 idle 权重 触发 音效 kind
wave 挥手 1150ms 2 idle/active/pending/tool 3 挂载 900ms 后打招呼;进入 STANDBY wave
nod 点头 780ms 2 idle/active/pending/tool 2 单击 34% 概率 nod
deny 摇头 760ms 3 任意 0 进入 ALERT deny
look 左右张望 2400ms 1 idle/pending 4 idle break look
stretch 伸展 1700ms 1 idle 3 idle break stretch
hop 原地小跳 900ms 2 idle/active/tool 3 idle break hop
walk 碎步 1100ms 1 idle/active 2 idle break step
stomp 踏步 840ms 3 active/tool/berserk 0 进入 ACTIVE / OPERATE stomp
charge 蓄力 1500ms 5 任意 0 进入 BERSERK charge
roar 咆哮 1600ms 5 berserk 0 蓄力后 1560ms 自动接上 roar
salute 敬礼 1250ms 2 idle/active 1 作业完成回到 IDLE salute
shiver 颤抖 900ms 4 任意 0 ALERT 12%(T18) —
slash 振动刀挥砍 1050ms 4 active/tool/berserk 0 进入 ACTIVE/OPERATE 25%(T18) prog
unbind 撕开口枷 1400ms 5 berserk 0 暴走链第 2 拍(1560ms,T18) jaw
guard A.T. 场防御 1200ms 4 任意 0 ALERT 18%(T18) atfield
shutdown 电源耗尽停机 1800ms 5 任意 0 暴走 8s 窗口结束(T18) lifeless
turn 原地转身 900ms 2 idle/active 2 idle break pivot
crouch 下蹲 1250ms 2 idle/tool 2 idle break crouch
scan 传感器扫视 2200ms 1 idle/pending 3 idle break look
tapcore 敲核心 1150ms 2 idle/active/tool 1 idle break poke
tiptoe 踮脚 1400ms 1 idle 2 idle break tiptoe
rebound 受击回弹 800ms 3 active/tool/alert/berserk 0 使徒计数上涨(T18) thud

T18 已组接:上表原本标「预留」的 6 个动作全部报上了真实触发点(见 T18 節);新增的 audit-triggers.cjs 闸门保证不会再出现只有关键帧、永远跑不到的动作。

互斥规则:暴走/蓄力/撕枷/停机(5) > 颤抖/挥砍/防御(4) > 情绪反应/回弹(3) > 打招呼(2) > idle break(1) > 情绪循环。 运行中的动作会拒绝优先级更低或相等的请求,所以两个动作永不争抢同一个 transform;拖拽中一律拒绝 (机体本身就是拖拽把手)。每条关键帧的 0% 与 100% 都回到 identity,class 摘掉时不会跳变。

调试触发钩子(供自动化验证用,非 UI 功能):

window.__eva01.play('hop')   // -> boolean,被情绪门控/优先级拒绝时返回 false,未知动作名返回 false
window.__eva01.actions       // 动作名列表
window.__eva01.state()       // { mood, act, drag }

音效

全部现场合成:振荡器 + 一块共享白噪 buffer 过 biquad,插件不带任何音频资源文件。 共 44 个 kind,硬约束由 tests/audio.mjs 断言:单层峰值 ≤ GAIN_CAP 0.12、单个配方 delay + dur ≤ 2s、同一 kind 的重叠峰值 ≤ 0.26,母线 BUS_GAIN 0.75。最响的仍是 roar (0.24 合计 → 出口 0.18)。设计依据与逐层理由见 SFX_RESEARCH.md。

T8 新增 15 个 kind(THROTTLE 为同一 kind 两次播放的最小间隔):

kind 语义 挂载 throttle
prog 振动刀出鞘,双高频拍频即刃振 slash 500ms
jaw 暴走前撕开口枷 unbind 900ms
battery 内部电源倒计时双响 shutdown + ALERT 周期 1000ms
pivot 髋部伺服转向,含制动卡榫 turn 350ms
crouch 液压下沉 + 落定 crouch 600ms
tiptoe 踮步,响度仅 step 的一半 tiptoe 300ms
pulse 生体心搏,S1/S2 强弱不等 呼吸循环重音周期 1400ms
s2 S² 機関驻留,55/56.5Hz 拍频=双螺旋 BERSERK 周期 6000ms
umbilical 三点式插头就位 + 送电涌入 待接 800ms
unplug 电缆断开 → 切内部电源 待接 900ms
atburst A.T. 场碰撞显形,3:2 双环鸣 待接 400ms
lcl Entry Plug 注液 + 电解 待接 3000ms
lifeless 电源耗尽停机,末声钝 240Hz 待接 2000ms
magi MAGI 三体多数决,全表最轻 待接 700ms
sync 同步率分级建立,四级台阶 待接 1200ms

三个状态型音效不走 ACTIONS[x].sound,而是在情绪层周期请求、靠 THROTTLE 自然限流: battery 在 ALERT 下每 0.9s 请求一次、1s 节流 → 实际约 1.8s 一响;s2 在 BERSERK 下每 0.9s 请求、6s 节流 → 约 6.3s 重新起一次驻留;pulse 每 1.5s 请求,BERSERK 每次都过(心率飙升), 其余情绪过 35% 概率门 → 平均约 4s 一拍,ALERT 下让位给电池倒计时。

标「待接」的 7 个已实现并通过全部断言,只是还没有触发点(与早前的 power / hum 同一处理方式)。

状态联动

情绪读自两个来源:shell.overlay 标准 prop useSessions(会话列表:谁在跑、谁在等你),以及当前会话的对话装配——插件自己用客户端 sessions 服务把 sessions.binding(current).session 的 ConversationSnapshot 订阅下来。同步率每 0.9s 向目标值收敛:

情绪 触发 目标同步率 HUD
IDLE 其余 60 UMBILICAL LINKED / TOOL n
ACTIVE 当前会话 running,或存在任意 running 会话 88 ACT n / TOOL n
STANDBY 当前会话有 pendingInteraction(等你授权/回答) 71 —
OPERATE 当前会话有正在执行的工具调用 94 OP <工具名>
ALERT 当前会话出现新的 agent 错误 33 ⚠ PATTERN BLUE ×n
BERSERK 双击 400 PWR mm:ss

优先级:BERSERK > ALERT > OPERATE > ACTIVE > STANDBY > IDLE。

派生规则(readFeed):

  • TOOL n —— 窗口内 tool-result 节点数 + 当前在跑的调用数。
  • ⚠ PATTERN BLUE ×n —— 失败的 tool-result(isError)与 turn-error 节点计为「使徒」。
  • ALERT —— 由 lastAgentError 文本变化驱动,警报持续 8 秒后自动解除并播报「使徒歼灭」。订阅建立时读到的那条错误只作基线,不报警,所以刷新页面不会为历史失败拉响警报。
  • 流式 token 不触发重算:feedSig 只在节点数、在跑调用、错误文本变化时才重新折叠快照。

安装

dsh plugin --profile web add link:E:/DSH/plugins/eva-unit01

该命令会同时把包名追加到 profile package.json 的 dsh.profile.bundles。bundle 列表在启动时 读取,需要重启 dsh 才生效。

验证组合树(不启动应用):

dsh --profile web --dump-config

测试

node tests/smoke.mjs

用假的 window.__ModuleLoader__ 与假 useSessions 快照,跑真实 React 渲染。覆盖:

  • 模块形状、导出、样式表只插一次、Slot 注册参数、inject 含 slots 与 sessions;
  • readFeed 快照折叠 6 例(空会话、落地工具计数、失败工具与 turn-error 计为使徒、在跑调用取名并计数、错误文本、未知形状降级为空);
  • feedSig 的流式抑制:同一节点集下 partial 变化不重算;
  • subscribeFeed 真实订阅路径:首读作基线、后续变化上报、token-only 变化不重复通知、disposer 解绑、无 sessions 服务降级、binding() 抛错降级;
  • moodOf 六档优先级,且标签与同步率互不重复;
  • Hud 七种状态的实际标记(OP <工具名>、TOOL n、ACT n、⚠ PATTERN BLUE ×n、PWR mm:ss、进度条宽度);
  • 4 种会话快照的整机渲染,以及 apply() 注册的 overlay 入口能真实渲染;
  • 样式表里每个情绪态都有对应状态规则,避免加了状态却没有视觉。

SSR 不跑 effect,所以 OPERATE/ALERT 的验证走两条可测缝:订阅逻辑用假 session face 直接驱动, HUD 标记用独立的 Hud 组件按状态渲染。

设计说明:为什么不走宿主事件

早期动态插件版本用宿主 agent/error 与 tools/result 事件驱动 ALERT 与 TOOL 计数。常驻插件的 浏览器半程没有动态包那种 Package 私有 host.call 通道,而 @deepseek-ai/dsh-api-remotes 的转发 白名单(API_REMOTE_FORWARDED_EVENTS)是构建时固定的、不含这两条事件——不改动 deployment 自带的 安装就加不进去。

但这两项能力不需要宿主通道:浏览器本来就持有当前会话的完整装配。ConversationSnapshot 直接带 nodes(含 tool-result / turn-error)、runningCalls 与 lastAgentError,所以改成从客户端 快照派生,反而比事件驱动更好:

  • 刷新页面后计数不丢(快照是权威,不依赖曾经收到过哪条事件);
  • 能显示当前正在执行的工具名,事件计数做不到;
  • 零宿主侧改动,宿主半程仍是空 apply。

代价:计数限于当前加载窗口内的节点(loadOlder 之前的历史不计入)。

T12:表现形式换轨 + 通知层(本轮)

1. 为什么换成贴图骨架

手写矢量追插画追不上:换轨前用同一像素管线量测,桌宠 vs 参考图是 aspect 0.912/0.782、头高占比 45.0%/35.5%、头宽高比 1.656/1.874、颈线 0.449/0.354 —— 四项全偏,而且每改一次都要重打上百个 路径坐标。改成「切参考图」后,比例不再需要调:等比贴图天然带着参考图的比例。

2. 验收数据(pet-ref/compare-fidelity.py,双图同一管线,不用硬编码常量)

指标 参考图 桌宠渲染 判定
宽高比 0.782 0.782 OK
头宽占比 85.14% 85.24% OK
头高占比 35.55% 35.67% OK
头宽/头高 1.874 1.869 OK
颈线位置 0.354 0.355 OK
轮廓 IoU — 0.9908 形状即参考图

measure-pet.py 里那组 REF 常量已被证伪:它的 legsplit_frac 0.744,用同一管线量参考图自己 得到的是 0.998 —— 该指标本身不可用,已改由 compare-fidelity.py 现场量测双图。

3. 关节表(由切片 bbox 导出,CSS transform-origin 与之一致)

部件 关节 部件 关节
head 150,122.7 jaw 162.8,122.7
chest 168.6,241.6 inner 150,317
armL 112,166 armR 227,166
legL 104,241.6 legR 228,241.6
pylonL 105,142 pylonR 220,142
finL 115.2,69.5 finR 228.3,69
greaveL 100,267.2 greaveR 233,269.1
footL 98,293.3 footR 240,304
core 165,166.2 — —

4. 气泡与提示音(三态 + 两声)

时机 气泡 音效 说明
工作中(进入 ACTIVE) LINES.active 随机 up + sync 原有
工作中(进入 OPERATE 工具调用) LINES.tool 随机 magi 新增:此前直接进工具态时桌宠一言不发
需要授权(STANDBY) LINES.pending 随机,5.2s authreq 新音效:G6→C7 上行四度问句,问两遍 + G5 尾音
任务结束(回到 IDLE) LINES.done 新池 5 条 taskdone 新音效:C6-G5-C5 下行终止式 + 八度铃
闲时 LINES[mood] blip 定时器改为 26-46s 自重排(原先固定 46s 像节拍器)

任务结束的动作节拍改为 45% cheer / 55% salute,避免连续完成时一直敬礼。down 音重新接到 警报解除(下降双音正是「降级」语义),音效接线审计因此回到 44 kinds / 44 已接线。

5. 暴走态色彩处理(依据第二张参考图的实测配色)

第二张暴走参考图是满幅插画(白底仅 0.3%,血红背景 #da3533 占 12.7%),抠不出干净的角色掩膜 (试得的掩膜填充率仅 0.52 且贴到画面底边),因此本轮不切第二套贴图,只取它的权威配色做色彩分级: 角色主紫实测 #393172(平时 #5e369c)、灰 #616371、绿 #4a8850、暗部 #201e2a。落地为 .eva01-root.is-berserk .eva01-inner{filter:brightness(.76) saturate(.88) contrast(1.14) drop-shadow(0 0 9px rgba(216,53,51,.55))} —— brightness(.76) 把 #5e369c 压到约 #472a76, 红色投影补上背光;眼色与 A.T. 场原本就走 --eva-* 变量切换。

6. 新增 4 个动作 / 3 个音效

finflare(鳍片外张,1300ms,音 plate)、armcross(双臂交叠,1400ms,音 latch)、 lookback(回望:眼先动 → 头转 → 鳍延迟 → 电缆最后跟,2000ms,音 pivot)、cheer(跃起举臂, 1300ms,音 comms)。三个新音效按 SFX_RESEARCH.md 的分层规则(瞬态 → 本体 → 尾音)推导。

7. 本轮的诚实边界

  • 本机 web_search 未配置 DEEPSEEK_API_KEY,本轮没有任何新的联网来源;新音效是声学推导而非引用。
  • 本机模型无图像输入(describe_image 插件 baseURL 无效、modlens 超时),所有形象判断都是像素统计, 不含任何「我看了一眼觉得像」。视觉终审仍需你本人看一眼 GUI。
  • 暴走形象目前只是色彩分级 + 既有开颌/獠牙/抖动,不是第二套贴图;要复刻那张图的姿态,需要一张 白底或透明底的暴走立绘。

T13:切片没扣干净的修复(用户报告)

用户截图指出机体带白斑/白边。查证后是切片器 v1 的两个真实缺陷,不是渲染层问题:

缺陷 成因 证据 修复
胸口一块白斑 v1 对躯体掩膜用了 binary_fill_holes,把「近臂与躯干之间被围住的白色背景空隙」当前景填了进去 chest.png 内含 54x71 纯白实心块,2189 px,均值 RGB(254,254,254) 不再填洞;只补 <=8px 针孔,6 处真实空隙保持透明
一圈白毛边 白底判定 min(rgb)>238 太窄,白页与黑轮廓之间的反锯齿过渡行被算成躯体 贴图边缘近白像素占 4.8%(legL 11.6%、eyeL 11%) 近白判定放宽到 min(rgb)>225 且按连通域判定页面,再对 alpha 内缩 1px 丢掉混合行

修复后量测(slice-rig2.py 自带审计):

指标 v1 v2
边缘近白像素占比 4.8%(650/13422) 0.1%(18/18942)
单层最大白斑 2189 px 0 px
半透明边缘中的近白 — 0.47%(19/4053)
不透明近白像素 — 0
合成到 GUI 面板 #081840 后的亮边像素 — 16 层全部为 0
轮廓 IoU 0.9908 0.9880(1px 内缩的代价,5 项比例仍全 OK)

体积同时下降:base64 278KB -> 265KB,client.js 408,698 -> 395,758 字节。 回归:tests/audio.mjs 3597 断言、tests/smoke.mjs、audit-classes、t7-crosscheck.mjs 902 断言全过。

T13b:脸上被啃出透明缺口(用户第二次报告)

用户报告头部出现应为黑色却透明的区域。查证:v2 掩膜共 6 个洞,其中 5 个在脸上 (最大 985 px,x209-244 / y255-297,原图均值 RGB(142,54,116) —— 实心美术),只有 1 个 (x380-468,RGB 249,249,249)是真背景空隙。

成因是 v2 里那段颜色键剔除红色 CJK 文字块的代码:(R>200)&(G<70)&(B<70) 同时命中了角色脸上的 亮红高光(#c8262c 的 R 正好 200),再经 5x5 两次膨胀,就在高光四周啃掉约 4px 深的一圈。 而红字块本身是独立连通域,取最大连通域时天然被排除 —— 那段剔除逻辑纯属多余。同时移除了 binary_opening,它会啃细线条美术。

新增不变量(这条断言本可以第一时间拦住上面的 bug,现已内建):每个保留为透明的洞,其原图颜色 中位数必须是近白页面(min 通道 > 225),否则直接 SystemExit 拒绝导出。

指标 v2 v2b
掩膜中的洞 6(5 个是美术) 1(全部为背景,通过颜色不变量)
头部内部「暗色美术被透明」 存在 0 px
躯体像素 139,358 141,568(回补 2,210)
边缘近白像素 0.1% 0.1%(未回退)
轮廓 IoU 0.9880 0.9881

回归:audio 3597 断言、smoke、audit-classes、t7-crosscheck 902 断言全过;线上 bundle 400,421 字节。

T14:暴走正典动作集(AT 力场 / 持枪 / 振动小刀 / 出击 / 殴打使徒)

1. 五个新动作

动作 时长 优先级 情绪门控 触发 音效 动作要点
atopen A.T. 力场展开 1800ms 4 idle/active/tool/alert/berserk 暴走链第 3 拍;play() atfield 双臂前推、六边形力场 0.74→1.04 张开、机体后撑、眼闪 1.2x、鳍片外张 18 度
gunfire 持枪射击 2000ms 4 alert/berserk/active/tool ALERT 40% rifle 举枪→三连发(枪口焰 + 机体后座 5px + 右腿撑步)→收枪
knifedraw 抽振动小刀 1700ms 4 alert/berserk/active/tool ALERT 35% deploy 右肩甲开启 13 度 → 手伸向肩后 → 刀现 → 一记斩击
sortie 出击 1600ms 3 idle/active/tool 进入 ACTIVE/OPERATE 35% launch 深蹲蓄力(压扁 1.06/0.9)→ 弹射上冲 26px(拉伸 0.93/1.09)→ 两段落地
beatdown 殴打使徒 2200ms 4 alert/berserk 暴走链第 4 拍 punch 四记交替重拳,髋部先转带动出拳,命中帧地面火花

暴走链改为正典顺序:charge(0) → roar(1560) → atopen(3160) → beatdown(4960),末尾 7160ms, 仍在 8 秒暴走窗口内;每次交接都等上一动作结束,不会有两个动作抢同一个 transform。 ALERT 不再只是摇头:40% 持枪 / 35% 抽刀 / 25% 保留原摇头。

2. 两件手绘矢量道具

参考图里没有武器,所以枪与刀是手绘矢量(不是切片),挂在 eva01-armR 组内随臂运动, 平时 opacity:0,只在自己的动作里显形:

  • eva01-rifle 托盘式步枪:机匣 + 顶部受光棱 + 枪口块 + 弹匣,另有 eva01-flash 枪口焰
  • eva01-knife 振动小刀:刀身 + 刃口高光 + 刀柄
  • eva01-hit 命中火花两片,放在 inner 层而非手臂组,所以不会随拳头一起旋转

3. 声画对齐(这轮特意校过,不是凑巧)

事件 动画命中帧 音效层延迟
枪火第 1 发 12% × 2000ms = 240ms rifle 层 delay 0.24
枪火第 2 发 26% = 520ms delay 0.52
枪火第 3 发 40% = 800ms delay 0.80
重拳第 1 击 20% × 2200ms = 440ms punch 层 delay 0.44
重拳第 2 击 50% = 1100ms delay 1.10
重拳第 3 击 82% = 1804ms delay 1.804(+0.16 时长,刚好卡进 2s 上限)

4. 四个新音效(合成参数)

kind 语义 配方要点 throttle
rifle 托盘枪三连发 每发 = 90→45Hz 方波 0.12s(0.075)+ 300Hz 低通噪声(0.05)+ 4.2kHz 高通脆响;间隔 280ms,是慢速重炮而非连发 900ms
launch 弹射轨道 40→120Hz 正弦 0.9s(attack 0.2)+ 600→1800Hz 低通噪声 0.85s + 卡榫方波 + 风噪尾 1600ms
punch 三记重拳 130→50Hz 正弦 0.16s(0.085)+ 420Hz 低通(0.045)+ 5kHz 高通爆点,逐击衰减 180ms
deploy 抽刀 5kHz 高通瞬态(锁扣)+ 300→1200Hz 锯齿滑出(刀身)+ 2400/2412Hz 双正弦驻留 —— 12Hz 拍频即刃振 600ms

5. 闸门抓到并修掉的两个真问题

  1. eva01-atHex 与 eva01-beatHit 的 0%/100% 不是 identity(scale(.72)/scale(.6)),违反 「class 摘掉不得跳变」的不变量 —— 已把缩放挪到内部帧,首尾恢复 scale(1)。
  2. atopen 起初给了 idle 权重且门控含 alert/berserk,使警报态与暴走态混进了闲时随机池 (危机中不该摸鱼)—— 改为 idle: 0,仍可由暴走链与 window.__eva01.play() 显式触发。

回归:audio.mjs 4054 断言 / 48 kinds、smoke.mjs、audit-classes、audit-sfx-wiring、 t7-crosscheck.mjs 1133 断言 / 31 动作 / 180 组关键帧 全过;轮廓 IoU 0.9881 未受影响 (渲染 harness 已同步剥离武器与火花图层,否则会污染轮廓量测);线上 bundle 415,482 字节。

6. 仍未做到的

  • 暴走形态依旧是色彩分级 + 开颌獠牙 + 抖动,不是第二套贴图:那张暴走图是满幅插画,抠不出 干净掩膜(见 T12 第 5 节)。要真正复刻其姿态,需要白底或透明底立绘。
  • 音效仍是按声学与既有 SFX_RESEARCH.md 体例推导;本机 web_search 无凭据,本轮依然没有新的 联网正典来源,不要把上表当作引用。

T15:补上联网检索能力,并把正典音效调研补做完

1. 能力从哪来(没装插件也能用)

根因是 dsh 进程带着一个已死的代理(127.0.0.1:7897):api.github.com 走它 rc=7 拒连、 走 33210 或直连都是 200。所以 web_search(还缺 key)与 find_dsh_plugin(返回空列表) 都不是坏了,是被掐住。

新增 E:\DSH\tools\websearch.py:自动探测可用路由(33210 → 7897 → 7890 → 直连), 走 DuckDuckGo HTML 端点,零 API key、零第三方依赖(纯标准库)。三个子命令:

python E:\DSH\tools\websearch.py search "query" [n]
python E:\DSH\tools\websearch.py fetch  "https://..." [chars]
python E:\DSH\tools\websearch.py github "topic query" [n]

2. 可选插件(真实检索结果,按星数)

插件 星 要点
liustack/modsearch 107 一条命令接管 dsh 内置 web_search;默认引擎 Antigravity CLI 免密钥(浏览器登录),Tavily/Exa/Firecrawl 免费额度做失效转移
anysearch-team/anysearch-dsh 54 AnySearch 搜索 provider + 进阶检索工具
anweat/dsh-web-search-pro 12 多引擎 + SQLite 持久缓存
gxpppp/dsh-search-mcp 10 用 MCP 服务器(Tavily/Brave/Exa/Perplexity/DuckDuckGo)替换内置搜索

注意:装任何一个都改不了根因 —— 插件跑在 dsh 进程里,同样会走那个死代理。 顺序应为:先跑 E:\DSH\fix-uv\apply-uv-fix.ps1 修代理端口 → 重启 dsh → 再装插件。

3. 调研成果与对音效的实际改动

详见 SFX_SOURCES_T15.md(每条结论带来源链接)。三处实现改动:

改动 依据 具体参数
roar 重做为「放慢的人声尖叫」 初号机嘶吼实为林原めぐみ的尖叫放慢(EvaGeeks 13988 / Reddit 多源) 删掉 1400→300Hz 合成器扫频层,改为两条同步下行高 Q 带通(760→420Hz Q6、1250→700Hz Q8)叠在 300→78Hz 锯齿上 + 呼吸尾音;合计峰值 0.24 → 0.187
新增 plugsuit 皮革褶皱音 Khara 官方揭露驾驶服音效来自一只 Madison Square Garden 皮质运动包 1500→700Hz 带通 + 3.8kHz 高通颗粒 + 2600→1400Hz 二次揉捏;接在拖拽起手,grab 之后
deploy 刃振提频 EvaWiki:刀身以极高频振动,收纳于左肩甲 驻留双音 2400/2412Hz → 3200/3214Hz(拍频 14Hz,从「嗡」变「嘶」);并确认 knifedraw 用右侧肩甲即 Eva 的左肩,方向与正典一致

仍无权威来源的项(A.T. 力场音、弹射音、托盘枪音)继续标注为声学推导,不冒充引用。

T16 更新:其中 A.T. 力场音 与 托盘枪音 已在 T16 找到来源并落地(见下一節与 SFX_SOURCES_T16.md);弹射音仍无来源。

回归:audio.mjs 4132 断言 / 49 kinds、smoke.mjs、audit-sfx-wiring、 t7-crosscheck.mjs 1133 断言 全过。

T16:把「无来源」的音效追到底 + 第一次真正的视觉终审

1. 先修能力,再干活

上一轮的两个硬限制本轮都没了:代理从死掉的 127.0.0.1:7897 改到 33210(用户级 环境变量已改,dsh 重启后继承),websearch.py 因此能真的联网;图片理解(describe_image) 配好了 Ark /api/v3 + doubao-seed-1-6-250615,实测可读图 —— T12/T14 反复声明的 「本机模型无图像输入,视觉终审仍需你本人看一眼」这条限制,本轮第一次可以自己做了。

2. 视觉终审:确认无瑕疵,但也确认了「不能听视觉模型讲细节」

把 pet-ref/pet-shot.png(桌宠渲染)与 pet-ref/reference.png(参考插画)分别交给视觉模型, 同一套提问(对象数、姿态、比例、颜色分区、瑕疵、面部细节):

项目 结论
白斑 / 白毛边 / 透明缺口 / 断肢 / 贴图接缝 两图都报「未观察到」 —— T13/T13b 的修复第一次得到独立于像素统计的确认
姿态与颜色分区 两图描述几乎逐条重合(紫色主体、绿色鳍/肩/膝/小腿内侧、红色眼上三角、黄色眼与膝块)
头身比 都判为 Q 版、头约占全高 1/3 —— 与 compare-fidelity.py 的 35.55% / 35.67% 一致

但视觉模型对细节给出了两条矛盾描述:说桌宠眼睛是「圆形、无瞳孔」、参考图是「横向椭圆、有黑色瞳孔」, 还说桌宠嘴是「咧嘴」、参考图是「闭合」。这两条被像素测量证伪(黄色连通域 bbox 与域内暗像素占比):

眼部黄色连通域 参考图 桌宠渲染
左眼 w/h 0.840 0.812
左眼域内暗像素占比(瞳孔) 0.390 0.380
右眼 w/h 1.278 1.364
右眼域内暗像素占比 0.214 0.210

两图的眼形比例与瞳孔占比几乎相同,桌宠是有瞳孔的,也没有哪一只眼睛是「横向椭圆 vs 圆形」的差别。 所以本轮没有按那两条描述改任何形状 —— 视觉模型可用于「有没有明显瑕疵」这类整体判断, 它的细节措辞不能当量测用。

3. 音效来源:一条真改动,一条认输

完整来源与摘录见 SFX_SOURCES_T16.md。

kind 本轮结果
atfield 补上来源(EvaGeeks 13974 的「像 binaural beats」听感)→ 加 220/226Hz 一对正弦,6Hz 拍频;标注为社区听感,非制作来源
rifle 有正典依据的重做:EvaWiki 给出托盘枪 = Type MM-99 大口径自动步枪、造型取自 Steyr ACR、ACR 用 flechette 钢镖弹 → 三连发间隔 280ms → 110ms、本体 0.12s → 0.09s、每发各带 5.2kHz 钢镖瞬态(原先只有首发一次 4.2kHz);低频本体保留(「大口径」是正典)
roar 拿到第三个独立佐证(thread 13574:「录一个人尖叫再把频率放慢」;且咆哮被放在对白轨,英配需重录)—— T15 的实现无需再改
launch / punch / atfield 的制作来源 没查到。两条专问弹射音的查询被 DuckDuckGo 限流返回空,EvaWiki 无音源说明 → 继续标注为声学推导,不冒充引用

新的工艺定位(写死在文档里):论坛一手结论是 NGE 的 TV 版音效「以现成音效库 + 混音为主」, 音响制作方为 "Audio Tanaka"。原作没录真物、我们也没录真物,所以本插件的音效永远只能是声学推导, 任何时候都不写成「复刻正典音源」。

声画对齐随之 retime(T14 第 3 节的规矩):枪火三帧 12% / 17.5% / 23%(240 / 350 / 460ms) = 音效层 delay 0.24 / 0.35 / 0.46;eva01-gunFlash / eva01-gunBody / eva01-gunArmR 三组关键帧一并改,首尾仍是 identity。

4. 顺手修掉的文档缺陷

README 里 T12 章节整段重复了两次(2590 字符逐字相同,应是上一轮 patch 的编辑事故)。 本轮删掉第二份,删除前先断言两段完全相同才动手。

5. 回归

audio.mjs 4196 断言 / 49 kinds、smoke.mjs、audit-classes(180 组关键帧、0 处缺 0%/100%)、audit-sfx-wiring、t7-crosscheck.mjs 1133 断言 / 31 动作 全过。 rifle 新增两层后单层峰值仍 ≤ 0.12、三发窗口互不重叠(0.24–0.33 / 0.35–0.44 / 0.46–0.55)。

6. 仍未做到的

  • 暴走第二套贴图依旧没做:那张暴走插画是满幅背景(白底仅 0.3%),抠不出干净掩膜(T12 第 5 节), 现在图片理解虽然能用了,但它给不出掩膜,只能给描述 —— 缺的是一张白底/透明底暴走立绘。
  • launch / punch 的正典来源仍缺;下一轮可追 "Audio Tanaka" 与 EvaGeeks thread 21607 (本轮抓到的正文只有提问,没有答复)。
  • 6 个「预留」动作(shiver / slash / unbind / guard / shutdown / rebound)与 5 个「待接」音效(umbilical / unplug / atburst / lcl / lifeless)仍没有自动触发点。

T17:按两张参考图改暴走与 A.T. 力场(音效跟着动画走)

用户给了两张图:图 A 是初号机 Funko 手办实拍(深蓝近黑背景占 80%,手持红色长枪), 图 B 是暴走形态插画(红底)。

1. 先说两个如实结论

两张图里都没有 A.T. 力场。 视觉模型对两图分别独立回答"未出现力场",图 A 的颜色直方图前 12 位 全是 #000818/#081020 一类近黑(背景),也没有任何几何叠加的迹象。所以本轮 A.T. 力场的改法 依据不是这两张图,而是荧幕上的多层六边形障壁表现,这一点必须写清楚。

图 B 依然抠不出干净掩膜,第二套贴图继续不做。 这次是量出来的,不是感觉:

量测项 值 含义
红背景像素占比 38.9% 视觉模型说的"纯红背景 100%"是错的
颜色键后最大前景连通域 占全图 61.1% 不是角色,是"非红色的所有绘画"
掩膜 bbox 710x734=整幅 上/下/左三条边命中率 100%
掩膜填充率 0.611 与 T12 那张(0.52)同类,满幅插画
掩膜内的洞 27 个,最大几个中位色 RGB(216,56,57) 洞是背景,颜色不变量这条仍然守住

所以暴走形态改成矢量叠加(贴在既有 16 层贴图骨架上),不是切第二套图。

2. 图 B 落地成 5 个新部件

掩膜内实测配色(这次量的是掩膜内部,不是整幅):紫 #463c75、绿 #559e57、 黑色外露组织 #15151a 占身体 28%、红 #892426、白 5.6%(獠牙与高光)。

部件 依据(图 B) 实现
eva01-horn 头顶独角 "紫色,尖端蓝色,垂直向上" 头切片顶边 y=26、脸部中线 x=164.7(双眼中点),独角根部 y=35 → 尖端 y=3;主体 #463c75 + 蓝尖 #3244b8;进入暴走时 hornrise 从 scaleY(.05) 弹出
eva01-fangs 双排獠牙 "上颚 4 颗突出白色獠牙,下颚 6 颗较短,内侧细密锯齿" 原先是一条锯齿路径(表达不了两排不同长度)→ 改为上排 4 长牙 + 下排 6 短牙 + 一条 45% 透明的细锯齿带
eva01-eyeslit + eva01-eyevein "狭长三角形眼、亮黄、眼内红色竖纹" 圆眼窝保留(它持有发光与眨眼 transform),CSS 在暴走下压到 opacity .35,让狭长三角 + 红竖纹主导
eva01-tail 尾巴 "从躯干后方延伸、向下弯曲约 120°、黑色鳞片组织" 填充矢量 #15151a + 虚线鳞纹,根部 (203,250) 为 transform-origin,tailsway ±8° 摆动
eva01-hunch 前倾深蹲 "躯干前倾约 25°、膝约 90°、压迫感" 新建包裹组承载这个姿态,因为 shake / roar / breathe / 各动作已经各自占用了 figure / head / chest / stage 的 transform —— 新类零冲突,不违反"两个动作不争抢同一 transform"

暴走色彩分级也按实测重标:brightness(.76) saturate(.88) → brightness(.8) saturate(.93) (#5e369c → #463c75 的亮度比实测为 0.81),红色投影加到 10px。开颌幅度从 translateY(12px)/8° 加到 19px/13°,配合两排獠牙。

3. A.T. 力场:三层障壁 + 边缘发光

从 2 层六边形加到 3 层(新增内环 h3,顶点为外环对中心 (150,170) 的 0.72 倍缩放), 三环点火间隔 180ms,is-act-atopen 下给六边形加 drop-shadow(0 0 7px var(--eva-field))。

一开始我把两个新环写成 animation-delay 修饰规则,被 t7-crosscheck 拦下:它要求每条 is-act-* 规则自己声明 animation(否则可能是永不生效的空规则)。这条闸门是对的——改成完整 animation:eva01-atHex 1.8s ease-out .18s/.36s 1 both 简写,语义更明确,闸门也不用放水。

4. 音效跟着动画改

改动 对齐关系
atfield 新增两条 2.6kHz 障壁锁定瞬态,delay 0.23 / 0.41 三环点火帧=各自 atHex 的 3% × 1800ms = 54ms,加上 .18s / .36s 的层延迟
进入暴走时除 pulse 外追加 plate 独角弹出(hornrise 0.62s)需要一声装甲板锁定
jawchomp 幅度加大 咬合音 jaw 的既有节奏不变,但视觉张口幅度与之匹配

5. 验证(含一条以前做不到的)

5 道闸门:audio.mjs 4230 断言 / 49 kinds、smoke.mjs、audit-classes(183 组关键帧、 0 处 CSS 引用未赋值、0 处缺 0%/100%)、audit-sfx-wiring、t7-crosscheck.mjs 1145 断言 全过。

暴走分支第一次真被渲染并看过:smoke.mjs 覆盖的 4 种情绪都不含暴走(它由双击驱动,SSR 派发不了 事件)。本轮新增 pet-ref/render-berserk.mjs:在内存中的 bundle 副本里把 react.useState(false) 翻成 true(磁盘文件不动),渲染出 berserk-render.html,用 vision_html_screenshot 栅格化,再交给视觉模型逐项确认:

独角在、主体紫尖端蓝;嘴张开、两排牙且上排明显更长;眼睛狭长黄色、中间有红色竖纹; 右下方有向下弯曲的黑色尾巴;无部件错位、无漂浮碎块、无穿模、无截断。

6. 仍未做到的

  • 图 B 的姿态(前倾 25°/深蹲 90°)只能用一层包裹组的轻微倾斜+压缩近似,Q 版贴图骨架没有髋膝的 真实关节自由度;要真复刻那个姿势仍然要第二套贴图,而第二套贴图要一张白底或透明底的暴走立绘。
  • A.T. 力场仍无正典音源来源(T16 只拿到"像 binaural beats"的社区听感),视觉上的多层六边形也 只是荧幕表现的复述,没有设定集出处。

T18:6 个「预留」动作全部接上真实触发点(并加一道防复发闸门)

从 T7 起,shiver / slash / unbind / guard / shutdown / rebound 六个动作 表项、关键帧、选择器、音效全都齐了,但组件里没有任何自动触发点,idle 权重也是 0 —— 只能靠 window.__eva01.play() 手动放。本轮全部按会话语义接上。

动作 新触发点 为什么是这个语义
unbind 撕开口枷 暴走链第 2 拍(1560ms) 正典顺序是先崩开束缚再嘶吼。链改为 charge(0) → unbind(1560) → roar(2960) → atopen(4560),末尾 6360ms,仍在 8s 暴走窗口内
beatdown 殴打使徒 从链尾移出 → 暴走中挨打时反击 把它塞回链里会到 8560ms,超窗;而"挨一下打回去"本来就是它的语义
rebound 受击回弹 使徒计数上涨(失败工具/turn-error 增加),非暴走态 挨打就该回弹;门控补上 alert,因为新错误通常正好把情绪推进警报态
guard A.T. 场防御 ALERT 18% 警报里除了开枪抽刀,也该有防御
shiver 颤抖 ALERT 12% 驾驶员十四岁
slash 振动刀挥砍 进入 ACTIVE/OPERATE 25% 一次工具调用就是机体切进去干活
shutdown 电源耗尽停机 暴走 8 秒窗口结束的那一刻 窗口到期=内部电源耗尽,正是这个动作画的东西(音效 lifeless)

ALERT 的答复分配从「40/35/25」改为 34% 持枪 / 28% 抽刀 / 18% 防御 / 12% 颤抖 / 8% 摇头; 进入作业态从「35% sortie / 65% stomp」改为 30% sortie / 45% stomp / 25% slash。

新闸门:pet-ref/audit-triggers.cjs

只补触发点不够——这种"有关键帧、永远跑不到"的状态必须变成装不进去的。新审计解析 ACTIONS 表,要求每个动作要么有 idle 权重,要么在组件里出现显式触发(playAction("x") 或三元里的动作名), 否则退出码 1。调试钩子 window.__eva01 那段被排除在外:它是测试缝,不是桌宠自己的行为。

这道闸门自己也被验证过(负例测试):把 T18 的四处触发改回旧写法后跑同一个审计,退出码 1, 并且精确点名:

TRIGGERS FAILED: unreachable actions (keyframes but no way to run): shiver, slash, unbind, guard, shutdown, rebound

一个不会失败的闸门等于没有闸门,所以这条负例是本轮交付的一部分。

回归(现在是 6 道)

闸门 结果
audio.mjs 4230 断言 / 49 kinds
smoke.mjs 4 情绪整机渲染 + 6 例折叠 + 7 种 HUD
audit-classes 183 组关键帧,0 处 CSS 引用未赋值
audit-sfx-wiring 49 kinds 全接线
t7-crosscheck.mjs 1145 断言 / 31 动作
audit-triggers.cjs(新) 31 个动作全部可达:17 个 idle 驱动 + 14 个显式触发

上表也把 README 前面那张动作表里 6 行「预留」改成了真实触发点——那张表声明"取自 ACTIONS 表实际值",就不能留着过期的话。

仍未做到

  • 图 A 里那把红色长枪(朗基努斯之枪)还没做:现有手绘道具只有托盘步枪与振动小刀,加第三件道具 是独立一轮的活。
  • launch / punch 的正典音源仍缺(T16 已认输,两条待追的线索没变)。
  • 暴走第二套贴图仍缺白底/透明底立绘(T17 已量测证明现有两张图都抠不出干净掩膜)。

T19:朗基努斯之枪(第三件手绘道具)

图 A 里初号机手上那把红色长兵器就是朗基努斯之枪。这轮把它做成第三件道具,正典事实来自 EvaWiki《Spear of Longinus》https://wiki.evageeks.org/Lance_of_Longinus:

正典原文 落地
"an extraterrestrial artifact with the power to penetrate any A.T. Field" 优先级给 5(和暴走各拍同级):能穿透任何 A.T. 场的东西,不该被日常动作打断
"resembles a long red bident on a scale matching the size of an Evangelion" 双叉,不是单尖;杆长 175 单位(viewBox 0 0 300 340 里从拳心到尖端)
"Its structure is double-helical" 主杆两侧各一条明/暗螺旋股(#d98a80 / #4a0f1c)
"When thrown at ... Arael, the tines wrap together" 投掷是它的正典用法 → 动作是一记长突刺,不是挥砍

红色不是猜的:从图 A 的红色连通域里量出来的 —— 中位 #7b2130、85 分位亮部 #ab5b55 (图 A 是暗背景实拍,所以整体偏暗)。视觉模型说"枪头内侧有绿色宝石",但量出来的绿色连通域都在 机体的绿装甲位置,没有证据,所以没做。

动作与声画对齐

lance 2000ms / 优先级 5 / 门控 alert+berserk+active+tool。举枪(14%) → 螺旋起转 → 突刺(31%) → 收势。音效 spear 新增:5.4kHz 锁定瞬态 + 1180/1194Hz 双音(14Hz 拍频=双螺旋) + 900→2100Hz 低通挥动 + 命中层 delay 0.62 = 31% × 2000ms = 620ms,与 T14 定的规矩一致。

触发点:第三只使徒还站着的时候(feed.angels >= 3)投枪 —— 依据是"穿透任何 A.T. 场、 别的都不管用时才拿出来";暴走态仍然用拳头(beatdown)。

视觉复核抓到并修掉的两个真问题

新道具第一版通过了全部 6 道闸门,但渲染出来一看就是错的:

  1. 枪尖和螺旋股整段看不见。 原因不是画错了,是图层顺序:inner 组里 head 排在 armR 之后,而我把枪指向左上 (x110-143, y30-66),正好落在头部切片的 bbox(x68-261, y26-122)里 —— 被头盖住了。视觉模型报"单尖、没有螺旋"就是这个原因。改为指向右侧空白边距 (头右缘 x=261,枪尖落在 x272-298)后,双叉立刻出现。
  2. 螺旋股仍然读不出来。 这是几何问题,不是审美问题:二次贝塞尔离弦的最大偏移约等于控制点 垂距的一半,原来 ±10 的控制偏移只让股线离弦 ~5 单位,而主杆半宽 3.5 —— 基本埋在杆下。 弦 (252,258)→(285,86) 的单位法向是 (0.983,0.189),取 ±24 偏移把控制点放到 (292,176) 与 (245,167),每条股线离杆约 8 单位,再把线宽提到 3、亮股提亮到 #d98a80。

第三次渲染后视觉逐项确认:右侧向上的红色长杆、顶端两个分叉、杆身两条深浅不同且向两侧弯出的 细线、与身体无穿模、未被画面截断。

回归

6 道闸门全过:audio.mjs 4384 断言 / 50 kinds、smoke.mjs、audit-classes、 audit-sfx-wiring、t7-crosscheck.mjs 1185 断言 / 32 动作、audit-triggers.cjs 32/32 可达。

仍未做到

  • launch / punch 的正典音源仍缺(T16 已认输);spear 的造型有正典出处,声学仍是推导。
  • 暴走第二套贴图仍缺白底/透明底立绘。
  • 枪的"投出去"没有真的脱手飞出(那需要一条离开机体坐标系的飞行轨迹与命中目标物),目前是突刺。

T20:改用真实的初号机音效与音乐(合成退为兜底)

用户要的是真音:任务处理、点击、完成提醒都用初号机自己的音效/音乐,而不是听起来"像"的合成音。 本轮加的是采样层,不是替换掉合成器——两者同时在线,文件有就用文件,没有就用合成。

1. 宿主半程第一次有了行为

lib/index.js 以前是空 apply(纯浏览器插件)。现在它注册一条只读路由,因为浏览器自己读不了磁盘:

路由 作用
GET /eva01-audio/manifest 返回 { dir, writable, files:[{name,bytes,type}] }
GET /eva01-audio/file/<name> 返回单个文件的字节(content-type 按扩展名,缓存 300s)

没有上传路由,这是故意的:文件由用户用资源管理器放,页面侧写不了任何东西。安全性是实测过的: resolveAudio 只认"出现在目录列表里的纯文件名",所以 ../../settings.yaml、 ..\\..\\settings.yaml、sub/click.mp3、.、空串、非音频的 notes.txt 全部返回 undefined (逐个跑过);apply() 在没有 webServer 服务时静默返回,不抛。

投放目录:%USERPROFILE%\.dsh\eva01-audio(可用环境变量 EVA01_AUDIO_DIR 覆盖), 首次读 manifest 时自动创建;已在里面放了一份 放这里.txt 说明。

2. 文件名决定它替换哪个事件

文件名 替换 事件
click.* blip 单击桌宠
task-start.* / start.* up 开始处理任务(进入 ACTIVE)
task-done.* / done.* / complete.* taskdone 任务完成提醒(回到 IDLE)
alert.* alarm 使徒警报(出现错误)
berserk.* roar 双击暴走
bgm.* / music.* —— 任务处理期间循环播放的音乐

进阶:文件名等于任意一个内置 kind(现有 50 个)就覆盖那个 kind —— 放个 atfield.mp3, A.T. 力场展开就用你的文件,其余仍走合成。

3. 工程细节

  • 采样播放挂在 playSfx 里、节流检查之后、合成层循环之前:采样同样受 THROTTLE 约束 (不会连发),命中采样时一个合成节点都不建。
  • 首次触发某个 kind 时缓冲区还在解码(decodeAudioData 是异步的),那一次仍由合成音应答, 之后都是真音。BGM 会在 1.2s 后重试一次,避免开局那一次错过就整场没音乐。
  • 增益:音效 SAMPLE_GAIN 0.5、音乐 BGM_GAIN 0.2,音乐永远压在音效之下;淡入 0.6s、 淡出 0.7s;♪ 静音开关会一并停掉音乐;active ↔ tool 切换不会重启音乐(effect 故意不写 cleanup),卸载时停。
  • 插件不附带任何音频资源:包体积没变,仓库里没有一个音频文件。

4. 新闸门 audit-samples.cjs 第一次运行就抓到一个真 bug

这道审计断言 5 条:槽位目标必须是真实 kind、bgm/music 不能同时是 kind、采样钩子必须在节流之后 合成之前、BGM_GAIN < SAMPLE_GAIN ≤ 1、两个半程的路由常量必须对齐。

第一次跑就红了:SAMPLE_ALIAS.berserk 指向 "growl",而 growl 只是 SFX_ALIAS 里 roar 的历史别名。playSfx 先解析别名再查采样表,所以采样表的键必须是解析后的 kind —— 照原样发出去,berserk.mp3 永远不会响。改为 "roar",并给审计加了一条"槽位不得指向别名"的断言。

5. 回归(7 道闸门)

audio.mjs 4384 断言 / 50 kinds · smoke.mjs · audit-classes · audit-sfx-wiring · t7-crosscheck.mjs 1185 断言 / 32 动作 · audit-triggers.cjs 32/32 可达 · audit-samples.cjs 8 槽位全部命中真实 kind。两个半程都过 node --check。

6. 需要注意

  • 宿主半程改了 → 必须重启 dsh 那条路由才会挂上(profile 只在启动时加载)。实测证据:当前进程 访问 /eva01-audio/manifest 返回的是 SPA 的 HTML 而不是 JSON。客户端半程(采样层本身)刷新 页面即生效,只是在重启前 manifest 永远拿不到,于是全部回落到合成音——降级是干净的。
  • 音频文件的版权归你自己处理:插件只播放你放进那个目录的文件,不下载、不附带。

T21:真的把素材找来装好了(8 个文件已就位)

用户要我自己去找素材。搜索路径:websearch.py → myinstants 的 Evangelion 搜索页(29 个直链 .mp3)。101soundboards 返回 403 拒绝抓取,voicy/soundboards.gg 未尝试。下载走 127.0.0.1:33210 代理,带 Referer;每个文件都验过 MP3 magic bytes,并用 ffprobe 量了真实时长。

装好的 8 个文件(~/.dsh/eva01-audio)

文件 素材 时长 为什么是它
click.mp3 evangelion-laser 0.81s 全场最短、干脆,点击音不能拖尾
task-start.mp3 evangelion-external-power-disconnect 2.27s 「外部电源切断」=转内部电源出击,正是"开始干活"
task-done.mp3 omedetou-1(おめでとう) 1.73s 完成提醒要短;18s 的 congratulations 版被否掉
bgm.mp3 decisive-battle(決戦) 25.26s 作战 BGM,够长,循环不刺耳
alert.mp3 ramiel-sound-clean 5.30s 第五使徒的驻留音,本身就是"使徒接近"的听觉符号
berserk.mp3 shinji-scream 4.92s 有 T15 依据:初号机嘶吼的正典做法就是把人声尖叫放慢
atfield.mp3 at-field-impact 2.09s 覆盖内置 atfield kind(A.T. 力场展开)
unplug.mp3 同 task-start 素材 2.27s 覆盖内置 unplug kind(暴走切内部电源)

备选素材留在 pet-ref/audio-candidates/(congratulations 18.23s、cruel-angel 11.53s、 okaerinasai 3.96s、ramiel-attack-scream 5.28s、evangelion 21.45s),想换哪个直接改名覆盖即可。

审计随之扩了一节

audit-samples.cjs 现在还会读投放目录,把每个音频文件实际会触发什么列出来,并且如果某个音频 文件映射不到任何事件就直接失败 —— 防止 taskstart.mp3(少了连字符)这种"看着装好了、其实永远 不响"的情况。当前 8 个文件全部命中:alarm / atfield / roar / 循环音乐 / blip / taskdone / up / unplug。

版权

这些是 myinstants 上用户上传的动画片段,版权属于 Khara/GAINAX。放在你自己机器上给桌宠用属于私人 使用;不要再分发,插件仓库里也仍然不含任何音频文件(素材只在你的用户目录)。想换成你自己抓轨的 OST,直接覆盖同名文件即可。

—/ 5

No ratings yet

Verified DSH bundle

Commit aba0a3e9bec4

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout