在对话页旁展示 LIVE2D 形象,随语音口型与表情联动
30.6/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Stella-Mira/muse_vtuber该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · other
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 34 处,展示前 34 条)
- 发起网络请求lib/client.js:47
const response = await fetch(API + path, { - 发起网络请求lib/client.js:60
const response = await fetch(API + path, { headers: { accept: 'application/json' } }) - 发起网络请求lib/client.js:1557
fetch(API + '/settings', { headers: { accept: 'application/json' } }) - 发起网络请求lib/client.js:1584
const response = await fetch(API + '/settings', { - 写入本地文件lib/kit.mjs:43
mkdirSync(dir, { recursive: true }) - 写入本地文件lib/kit.mjs:71
try { chmodSync(tmp, options.mode) } catch { } - 写入本地文件lib/kit.mjs:73
renameSync(tmp, file) - 删除本地文件lib/kit.mjs:80
try { unlinkSync(tmp) } catch { } - 读取本地文件lib/kit.mjs:93
if (!existsSync(file)) return fallback - 读取本地文件lib/kit.mjs:94
const raw = JSON.parse(readFileSync(file, 'utf8')) - 读取本地文件lib/kit.mjs:103
if (!existsSync(file)) return { ok: false, reason: 'missing' } - 读取本地文件lib/kit.mjs:106
raw = JSON.parse(readFileSync(file, 'utf8')) - 读取本地文件lib/kit.mjs:118
try { return statSync(file).mode & 0o777 } catch { return -1 } - 读取本地文件lib/config.js:169
return statSync(dir).isDirectory() - 读取本地文件lib/config.js:212
return readFileSync(this.file, 'utf8') - 读取本地文件lib/models.js:23
return readdirSync(dir, { withFileTypes: true }) - 读取本地文件lib/models.js:87
text = readFileSync(file, 'utf8') - 读取本地文件lib/models.js:134
if (!existsSync(full)) missing.push({ file: rel, why }) - 读取本地文件lib/models.js:181
return statSync(caps.dir).isDirectory() - 读取本地文件lib/routes.js:141
const buf = await readFile(full) - 读取本地文件lib/legacy/node-bridge.js:130
const readDirSafe = (dir) => { try { return readdirSync(dir, { withFileTypes: true }) } catch { return [] } } - 读取本地文件lib/legacy/node-bridge.js:172
if (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).name === '@deepseek-ai/dsh') { root = dir; break } - 读取本地文件lib/legacy/node-bridge.js:181
if (existsSync(join(mods, 'dsh-session-format-v3-to-v4', 'package.json'))) return { format: 4, how: 'host ships dsh-session-format-v3-to-v4' } - 读取本地文件lib/legacy/node-bridge.js:182
if (existsSync(join(mods, 'dsh-session-format-v2-to-v3', 'package.json'))) return { format: 3, how: 'host ships only dsh-session-format-v2-to-v3' } - 发起网络请求lib/legacy/node-bridge.js:235
const res = await fetch(new URL('cmd', this.cfg.node.base + '/'), { - 发起网络请求lib/legacy/node-bridge.js:246
health() { return fetch(new URL('health', this.cfg.node.base + '/'), { headers: this.headers() }).then((r) => r.json()) } - 发起网络请求lib/legacy/node-bridge.js:262
const res = await fetch(this.cfg.mcp.url, { - 发起网络请求lib/legacy/node-bridge.js:272
await fetch(this.cfg.mcp.url, { - 发起网络请求lib/legacy/node-bridge.js:300
const res = await fetch(this.cfg.mcp.url, { - 发起网络请求lib/legacy/node-bridge.js:402
const res = await fetch(url, { headers: this.headers({ Accept: 'application/x-ndjson' }), signal }) - 读取本地文件lib/legacy/node-bridge.js:485
try { return JSON.parse(readFileSync(p, 'utf8')) || {} } catch { return {} } - 写入本地文件lib/legacy/node-bridge.js:492
mkdirSync(this.dir, { recursive: true }) - 写入本地文件lib/legacy/node-bridge.js:496
writeFileSync(tmp, JSON.stringify(next, null, 2), 'utf8') - 写入本地文件lib/legacy/node-bridge.js:497
renameSync(tmp, p)
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DSH 界面交互(形象):LIVE2D 主位 + 视频/音频/表情侧边栏、虚拟摄像头与麦克风(外部采集器)、语音识别与识图事件流
README
由 DeepSeek 最新模型翻译生成muse_vtuber — DSH 界面交互(形象)
任务书 §muse_vtuber 的实现。4.0.0 起它只负责「画」(4.1.0 起连账号模型也去掉):给 DSH GUI 加一个「形象」页签 (对话 / 轨迹之后)——主位是 LIVE2D(说话时口型跟着音量动;没模型时频谱环兜底),右侧栏自上而下是视频 / 音频 / LIVE2D 表情;设置页叫「形象」。
声音与输入已经拆成两个可复用插件(2026-11-01):
muse_vtuber(本插件)──→ mira_device ──→ mira_media 画 LIVE2D、右侧栏、 摄像头/麦克风/ TTS/ASR/VAD/凭据表情/动作/模型/权限 采集器/自动推帧 (唯一一份阿里云 key)
- 版本:4.1.0(4.0.0 拆分出三件套并删除账号权限;3.1.0 是拆分前的单体;更早的 2.0.1 是「外部 stella 节点」桥,见 §10)
- 位置:PluginDSH/muse_vtuber
- 依赖:零第三方依赖;assets/lib/ 是 LIVE2D 运行库(见 THIRD-PARTY-NOTICES)
- 宿主依赖(inject):tools、webServer、miraMedia、miraDevice
1. 界面结构(对照任务书功能点)
| 功能点 | 落地 |
展开完整文档(README 剩余 1 节)
muse_vtuber — DSH 界面交互(形象)
任务书 §muse_vtuber 的实现。4.0.0 起它只负责「画」(4.1.0 起连账号模型也去掉):给 DSH GUI 加一个「形象」页签 (对话 / 轨迹之后)——主位是 LIVE2D(说话时口型跟着音量动;没模型时频谱环兜底),右侧栏自上而下是视频 / 音频 / LIVE2D 表情;设置页叫「形象」。
声音与输入已经拆成两个可复用插件(2026-11-01):
muse_vtuber(本插件)──→ mira_device ──→ mira_media 画 LIVE2D、右侧栏、 摄像头/麦克风/ TTS/ASR/VAD/凭据表情/动作/模型/权限 采集器/自动推帧 (唯一一份阿里云 key)
- 版本:4.1.0(4.0.0 拆分出三件套并删除账号权限;3.1.0 是拆分前的单体;更早的 2.0.1 是「外部 stella 节点」桥,见 §10)
- 位置:PluginDSH/muse_vtuber
- 依赖:零第三方依赖;assets/lib/ 是 LIVE2D 运行库(见 THIRD-PARTY-NOTICES)
- 宿主依赖(inject):tools、webServer、miraMedia、miraDevice
1. 界面结构(对照任务书功能点)
| 功能点 | 落地 |
| 1 新界面「形象」在「对话」「轨迹」之后 | 注册 conversation.view,id:"muse-avatar"、order:20 |
| 2 形象主体 + 侧边栏 | 左侧 .mv-main(LIVE2D 舞台 + 气泡),右侧 .mv-side |
| 3 主位 LIVE2D;侧边栏自上而下 视频 / 音频 / 表情菜单 | VideoPanel → AudioPanel → ExpressionPanel(数据来自 mira_device) |
| 5 摄像头关 → 视频黑屏;开 → 显示捕获画面 | 面板读 window.__miraDevice__ 的流/来源;采集器源走 /device/api/stream.mjpg |
| 6 麦克风关 → 音频直线;开 → 显示波形 | 波形用 mira_device 的 AnalyserNode;采集器源用宿主推的 RMS |
| 7 识别结果插话 / TTS 说话 | 插话在 mira_device;说话在 mira_media(device_say),形象订阅 say 做气泡 + 口型 |
| 9 背景「频谱环」 | SpectrumRing:麦克风开着用麦克风频谱、说话时用播放器频谱、都不是就呼吸波形 |
| 8 设置界面 | 注册 settings.section(@deepseek-ai/dsh-client-ui-settings)→ 「形象」:模型/目录/画布 |
两条稳定性约定(踩过坑才写下的)
- 舞台的 DOM 节点恒定存在(隐藏只切 opacity)。早期版本用「有/没有模型就换一个节点」的方式渲染,任何一次上层重渲染都可能把挂 canvas 的那个节点换掉 → 表现就是「形象忽然不见了」。
- 表情/动作先校验再落状态:模型里没有的名字不会写进 state.json,也不会喂给 pixi-live2d-display(喂了会把表情管理器写坏,表现是「模型忽然不渲染」)。
- 布局:.mv-view 的高度按「最近可滚动祖先」实测钉死,右侧栏自己滚 —— 早期版本靠 height:100%,在宿主那个高度是 auto 的槽位里解析不出来,模型只显示下半身。
2. 落盘(约定1 / 约定3 / 约定7)
$DSH_HOME/mira_config/muse_vtuber/
config.json 配置(schemaVersion 1)。唯一会自动创建的文件 state.json 形象实况(可见性/模型/表情/开关/动作,schemaVersion 1) model/ 可选:自己的模型目录(留空 modelsDir 时优先用它)
不再在这里:creds/dashscope.json(→ mira_config/mira_media/creds/)、 capture.json(→ mira_config/mira_device/capture.json)。
热生效:config.json 内容变了,下一次读取就重新加载(约定9);换代码仍需重启宿主(§11 的坑)。
3. 配置表
| 键 | 默认 | 说明 |
| enabled | true | false = 不注册工具与路由 |
| live2d.modelsDir | "" | 留空 = 依次找 mira_config/muse_vtuber/model → mira_config/mira_live2d/model。手填绝对路径优先 |
| live2d.model | "" | 要显示的模型(目录名或 .model3.json)。留空 = 不显示模型(只剩频谱环);设置页选完保存会立即切换 |
| live2d.width / height | 420 / 560 | 初始画布尺寸(CSS 像素),实际随容器缩放 |
| legacyNode.enabled | false | 旧的外部节点桥(见 §10),默认不加载 |
| ui.showHint | true | 首次进入给操作提示 |
旧版(≤3.1.0)的 camera / mic / tts / asr / vision / capture / events 键不再被读取,但会原样留在 config.json 里(前向兼容);对应能力分别搬到了 mira_device / mira_media(见 §9)。
4. 工具(5 个)
没有权限模型(4.1.0 起):形象是纯展示面,任何会话都能调这 5 个工具,不再需要 mira_account、不再有 taker/observer/force。旧版那套「形象是一个账号」的绑定模型已整个删除(真要防多会话打架,等需要时再加一个内存认领,不必把账号池拉进来)。
| 工具 | 干什么 |
| vtuber_status | 只读:形象状态(可见性/模型/表情/开关/动作)、模型清单与缺失资源、连着的页面数,并转述 audio(TTS/ASR/key)与 input(开关/采集器/识图)状态 |
| vtuber_expression | 表情三件套:name(互斥)/ toggles(整体替换叠加开关)/ switch+on。未知名字 → expression/unknown + 清单,状态原样不动 |
| vtuber_motion | 播放动作组;不传 = 列清单 |
| vtuber_visible | 显示/隐藏形象主体(频谱环仍在) |
| vtuber_model | 切模型;不传 = 列清单;clear:true = 只留频谱环 |
5. 宿主 HTTP 面(/vtuber/api/,全部同源校验)
| 方法与路径 | 作用 |
| GET /vtuber/api/bootstrap | 一次拿全:配置(脱敏)、状态、模型清单、deps(声音/输入是否就位)、endpoints |
| GET /vtuber/api/capabilities?model= | 表情/动作清单 + 缺失资源 |
| GET /vtuber/api/events | SSE:hello / state(模型/表情/动作/可见性) |
| GET/POST /vtuber/api/state | 形象状态 → state.json → 广播(clientId 记成 by: client:<id>) |
| GET/POST /vtuber/api/settings | 设置页读写(只有 live2d.);GET 回 keyConfigured(转述声音插件)与 deps |
| GET /vtuber/api/health | 存活探针(客户端数、依赖是否就位、features.live2d) |
| GET /vtuber/assets/、/vtuber/models/ | 运行库与模型静态文件 |
已经不在这里(拆分后的入口):
| 旧 | 新 |
| POST /vtuber/api/say、GET /vtuber/api/audio/<id> | POST /media/api/say、GET /media/api/audio/<id> |
| POST /vtuber/api/asr、POST /vtuber/api/vision | POST /device/api/asr、POST /device/api/vision |
| POST /vtuber/api/capture/、GET /vtuber/api/stream.mjpg | /device/api/capture/、/device/api/stream.mjpg |
6. 页面全局契约(形象读别的插件)
window.__miraDevice__ = { state(), subscribe(fn), level(), analyser(), play(url), ready(), version }
window.__miraDevice__ = { state(), subscribe(fn), videoStream(), analyser(), level(),
setCamera(on), setMic(on), setSource(kind, source), heard(), seen(), captureUrl() }
- 形象不自己播音频:声音由 mira_media 的全局播放器播,这里只读 state().level 驱动口型(两边都播会变成双重声音)。
- 形象不碰硬件:视频/音频面板只消费 mira_device 的流、电平与日志。
- 两个全局对象都可能比本模块晚出现(模块加载顺序不定),所以都做了短轮询 + 订阅。
7. 模型与资源缺失
models.js 解析 model3.json 的 FileReferences,逐个检查 Moc / Textures / Physics / Pose / Expressions[].File / Motions[].File,缺什么就说清是哪个文件、属于什么类型:
vtuber_status → models.missing: [{ file: "SylviaMuse.4096/texture_02.png", why: "贴图" }] 侧边栏表情菜单 → 缺资源:…(放进 <模型目录>/<模型名>/)
表情分两类(与 mira_live2d 同一套约定):开关- / 动作- 可同时打开(叠加层),其余(表情-)互斥。叠加是把"当前互斥表情 + 所有打开的开关"合成一个 ExpressionMotion,经 expressionManager 的官方队列应用。
8. 迁移:3.1.0(单体)→ 4.0.0(三件套)→ 4.1.0(去掉账号)
| 旧位置 | 新位置 |
| muse_vtuber/config.json 的 tts / asr / mic.vad | mira_media/config.json(首次创建时自动迁移) |
| muse_vtuber/creds/dashscope.json | mira_media/creds/dashscope.json(首次加载时自动复制,600;旧文件保留) |
| muse_vtuber/config.json 的 camera / mic / capture / vision / events | mira_device/config.json(首次创建时自动迁移) |
| muse_vtuber/capture.json | mira_device/capture.json(mira_device 重新生成;muse_galaxy 已改读这里) |
| muse_vtuber/state.json 的 cameraOn/micOn/cameraSource/micSource | mira_device/state.json(不迁移,重新点一次开关即可) |
| 工具 vtuber_say | → device_say(工具名变了,提示词/预设里如果写了要改) |
| 工具 vtuber_camera / vtuber_mic / vtuber_look / vtuber_listen | → device_camera / device_mic / device_look / device_listen |
| 设置页「形象」里的 TTS/ASR/识图/设备 | → 「声音」/「输入」两个设置页;「形象」只剩 LIVE2D |
迁移只读旧文件,不删不改;回滚就停用三个新插件,重新启用旧 muse_vtuber 3.1.0。
9. 已知取舍
1. 说话工具改了名字:vtuber_say → device_say。用户口径是「各自的能力归各自的插件」:发声属于声音插件,形象只管口型。预设/技能里提到旧名字的要一起改。
2. 插话不再由形象负责:events. 配置、限流、模板都搬到了 mira_device;形象不再需要 sessionController。
3. 自动识图默认关(mira_device 的 vision.autoIntervalMs: 0):定时抓帧会持续消耗额度。
4. 模型目录默认复用 mira_live2d 的那套(存在才用)。
5. LIVE2D 运行库是复制进来的,不是跨插件 import(link: 安装下跨包相对 import 不可靠)。
6. 表情叠加用 expressionManager._setExpression()(下划线接口):mira_live2d 已在生产用,上游改名就会失效 —— 表现是「开关点了没反应」,不会崩。
10. 旧的外部节点桥(2.0.1,默认关)
旧版是「DSH ↔ stella muse_vtuber 节点」的桥:MCP 拿工具、/dsh 出口拿事件,工具名 muse_。
3.0.0 按任务书重写成纯 GUI 插件,桥不是任务书范围。代码原样留在 lib/legacy/node-bridge.js,默认不加载;要恢复就把旧配置整体搬进 config.legacyNode.config 并把 legacyNode.enabled 设为 true(失败只 warn,不影响形象页签)。
11. 验收
node --check lib/client.js # 浏览器模块只做语法自检
node test/smoke.mjs # → ALL PASS(通过 34 项断言)
node test/http-e2e.mjs # → ALL PASS(10 项端到端断言,真起 http + 真 SSE)
node ..\tool_shared\tools\check-zero-dep.mjs muse_vtuber
node ..\tool_shared\tools\check-kit.mjs
手工(三件套一起装好之后):
| # | 步骤 | 期望 |
| 1 | 打开会议话界面 | 顶部页签:对话、轨迹、形象 |
| 2 | 点「形象」 | 主位出现 LIVE2D(或频谱环);右侧 视频 / 音频 / LIVE2D 表情 |
| 3 | 点输入框里的「摄像头」 | 侧边栏视频出现画面;再点一次黑屏(按钮属于 mira_device) |
| 4 | 点「麦克风」说一句话 | 波形动;停顿后「听到:…(已插话)」;会话里多一条 [感知·语音](插话由 mira_device 投递) |
| 5 | 让模型说话(device_say / 「设置 · 声音」的试听) | 形象出声、口型跟音量动、气泡显示文字 |
| 6 | 设置 · 形象 → 选模型 → 保存 | 立即切换;空白 = 只显示频谱环 |
| 7 | 把 config.json 的 schemaVersion 改成 99 再重载 | 工具报 config/schema,不静默清空 |
两个「改代码不生效」的坑(都实测过)
1. 宿主半:Loader 把模块缓存在「解析后的真实路径」上,plugin_manager set_plugin 关开只会重放缓存里的旧模块(实测:改代码后关开,/vtuber/api/health 仍是旧响应)。换宿主代码必须重启 dsh web。新插件(首次 import)不受影响,可以热加载。
2. 前端半:dsh-client-modules 解析 dsh.client 时,从模块真实路径往上找 package.json,且要求 name 严格等于 loader 条目的 specifier。所以安装名必须与包名一致(muse_vtuber),别用别名装。
lib/client.js 末尾仍同时注册 muse_vtuber / muse_vtuber_ui 两个 id:只有宿主清单里那个会被真正 import,另一个只是躺着的工厂(历史原因:曾用别名装过)。
12. 开发约定
- 只依赖 node: 内置与浏览器 API;lib/kit.mjs 是 tool_shared/kit/kit.mjs 的逐字节副本。
- 所有工具返回 { ok:true, … } 或 { ok:false, error:{ code, message, hint } }。
- 单实例保护:apply 里 claimInstance('muse_vtuber'),第二个实例报 plugin/instance。
- 退场顺序:摘工具 → 卸路由 → 停 SSE → 落状态 → 放认领(ctx.effect 与装配失败走同一条路径)。
- 依赖方向不允许反向:形象可以读 miraMedia / miraDevice,它们不反过来依赖形象。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Stella-Mira/muse_vtuber
在对话页旁展示 LIVE2D 形象,随语音口型与表情联动
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目