DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

dsh-mpkg-wallpaper

Mpkg Wallpaper

DSH Web 壁纸引擎 Wallpaper Engine mpkg 背景插件:浏览器内直接解析 .mpkg(preview.gif 动态背景/内嵌 mp4 视频/多时段切换),整屏统一虚化/对话框/弹层/遮罩独立虚化、镜头缩放平移、时钟、冲突检测。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-mpkg-wallpaper@3.17.0
README兼容性版本

兼容性与来源证明

Mpkg Wallpaper 以 dsh-mpkg-wallpaper 发布,当前版本为 3.17.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
npm
Registry 更新时间
2026/11/4

版本

3.17.0stable
2026/10/28
3.16.6stable
2026/10/10
3.16.5stable
2026/10/7
查看其余 58 个版本收起版本
3.16.4stable
2026/10/4
3.16.3stable
2026/10/3
3.16.1stable
2026/10/3
3.16.0stable
2026/10/3
3.15.9stable
2026/10/3
3.15.8stable
2026/10/3
3.15.7stable
2026/10/3
3.15.6stable
2026/10/3
3.15.5stable
2026/10/3
3.15.4stable
2026/10/2
3.15.3stable
2026/10/2
3.15.2stable
2026/10/2
3.15.1stable
2026/10/2
3.15.0stable
2026/10/2
3.14.0stable
2026/10/2
3.13.12stable
2026/10/2
3.13.11stable
2026/10/1
3.13.10stable
2026/9/27

相关插件

正在加载相关插件…

最新版
3.17.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
2.9 MB
文件数
16
Surface
web
许可证
MIT
发布源
npm
GitHub
★ 12
周下载
1,202
安全扫描
✓ v3.17.0 扫描通过
最近提交
2026/10/30
查看源码 ↗项目主页 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
3.13.9stable
2026/9/25
3.13.8stable
2026/9/25
3.13.7stable
2026/9/24
3.13.6stable
2026/9/24
3.13.5stable
2026/9/23
3.13.4stable
2026/9/23
3.13.3stable
2026/9/23
3.13.2stable
2026/9/22
3.13.1stable
2026/9/22
3.13.0stable
2026/9/21
3.12.0stable
2026/9/20
3.11.0stable
2026/9/20
3.10.1stable
2026/9/20
3.10.0stable
2026/9/19
3.9.1stable
2026/9/19
3.9.0stable
2026/9/19
3.8.2stable
2026/9/19
3.8.1stable
2026/9/19
3.8.0stable
2026/9/19
3.7.3stable
2026/9/18
3.7.2stable
2026/9/10
3.7.1stable
2026/9/2
3.7.0stable
2026/8/28
3.6.0stable
2026/8/24
3.5.3stable
2026/8/24
3.5.2stable
2026/8/23
3.5.1stable
2026/8/23
3.5.0stable
2026/8/23
3.4.0stable
2026/8/23
3.3.2stable
2026/8/22
3.3.1stable
2026/8/22
3.3.0stable
2026/8/22
3.2.0stable
2026/8/21
3.1.6stable
2026/8/21
3.1.5stable
2026/8/20
3.1.4stable
2026/8/20
3.1.3stable
2026/8/20
3.1.2stable
2026/8/19
3.1.1stable
2026/8/19
3.1.0stable
2026/8/19

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Web App@deepseek-ai/dsh-web-appdsh 浏览器界面捆绑包:位于 dsh-base 之上的 Web 补丁层,加上运行时粘合插件(提供前端 dist、Web 界面提示符、bash 运行时变量和 URL 行)Experimental Session Titles Bundle@deepseek-ai/dsh-experimental-session-titles-bundle新的用户提示到达时刷新会话标题。Personalized Recommendations@deepseek-ai/dsh-personalized-recommendations回答下方以卡片形式提供个性化页面和内置插件推荐Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义

README

dsh-mpkg-wallpaper — DSH 壁纸引擎背景插件

中文 | English

给 DeepSeek Harness Web 界面(dsh web)添加背景壁纸的插件:Wallpaper Engine .mpkg 解析、Steam 创意工坊目录、视频/网页/图片壁纸、时间变化壁纸的多时段切换、整屏虚化体系、主题色与玻璃外观、本地壁纸库、定时轮换、Now playing 控件、一键更新。外观细节几乎全部可调。

  • 仓库:https://github.com/XHR666/dsh-mpkg-wallpaper(已发布 npm 包 dsh-mpkg-wallpaper)
  • 配套渲染器(纯 Scene 壁纸用,GPL-3.0-or-later,另行安装):本包不包含它,也不 import/内嵌其任何代码; 获取方式见本插件仓库主页的链接与 docs/ 说明
  • 许可:MIT(见许可与归属);第三方台账见 THIRD-PARTY.md

版本口径:本文件描述的是 package.json 里的 3.16.6(= npm latest)。 发布面以 npm pack --dry-run 实测为准:16 个文件(9 个 lib/*.js 运行时文件 + package.json、icon.svg、cordis.patch.yml、README.md、README.en.md、THIRD-PARTY.md、LICENSE); lib/liquid-glass/**、lib/liquid-glass-bundle.js、dist/、tools/、docs/ 都不进 npm 包(package.json 的 files 负向模式)。 历史发布记录见 docs/RELEASE.md。


1. 下载 · 安装

四种装载方式——先按这张表选一条,再看对应小节:

方式适合谁更新怎么做客户端界面
一 dsh plugin add(推荐)默认选择;市场能识别「已安装」dsh plugin --profile web update dsh-mpkg-wallpaper完整
二 pnpm 手动装自己管 profile 的依赖表同上(走依赖表)完整
三 GitHub 克隆开发者 / 离线 / 要改代码git pull完整
四 单文件 bundle离线应急;给非 DSH 宿主复用路由重新生成并替换那个 .mjs只有宿主端

方式一:dsh plugin add(推荐,市场可识别)

dsh plugin --profile web add dsh-mpkg-wallpaper
# 重启 dsh web 后浏览器 Ctrl+F5 生效

方式二:pnpm 手动安装

pnpm --dir $DSH_HOME/profiles/<profile> add dsh-mpkg-wallpaper
# 重启 dsh web,浏览器 Ctrl+F5 生效

与方式一同源,只是不经 dsh plugin 包装。

方式三:GitHub 克隆(开发者 / 离线)

git clone https://github.com/XHR666/dsh-mpkg-wallpaper.git $DSH_HOME/profiles/<profile>/node_modules/dsh-mpkg-wallpaper
# 然后在 profile 的 cordis.patch.yml 注册:
#   - insert:
#       - id: dsh-mpkg-wallpaper
#         name: dsh-mpkg-wallpaper
# 重启后生效

方式三不写依赖表 ⇒ 市场不显示「已安装」(只影响显示,不影响功能)。

方式四:单文件 bundle(离线 / 拷文件即装;只装宿主端)

把宿主端内联成一个自包含 ESM 再登记:

cd /path/to/dsh-mpkg-wallpaper
node tools/build-bundle.mjs          # 产物:dist/dsh-mpkg-wallpaper.bundle.mjs(大小以该命令输出为准)
node tools/build-bundle.mjs --check  # 与源码对拍:导出面 / 路由表 / ping JSON 形状
node tools/bundle-equivalence-test.mjs  # 更全的等价性门禁(构建可复现 + 路由逐字段对拍 + 装载布局 + 变异对照)

把 dist/dsh-mpkg-wallpaper.bundle.mjs 拷到任意目录(例如 ~/.dsh/plugins/),在 profile 的 cordis.patch.yml 里按绝对路径登记,然后重开 dsh web:

# $DSH_HOME/profiles/<profile>/cordis.patch.yml
- insert:
    - id: dsh-mpkg-wallpaper
      name: /绝对路径/dsh-mpkg-wallpaper.bundle.mjs   # ← 指向那个 .mjs 文件本身

这条路装载了什么 / 没装载什么(都是代码与门禁事实):

项方式四的行为依据
宿主端(上传/Range 流式播放、场景提取、音频清单、设置持久化、诊断上报、系统媒体会话等路由)完整(lib/index.js 及其相对 import 全部内联;外部依赖只有 node 内建)node tools/bundle-equivalence-test.mjs:路由表(kind + path)逐条相同
/api/mpkg-wallpaper/ping{ok, version, betterSidebar, betterSidebarVersion} 键集合与源码一致同上 + build-bundle.mjs --check
客户端半(设置面板 / 壁纸层 / 磨砂 / Now playing)不装载。单文件里只有宿主端导出面(apply / inject / __mpwTest)客户端半由 DSH 客户端模块系统按包发现:扫描宿主 Loader 条目里声明了 dsh.client 的包并解析其 exports["./client"];裸 .mjs 没有 package.json ⇒ 没有 dsh.client 声明
GET /api/mpkg-wallpaper/lg/*(遗留 WebGL 托管路由,客户端已不调用)bundle 旁边没有 liquid-glass/ 时 404;cp -r lib/liquid-glass <bundle 目录>/ 即与源码逐字节一致该路由以 import.meta.url 定位同目录 liquid-glass/;门禁两种布局都断言过
ping.version上一级目录没有 package.json 时返回 null(只影响版本号显示)new URL('../package.json', import.meta.url)
「检查更新 / 一键更新」无伴生 package.json 时 update-check 返回 500,update-apply 会往 bundle 同级/上级目录写文件 ⇒ 不建议在方式四下使用lib/index.js 的更新路由

结论:方式四是"宿主端能力"的降级装载(离线/应急/给非 DSH 宿主复用路由时好用);要完整界面请用方式一/二/三。产物不入库(dist/ 在 .gitignore 里:它是 lib/*.js 的纯派生物,发布时现生成)。

桌面版(DSH Desktop)怎么装

DSH 桌面包目前只有 macOS / Windows。官方口径:desktop 这个 profile 名由 Electron 壳独占, CLI 会拒绝它的 boot / config-dump / 插件管理请求 ⇒ 桌面上不能照抄 dsh plugin --profile desktop add …。 桌面档请按下面两条之一走(按你手上那个桌面版本的界面为准):

  1. 桌面 App 自带的插件入口(若有):在设置/插件页添加 npm 包名 dsh-mpkg-wallpaper;
  2. 手动装进桌面 profile 的依赖树:把包放进该 profile 的 node_modules/(或在其 package.json 里加依赖后装), 并在该 profile 的 cordis.patch.yml 里保留本包的挂载行(与「方式三」同形,只是 profile 换成一个由桌面壳管理的目录)。

桌面档还有一条与网页档不同的前提:宿主页面源可能不是回环 HTTP(Electron 用 file:// + IPC)。 3.11.0 起客户端已按 DSH 第一方口径兜底(location.origin 缺失或为 "null" ⇒ http://dsh.internal), 所以宿主路由在桌面档也能解析;若仍然连不上宿主,请跑 window.__mpwCompat() 与 GET /api/mpkg-wallpaper/compat 把两段 JSON 发给我们。

更新

# 方式一 / 二:走 npm 的 latest 标签
dsh plugin --profile web update dsh-mpkg-wallpaper

# 方式三:在克隆目录里
git pull

# 方式四:重新生成并替换那个 .mjs
node tools/build-bundle.mjs

更新后都要:重启 dsh web → 浏览器 Ctrl+F5。

卸载

方式一/二/三:dsh plugin --profile web remove dsh-mpkg-wallpaper。 方式四:删 .mjs + cordis.patch.yml 里那一行。

残留数据(可选清理,注意是两处不同目录):

  • 浏览器 localStorage['dsh.mpkg-wallpaper.v2']
  • 主数据目录 $DSH_HOME/.dsh-mpkg-wallpaper/(未设 DSH_HOME 时是 ~/.dsh-mpkg-wallpaper/):settings.json、web-store.json、media-audio.json、上传的 mpkg、转码缓存
  • 诊断/缩略图目录 ~/.dsh/.dsh-mpkg-wallpaper/:diag-*.json、thumbs/

2. 30 秒快速开始

装完到看见壁纸,只走三步:

  1. 装好并重启:按上一节任选一种方式装完,重启 dsh web,浏览器 Ctrl+F5。
  2. 打开面板:左侧栏「设置」→「壁纸引擎背景」。
  3. 选一张壁纸,任选其一:
    • 拖入 .mpkg 文件(视频类直接播;场景类走静态帧/图层合成)
    • 选本地图片 / 视频,或填一个图片链接
    • 「自定义目录」选一个文件夹(可直接选 Steam 的 steamapps/workshop/content/431960,每个子文件夹算一张)

默认档就已经能用:总开关开(enabled)、大文件混合模式开(hybrid)、整屏虚化开(unifyAmount = 30)、Now playing 挂在左侧栏(npNowPlaying 开)。 想微调,先动这三处就够:壁纸设置 → 磨砂模糊(0–40)、界面统一 → 整屏虚化程度(0–40)、壁纸设置 → 镜头缩放(10–2000%)。

没反应时先去「其他」tab 点一次 一键诊断上报(宿主不可用会自动下载 JSON),再带上它去反馈。


3. 主要特性

按你能感知到的东西分组(来源、时间变化、虚化、外观、播放、库与轮换、安全、备份),不按代码模块。

📦 壁纸来源

  • Wallpaper Engine .mpkg:浏览器内直接解析容器(不上传第三方);视频类播放内嵌 mp4 / 视频纹理;场景类解析容器提取素材;时间变化按系统时间选时段素材
  • Steam 创意工坊目录:自动发现 WE 安装(注册表 + libraryfolders.vdf,支持非默认盘),列出 video / web / scene 三类;也可把 workshop 主目录(steamapps/workshop/content/431960)直接设为自定义目录——每个子文件夹自动识别为一张壁纸
  • 视频:.mp4/.webm/.mov/.m4v 直接播放;网页:HTML 在沙箱 iframe 中加载(带风险预检);图片/动图/链接:本地图片或 URL(含 data:image)
  • 自定义目录:任意文件夹,.mpkg、workshop 子目录、图片/视频/scene.pkg 混放都能识别

⏰ 时间变化壁纸(Time Variation)

  • 识别 WE 的时间变化属性(morningtime / daytime / dusktime / nighttime / timevarying)
  • 按需懒加载:只提取当前时段素材(单槽峰值几十 MB),切换时段时才读,避免一次导入全部时段导致 OOM
  • 手动锁定时段:时段按钮只在容器里真的有该时段素材时出现,键名 timeOverride;点「自动」恢复随时间切换
  • 不串台:切换壁纸时清空上一张的时段缓存

🌊 整屏虚化(磨砂)体系

  • 统一虚化:一条滑条控制整屏壁纸模糊度 + 侧边栏/标题栏白雾厚度;聊天区是否跟随、新会话按钮是否跟随各自独立
  • 界面虚化(各自独立开关 + 程度):对话框(通用居中窗口 + 聊天输入框)、设置面板、下载/确认弹窗、弹层(菜单/下拉/提示)、遮罩(全屏背景)、左侧边栏磨砂
  • 透出壁纸:左侧边栏 / 标题栏 / 右侧边栏 dock 各自独立,标题栏磨砂可单独指定半径

🎨 主题色与玻璃外观(Aqua 实验默认全关)

  • 主题颜色(themeColor):取色盘 + 预置,驱动侧栏/标题栏/新会话按钮/设置弹窗底色;**配色(accent)**驱动品牌交互色(按钮/滑条/选中/链接/发送键)
  • 面板颜色匹配壁纸(aquaTint):自动采样壁纸主色(视频/GIF 每 2 秒刷新);统一雾(全屏色调雾罩)、自适应文字色 + 蓝色清理、深底文字可读增强、任务列表磨砂
  • 液态玻璃(CSS/SVG 版):lgCss + 折射强度,作用于输入框/左侧边栏/标题栏;lib/liquid-glass/ 的 WebGL 运行时不参与生成(见文件结构)

🧩 dsh-better-sidebar 适配(检测到该插件后显示)

  • 已安装时「其他」tab 出现适配分类:总开关 bsCompat(默认开)+ bsFloat(悬浮双层修复)/ bsFont / bsReveal + bsRevealAlpha / bsAqua
  • 宿主 /api/mpkg-wallpaper/ping 返回 {ok, version, betterSidebar, betterSidebarVersion};客户端写 body[data-mpw-bs-version],版本专属规则用 [data-mpw-bs-version^="…"] 门控
  • 详见 docs/BETTER-SIDEBAR-COMPAT.md、docs/BETTER-SIDEBAR-DOM-CONTRACT-0.19.1.md,回归 node tools/better-sidebar-compat-test.mjs

🧭 扫描壁纸页(右侧边栏版)

  • 顶部显示当前扫描目录(取「背景来源」里的自定义目录;未配置时用 Steam 创意工坊目录),打开即刷新
  • 缩略图按正方形铺成网格,列数随面板宽度自适应;点缩略图选中,上方详情区显示名称、容器内实际文件、类型
  • 详情区常驻:未选中时各项显示「无」,三个按钮置灰;选中后可「应用此壁纸 / 刷新选中 / 取消选中」
  • 选中项带描边高亮与上提阴影,应用后仍保持;网格可独立滚动,页面本身不滚动

🖱️ 鼠标光晕

  • 外观 tab 第 2 项开关;开启后指针所在面板内部以指针为中心泛出一圈柔光(白、低强度、随主题微调)
  • 关闭后不监听、不写任何变量;与「悬浮效果」总开关联动(总开关关闭时同样不生效)

💾 预设配置

  • 常用组合可存为预设并一键切换;「保存配置」把当前配置写回该预设快照,「恢复默认」把生效配置还原到该快照
  • 「+」新建时先把当前配置存成新预设的初值;编辑态下每个预设右上角出现灰色 ×,可直接删除

🧱 层叠与可读性

  • 代码块横幅(sticky 标题条)不再被标题栏样式规则接管:滚动与吸附全程保持不透明,与宿主原生一致
  • 弹层/菜单/提示气泡统一提到正确层级,气泡不被容器裁切;被裁场景会临时放开裁切祖先

⏯️ 播放控制与省电

  • 视频/网页壁纸可暂停/播放(设置页「壁纸设置」下的按钮),暂停状态实时反映视频实际状态;调整无关设置不会触发重播
  • 省电三档:页面隐藏/切页暂停(默认开)、窗口失焦暂停、电池供电暂停(getBattery 缺失则静默跳过);任一档触发即暂停,全部恢复才继续;与手动暂停共用一套门控

🚀 大文件混合模式(hybrid,默认开)

  • mpkg 流式上传到 DSH 宿主 → 磁盘存储 → HTTP Range 流式播放;>600MB 也能放,因为流不进内存;关掉则回纯浏览器模式(600MB 上限)

🖼️ 本地壁纸库与轮换

  • Steam 自动发现 + 自定义目录(跨平台目录选择器);WE 原生播放列表(config.json 的 general.playlists)导入为轮换列表
  • 上一个/下一个一键切换、定时自动轮换(rotate + rotateMin,1–120 分钟);列表勾选后滚动不跳顶

🛡️ 安全与共存

  • 冲突检测:检测到其他壁纸/主题插件时自动关闭本功能(可手动强开,写 forceEnabled)
  • .exe/application 壁纸完全排除;自定义目录只读媒体文件;宿主路由有路径穿越校验;网页壁纸 iframe 沙箱隔离

💾 备份与恢复 / 设置持久化

  • 「其他」tab 的备份与恢复导出外观类设置为可分享 JSON(BACKUP_FIELDS 白名单),导入即还原
  • 设置除浏览器 localStorage(键 dsh.mpkg-wallpaper.v2)外另存宿主端 settings.json,换端口/清浏览器数据不丢

4. 支持的壁纸类型与边界

这节回答「我手上的素材能不能用、能用到什么程度」。

类型表现能控制什么 / 做不到什么
mpkg(视频类)✅ 完整内嵌 mp4/视频纹理直接播放;静音、倍速、暂停、模糊/缩放/亮度全可调
mpkg(场景类)🟡 折中容器素材提取:静态帧 / 图层合成 / 内嵌视频时段;Live2D 木偶、shader、脚本做不到(见场景现状)
时间变化壁纸✅ 多时段自动切换 + 手动锁定;只提取当前时段
视频(mp4/webm/mov/m4v)✅ 完整直接播放;解码帧率上限/分辨率上限需 ffmpeg 转码
网页(HTML)🟡 实验性沙箱 iframe + WE API shim;只读设置项的 Live2D 类可改;外网 SDK / 重交互类未适配
scene.pkg 原始目录🟡 折中同 mpkg 场景类
preview.gif / 图片 / 动图✅ 完整场景壁纸无更多素材时回退作者预览图
Application(exe)❌ 排除内容判定即 unknown/excluded-application,绝不读取/执行
自定义目录(混合)✅ 完整mpkg 与 workshop 子目录混放;深度 ≤4、条数 ≤4000 的有界扫描

明确的边界(都不是"以后再说",是当前实现的事实):

  • 场景壁纸的完整动态还原做不到——MDL 木偶骨架无公开格式文档、shader/脚本无 Web 端运行时(见场景适配现状)
  • 纯 Scene 渲染方式选择器目前未接线:「其他」tab 的 sceneRender(webgl/static/elysia)有按钮、有写入,但全仓没有读取点;实际路径由渲染器可用性决定(在线走渲染器 iframe,离线回退静态帧)
  • 网页壁纸的 CSS :hover/:active、isTrusted:true、帧内 contextmenu、指针锁定/全屏/下载弹窗做不到(合成事件的固有边界,docs/WEB-WALLPAPER.md §11.4)
  • 超过 600MB 的素材只在 hybrid 模式下可用;纯浏览器模式另有 250MB(视频纹理)/200MB(图片纹理)/100MB(本地图片文件)上限

5. 设置项总表(7 个 tab;右侧边栏版另有「扫描壁纸」)

tab 顺序与面板一致,固定为 TAB_ORDER = ["source","wallpaper","appearance","unify","blur","other","liquid"], 界面文案:背景来源 / 壁纸设置 / 外观 / 界面统一 / 界面虚化 / 其他 / 测试项。

1. 背景来源(source)

面板文案内部键默认作用关闭 / 回退
启用壁纸引擎背景功能enabled开总开关;关闭即不应用任何背景关
上传到 dsh 进程流式播放hybrid开大文件混合模式(上传宿主 → 磁盘 → Range 播放,无 600MB 上限)关 = 纯浏览器模式
mpkg 文件 / 图片 / 视频 / 图片链接——文件选择与 URL 输入(http(s) 或 data:image)「清除壁纸」按钮
自定义目录customDirPath空任意目录;可指 workshop 主目录,每个子文件夹识别为一张壁纸清空输入
本地壁纸库(Steam 扫描)——扫描 WE 安装与创意工坊,导入壁纸与 config.json 播放列表重新扫描覆盖
轮换(定时自动切换)rotate / rotateMin关 / 5 分钟到点切换下一个壁纸(1–120 分钟)关
时段timeOverride自动手动锁定清晨/白天/黄昏/夜晚;按钮只列容器里真实存在的时段点「自动」
当前壁纸卡片——预览图、显示名、容器内文件名、类型;暂停/播放、刷新、清除—

2. 壁纸设置(wallpaper)

含「壁纸画面」与「省电」两个子分组。

面板文案内部键默认作用关闭 / 回退
静音(网页壁纸)mute开网页壁纸音频;关 = 放壁纸声音关
Now playing(左侧栏「设置」上方)npNowPlaying开左侧栏挂可展开播放器(传输行 = 壁纸声音控制);关掉仍是零注入;同一位置被别的插件占用时自动让位(data-mpw-np-yield)关 / 恢复默认
播放/暂停同时控制壁纸npLinkWallpaper开Now playing 的播放/暂停与进度同时驱动壁纸自身;关 = 只驱动本插件播放器(壁纸媒体是唯一声源时控件如实 disabled)关
Web 帧模式(网页壁纸)webFrameModeauto网页壁纸 iframe 的三档:auto = 隔离沙箱,被浏览器策略挡住 / shim 没报到时只在沙箱内降档(去掉 shim 标记重载,仍是不透明源),不会自动升同源(默认);sandbox = 强制隔离,不自动降档(原因写进状态,可查);compat = 兼容档(同源 + 不带 shim 标记,只有用户显式选它才到得了)。状态见 window.__mpwWebFrame 与 #mpw-bgWrap[data-mpw-webframe-mode|-reason|-attr|-fallback|-autocompat|-degraded],台账 window.__mpwWebFrameGuard(详见 docs/WEB-WALLPAPER.md §3.0)选 auto;也可用 ?webframe=auto|sandbox|compat 临时覆盖(不改设置)
自动降级到兼容档(高风险)webFrameAutoCompat关风险回退口:打开后 auto 档才允许在"被策略挡住"时自动降 compat —— 那意味着这张第三方壁纸的脚本与 DSH 同源(可读宿主界面/本地存储、可带 cookie 打插件路由)。关着时只记账 + 面板提示手动切。判据 tools/web-frame-origin-guard-test.mjs(详见 docs/SECURITY-ROUTES.md F5)关
渲染器上游白名单sceneUrlWhitelist空跨源回退口:sceneRendererUrl/sceneExtUrl 默认只允许 http(s) 回环(127.0.0.1/localhost/::1)与"和页面同主机的字面 IP";跨源上游必须把它的 origin 填在这里(逗号/空格分隔)才会被使用,否则一律拒绝并回落 127.0.0.1:8902(记账 + 日志,不静默)。⚠ 登记进来的上游会连同场景令牌 st 一起放行(详见 docs/SECURITY-ROUTES.md F6)

3. 外观(appearance)

含「透出壁纸」子分组。

面板文案内部键默认作用关闭 / 回退
悬浮效果float关左侧边栏/标题栏变悬浮卡片(圆角+阴影+透出)关
主题颜色themeColor空侧栏/标题栏/新会话/设置弹窗底色 tint(取色盘 + 预置)空 = 不启用
面板颜色匹配壁纸aquaTint关自动采样壁纸主色作面板底色(视频/GIF 每 2s 刷新)关 = 用取色盘
配色accent空品牌交互色(按钮/滑条/选中/链接/发送键)空 = DSH 默认
遮罩自定义色aquaColor空统一雾/面板的自定义色空 = 灰色
自定义灰字颜色fontColorGray关灰字走自定义色(配 fontColorGrayColor)关
左侧边栏透出壁纸sidebar开关 = 侧栏纯色不透明关
左侧边栏磨砂sidebarBlur关侧栏自身 backdrop-filter;弹窗打开时自动摘除关(需先开侧栏透出)
左侧边栏磨砂程度sidebarBlurAmount14px0–40;统一虚化开启时被接管—
标题栏透出壁纸headerBg开关 = 标题栏纯白关
标题栏磨砂headerBlur开统一虚化开启时被接管关
标题栏磨砂程度headerBlurAmount0%白雾厚度 0–100%(默认 0 = 透明)0
单独调节标题栏磨砂headerFrostOwn关开 = 用 headerFrostAmount 覆盖磨砂半径关
标题栏磨砂强度headerFrostAmount30px0–600

4. 界面统一(unify)

面板文案内部键默认作用关闭 / 回退
统一虚化unifyTint开整屏模糊感由一个条控制;开启后接管侧边栏/标题栏/右栏磨砂关
整屏虚化程度unifyAmount30px0–40(控制壁纸层 blur)—
界面透明度sidebarAlpha65%0% = 完全不透明(正常界面)、100% = 完全透明(看到壁纸);同时驱动左栏/标题栏/右栏·dock;与模糊互不影响—
聊天区跟随整屏虚化chatFollow开关 = 聊天区由「磨砂模糊」条控制关
新会话按钮跟随面板不透明度sessionFollow开关 = 回到宿主原色关
统一雾(全屏遮罩)aquaMask关所有表面共享一种雾色(原 Aqua 实验项)关
统一雾强度aquaMaskAlpha82%0–100%—

两个条的语义(判据 tools/fog-model-test.mjs): 「整屏虚化程度」= 模糊半径(0 = 完全不虚化); 「界面透明度」= 整个界面外壳的透明程度(0% = 完全不透明(正常界面,用宿主自己的表面色)、100% = 完全透明(看到壁纸))—— 它与模糊互不影响:模糊 0 时照样按它透出,只是背后壁纸是清晰的。 另外:透明度 = 0 时插件完全不覆盖宿主(不写背景/不写模糊/不动宿主 token)。 两者对整个界面外壳生效(左栏/标题栏/右栏/dock 共用同一套表面 token)。

5. 界面虚化(blur)

面板文案内部键默认程度键 / 默认关
跟随统一虚化blurFollowUnify开开 = 被接管的项(左栏磨砂/标题栏磨砂/右侧边栏·dock)与统一值一致;其中任一项你自己调过之后就独立;关 = 全部独立;重新打开 = 清空独立标记—
虚化对话框dialogBlur开dialogAmount 14px关
虚化设置面板settingsBlur开settingsAmount 14px关
虚化下载/确认弹窗confirmBlur开confirmAmount 12px关
虚化弹层popoverBlur开popoverAmount 10px;另有 popoverAlpha 94% 表面不透明度关
虚化遮罩(全屏背景)maskBlur开maskAmount 8px关
右侧边栏/dock 虚化rightSidebarBlur开rightSidebarBlurAmount 14px + rightSidebarAlpha 45%;跟随统一虚化时两项都被接管关

6. 其他(other)

面板文案内部键默认作用关闭 / 回退
轻度锐化sharp开提升低清 GIF 观感;卡顿请关关
Deep diving 背景方框thinkBg关开 = 思考状态显示模糊背景方框关
任务列表磨砂todoBlur关todo 卡片背景模糊关
第三方 UI 圆角兼容roundCompat关兼容第三方插件圆角关
自适应文字色 + 蓝色清理aquaInk关文字色随遮罩亮度自适应 + 品牌色统一(配 aquaInkColor)关
深底文字可读增强aquaTextEnhance关文字双色描边(近似方案)关
≥4K 源自动降 1080presMax(自动写 1920)自动检测到 ≥4K 且宿主转码可用、且你没设过「分辨率上限」时,自动把该壁纸降到 1080p(每张壁纸一次;?autocap=off 关闭;设置里可改回)?autocap=off
纯 Scene 壁纸渲染方式sceneRender—⚠ 有按钮、有写入,无读取点(未接线)—
场景渲染上报(排障)sceneReport开壁纸每 10s 把渲染器现场写到 reports/关
场景首帧看门狗sceneWatchdog开超时未出画自动回退静态帧;等待时长 sceneWatchdogSecs 8s(3–30)关
重试渲染器 / 渲染器调试参数 / 扩展钩子地址sceneDebugParams / sceneExtUrl空白名单透传(ln/eyehack/audit/isolate/parallax/…);扩展钩子按 extbase 拼进 iframe清空 / 一键清空
一键诊断上报——收集子系统状态 → POST /api/mpkg-wallpaper/diag;宿主不可用则下载 JSON—
诊断开关速查(渲染器)——常用渲染器诊断开关 + 「复制」URL 片段(见 §6.2)—
better-sidebar 适配bsCompat / bsFloat / bsFont / bsReveal / bsRevealAlpha / bsAqua

7. 测试项(liquid)

面板文案内部键默认作用关闭 / 回退
测试模式总开关lgTest关只保留壁纸 + 悬浮 + 布局,禁用全部外观类关
液态玻璃(CSS 版)lgCss关纯 CSS/SVG 折射 + 高光(不占 WebGL 上下文,可与场景壁纸共存)关 / URL ?lgcss=off
折射强度lgCssAmount14px0–40(0 = 纯模糊)—
输入框 / 左侧边栏 / 标题栏液态玻璃lgComposer / lgSidebar / lgHeader关各自选择作用目标(JS 打 [data-mpw-lg-css] 标记)关
独立演示页(端口 3081)——tools/liquid-demo/ 的 WebGL2 演示页(独立服务,不影响插件)—

没有面板控件的设置键

这些键存在且参与逻辑,但设置页里没有对应控件;只能通过备份导入、localStorage 手工改写或 URL 参数触达 (tools/switch-wiring-test.mjs 有「只影响运行时」的白名单与理由)。

键默认说明
clock / clock24h / clockSec / clockDate / clockPos / clockSize关 / 开 / 关 / 关 / tr / 40时钟是运行时兼容项:旧配置仍会渲染,设置页已无开关
bsAlpha关better-sidebar 面板跟随主题底色;CSS 有读取点,面板无控件
bsBottomAvoid关已定案的故意空操作(对齐交给 better-sidebar 自己的 ResizeObserver)
newStyle关只改设置页控件外观(JS 选 className),不进 buildCss
forceEnabled关冲突检测下手动强开的运行时优先级标记
opacity82「面板不透明度」滑条已删除(统一虚化下由 sidebarAlpha 取代);值仍被读取
aquaTintStrength45面板取色的壁纸主色混合比例;运行时读取,无控件
glassColor / glassAlpha空 / 12早期 WebGL 液态玻璃的遗留键:只随备份导出/导入与「恢复默认」走动,无控件、无读取点
webInteractionpointer网页壁纸交互档位(off/pointer/full):无面板控件,用 URL ?mpwinteract=… 或写存档
sceneRendererUrlhttp://127.0.0.1:8902/webloader/场景渲染器地址,可覆盖(默认 = 一站式测试台 :8902 直供的 /webloader/;旧默认是 :8899)
npVolume100Now playing 卡片里的音量电平(0..100,落到真实元素);默认档从不写元素音量,只有你动过才写
glassWindow—已退役删除:无控件、无读取点,功能已被 settingsBlur + dialogBlur/popoverBlur 覆盖;源码与 zh/en 字典 0 残留

选择器行为契约(选择文件夹 / 选择文件)

「自定义目录」「可调参数里的目录/文件属性」用的目录选择器自己持有滚动主权(历史 bug:滚轮一滚就弹回顶部、 行被重渲染后 scrollTop 归零、滚轮串联给宿主设置面板)。当前契约:

行为契约说明
滚动位置保持刷新 / 过滤 / 条目变少 / 500 项大目录 / 宿主重渲染 / 容器节点被重建后,滚动位置都在原位(不会出现"跳回顶"的一帧)
不抢焦点打开弹窗只把焦点给列表容器自己且带 focus({preventScroll:true});行一律 tabindex="-1" + mousedown 阻止默认聚焦 ⇒ 任何行都不会成为 document.activeElement
每个目录各自记位置A 目录滚到 60、B 目录滚到 20,来回切换互不串位
滚轮不串联列表滑到边界后不会带着背后的设置面板一起滚
行级增量更新目录刷新只增删差集(行 key = 完整路径,测试断言行节点 uid 不变)
锚点缺失不回 0记住的位置若超出新列表范围 ⇒ 夹到新范围;记忆值缺失/非法一律当"无锚点" ⇒ 认领当前位置
按键行为
↑ / ↓上下移动活动行(不抢焦点、只在按键时做最小位移 block:"nearest")
Home / End跳到第一个 / 最后一个目录
Enter进入活动行对应目录;未选中任何行时 = 「选择此文件夹」
Backspace / Alt+↑上一级目录
Esc关闭弹窗

回归:node tools/dir-picker-test.mjs(A 组为源码级断言,对旧实现会变红 ⇒ 用例有分辨力;B 组用假 DOM + 迷你 React 跑生产实现的切片)。 细节、根因与修法:docs/DIR-PICKER-SCROLL.md。


6. URL 开关速查

6.1 插件侧 URL 逃生口(刷新即生效,不改设置)

参数作用
?hdrfrost=legacy|off标题栏磨砂:旧门控 / 彻底关
?hdrblur=pseudo|element磨砂载体:伪元素 / 元素层对照
?railink=off关右侧时间线条的反色补偿
?sbfill=wide恢复旧的全局侧栏底色覆盖
?lgcss=off一键回退液态玻璃
?mpwtranscode=legacy|aggressive视频转码:回旧行为 / 连用户设的上限也先探测
?mpwinteract=1|on(自动进入交互)/ off|0|pointer|full(仅改档位,不自动进入)网页壁纸交互
?mpwstore=0|mem关帧内存储 facade / 只留内存不落盘
?mpwpersist=legacy设置持久化回旧行为
?bgwrapfix=legacy、?hdrfrostwatch=off壁纸层可见性 / 磨砂看门狗
?autocap=off关「≥4K 源自动降 1080p」
?webframe=auto|sandbox|compat临时覆盖网页壁纸帧模式(不改设置)
?npvoice=keep|drop交互期音频分类:保留 / 丢弃(语料实测清单只剩 BGM.wav)
?npaudit=0关音频审计(hook play/volume/muted/new Audio/AudioContext,有界环形 ≤200,可疑转变即上报 /diag)
?hiddengate=legacy隐藏闸门整族回旧行为(后台挂载/冻结/切页时不再拦我们的起播与重试;A/B 与线上救急用。默认档=页面隐藏时一律不起播、隐藏时停住所有我们的出声面、回到可见按当时策略恢复;详见 docs/WALLPAPER-LIFECYCLE.md §6.4)

6.2 渲染器侧诊断开关(纯 Scene 壁纸)

这两个数字口径不同,别混:

  • 渲染器开关主表当前 238 条(读数来自渲染器仓的 node tests/diag-flag-check.mjs,它把代码开关与主表双向对拍), 主表在渲染器仓:docs/README-DIAGNOSTICS.md。
  • 插件面板里只放常用/逃生口那一张小表(common:true 集合,当前 11 个),拼在渲染器地址后面用,例如 http://127.0.0.1:8902/webloader/?id=3719111841&audit=3:
开关用途默认
att=legacy附件锚点走旧自算路径(A/B 对照)新路径
mcc=1强制网格包围盒中心补偿关
piv=1 / piv=0子网格 pivot 全开 / 全关只对眼睛组合生效
align=0复现旧对齐(origin 恒几何中心)官方对齐
parallax=legacy鼠标视差退回旧近似式官方公式
gyro=1 / gyro=0移动端姿态源强制开 / 完全不监听auto(有细指针不启用、触摸设备启用)
audio=1播放场景 sound 层(每层一条流)静音
whitefallback=0缺纹理层改透明白块(与官方一致)
hier=0放弃父链合成,回退绝对定位兜底父链合成
isolate=<层名>只保留名字含关键词的层可见(逗号分隔)全可见
audit=N首帧逐层审计 N 帧1

这些是渲染器的 URL 参数,不是本插件的设置;插件只负责把它们拼进场景 iframe。面板文案与离线副本必须与渲染器 web/diag-flags.json 的 common 集合一致,由 tools/panel-smoke.mjs 断言。


7. Now playing 与壁纸声音

这节说明左侧栏那个播放器挂在哪、显示什么、能控什么——它控制的是壁纸自己的声音。 (本节按符号名引用实现,行号会随版本漂移,以符号为准。)

  • 挂载点:宿主 slot sidebar.footer.action(createSlotAction 的注册项:id:"mpw-now-playing"、order:60)。拿不到 slot 时 resolveAnchor() 按模式降级:slot → settings-slot → settings-area → foot;一条都不成立就不建任何节点并打一行 console.warn。锚点晚出现也照样挂上:找不到落点时盯住文档,宿主 slot 出口渲染出来后自动补挂。
  • 让位(默认开的配套):occupantOf() 逐个看容器子节点,放行三类——我们自己的节点、宿主自有节点、实质空节点;剩下第一个即算「占用者」⇒ 不挂(挂载前)或撤下(挂载后),写 data-mpw-np-yield="foreign-occupant" 并打一行可读 warn;占用者走了会自己回来。判据是双向的。
  • 左侧栏收起即隐藏:data-mpw-np-hidden + CSS display:none。判据以物理宽度优先(shouldHide():量到 ≥ NP_COLLAPSE_MAX_W = 96 就不隐藏),宿主信号只在宽度量不到时兜底。宽度不够时整体按 --mpw-np-fit = clamp(avail/260, 0.5, 1) 缩放。
  • 形态:一颗胶囊展开成卡片——封面、标题/副标题、进度条 + 时钟、整块点击热区。展开态四个键:上一首 / 播放-暂停 / 下一首 / 静音-取消静音;收起态三个键(静音键随卡片出现,受几何约束)。
  • 数据源(npResolveMedia:只报我们真的知道的东西):
当前壁纸NP 显示能控什么
视频壁纸(当前真的在放的那个 <video>)真实播放状态 + 时长/进度;明确知道没有音轨时副标题写「该视频没有音轨」播放 / 暂停 / 静音-取消静音(判断不了有没有音轨时不猜);没有曲目清单 ⇒ 上一首/下一首如实 disabled
壁纸目录里真实存在的音频文件文件名 + 清单序号;进度与时长来自媒体元素我们自己的 <audio>:播放 / 暂停 / 上一首·下一首按清单顺序环形切换(只有一条 ⇒ 两侧键 disabled)/ 静音
网页壁纸(目录里没有独立音频)副标题写「网页壁纸声音」只有静音这一条通道(canPlay=false,不假装能暂停帧内 WebAudio)
无源(静态图 / 清单还没到 / 场景无独立音轨)空闲态(曲名 = 未在播放)不显示"点了没用"的键;点播放给出面板提示 + console 一行,不做假动作
  • 两个控制(NP-4):① 音量电平 —— 卡片里的音量条,设置键 npVolume(0..100),真的落到元素;默认档从不写元素音量,只有你动过才写;② 可拖动进度(seek) —— 拖进度条即定位。两者都受下面这个开关管辖。
  • 「播放/暂停同时控制壁纸」(npLinkWallpaper,默认开):开 = 传输键与进度条同时驱动壁纸自身的播放/进度;关 = 只驱动本插件自己的播放器,壁纸媒体一个字节都不碰;壁纸媒体是唯一声源时控件如实 disabled 并在副标题说明。
  • 做不到的(明确列出,不做假动作;docs/NOW-PLAYING-DSH.md §7.7.7 与 §7.8):没有系统媒体源时不去猜(系统媒体源见 §8);web 壁纸帧内那份声音只有静音,它自己的播放/暂停做不到;视频壁纸没有上一首/下一首;静音键只在展开态出现;心形按钮不渲染;没有波形、没有键盘快捷键;包里(scene.pkg)的音轨只能列清单、不能播;进度条可拖动,但联动关掉或没有可定位媒体时如实不可拖。
  • 回退:把 npNowPlaying 关掉(或「恢复所有默认设置」)⇒ 回到零注入(不建 DOM、不装观察者、产物里一行 NP 规则都没有)。回归:node tools/now-playing-test.mjs 与 node tools/np-media-test.mjs,都在 tools/check.sh 第 2 步。
  • 归属:组件为 Bencho 的 "Now playing"(MIT)逐行移植(注释原文保留);侧栏挂载控制器、让位判据、自绘图标、token 映射、数据接入与门禁是本仓自写。登记见 THIRD-PARTY.md §6。

8. 系统媒体会话(MPRIS / SMTC)

这节说明「显示系统正在播放什么」这条链路的宿主半边:能力矩阵、诚实不可用路径。

lib/media-session.js(MIT,本仓自写,零第三方代码)是「Now playing 显示系统正在播放什么」这条链路的宿主半边。契约:createMediaSession({run, platform, env, now, timeoutMs, log}) → {probe(), snapshot(), control(op,arg), stats(), lastProbe()}。

能力矩阵

平台通道适配器(按优先级)元数据 / 状态 / 进度 / 封面控制
Linux / FreeBSD / OpenBSDMPRIS over D-Bus(org.mpris.MediaPlayer2.*)playerctl → dbus-send一次调用取 7 个字段:status / mpris:length / position / xesam:title / xesam:artist / xesam:album / mpris:artUrlplay pause playpause next prev seek
Windows 10/11SMTC(GlobalSystemMediaTransportControlsSessionManager)smtc(powershell.exe -NoProfile -NonInteractive)真 WinRT 调用取属性 / 时间线 / 播放控制 / 缩略图(转 base64 data URL)同上(op 与位置作为独立 argv 元素下发)
macOS——❌ 未实现:unsupported-platform,0 条命令❌
其它 / 无适配器—none❌ not-installed❌
  • 形状:snapshot 21 个键恒在,拿不到就是空/中性值(duration/position 单位毫秒,拿不到是 null,不编 0);available:true 时 title 非空。
  • 没有桌面会话总线时如实显示不可用:probe() 会真的探测(dbus-send --session ListNames,必要时退 busctl --user list),拿不到就回 available:false / reason:'no-session-bus'。
  • 绝不抛异常:snapshot() / control() 永不 reject;失败全部是返回值(reason 落在固定取值集合内)。
  • 安全:命令名与参数分开传(argv 数组,从不经过 sh -c);播放器名白名单,不合规 ⇒ bad-player + 0 条命令;op 白名单 + seek 范围 0..24h;超时默认 800ms(50–5000ms);读操作单飞 + 全局串行。
  • 零依赖:只用 node:child_process;package.json 里没有新增任何依赖。
  • 环境变量:MPW_MEDIA_ADAPTER(强指适配器)、MPW_MEDIA_PLAYER(钉播放器名)、MPW_MEDIA_TIMEOUT_MS。
  • 接线现状(如实):已接线 —— 宿主 GET /api/mpkg-wallpaper/media-session(21 键快照)/ POST /api/mpkg-wallpaper/media-control(六个 op,能力位先判)/ GET /api/mpkg-wallpaper/media-art(file:// 封面代理);客户端 npSystemMedia* 自适应轮询(有系统媒体 2s、本机无会话总线 30s)⇒ 卡片显示真实系统曲目/封面/进度,本机无总线时如实 available:false / no-session-bus。
  • 判据:node tools/media-session-test.mjs(契约/三适配器解析/诚实能力判定/参数化控制/超时/并发去重)与 node tools/media-session-wiring-test.mjs(接线面);细节见 docs/MEDIA-SESSION.md。

9. 诊断与排障

出问题先来这里:一次点击把状态发回本机宿主;只有需要缩小范围时才打开个别诊断开关。

  • 一键诊断上报(「其他」tab):把磨砂/侧栏/时间线是否被影响、壁纸类型与路径、shim 是否注入、视频解码、表面 token、场景健康打成一个 payload → POST /api/mpkg-wallpaper/diag,落在 ~/.dsh/.dsh-mpkg-wallpaper/diag-<epochms>.json(目录上限 50 个文件 / 32MB;客户端单份上限 512KB)。宿主不可用时自动改为下载 mpw-diag-<ISO>.json,离线也能把状态发回来。字段表带 provenance,读不到就是 value:null + degraded(docs/DIAGNOSTICS.md)。
  • 后台自动上报:开关是 localStorage['mpwdiag']='1'(不是 URL 参数——DSH 鉴权 303 会剥掉 query),刷新后在载入 6 秒时上报一次(每会话 ≤6 次);window.onerror 走同一采集器。
  • 插件侧 URL 逃生口:见 §6.1。
  • 渲染器侧诊断开关:见 §6.2。

宿主路由的来源闸门(P-204):三处 ACAO 回显白名单化(/raw、场景音频、缩略图上报,外加 /lg 静态 JS):只放 Origin: null(沙箱帧)与 http://127.0.0.1:3080|8899|8902(含 localhost);非白名单一个 Access-Control-Allow-* 都不发。非 GET 写请求过闸门:Sec-Fetch-Site(有则必须 same-origin/none)+ Origin 白名单;/scene-thumb-token 与 /settings 连 GET 也过闸。/custom-dir 拒敏感目录;/raw 的 file 有扩展名白名单。回退口(默认关,排障用):MPW_CSRF=0、MPW_CORS_LEGACY=1、MPW_CORS_ORIGINS=a,b、MPW_CUSTOM_DIR_ALLOW_ANY=1;GET /api/mpkg-wallpaper/security 只读播报当前生效值。完整规格见 docs/SECURITY-ROUTES.md,判据 node tools/sec-route-guard-test.mjs。

网页帧同源逃逸 + 可控上游(P-205):自动降档落点恒为沙箱档(allow-scripts,不透明源);入站消息同时校验 ev.origin 与"这个帧应有的来源";compat 只能由用户显式设置。设置里的外链只认 http(s) 回环 / "与页面同主机的字面 IP" / 显式白名单(sceneUrlWhitelist);场景令牌 st 只在目标过闸门时下发;非法目标一律拒绝使用(回落默认回环)+ 记账 window.__mpwSceneUrlGuard + console.warn + /diag 信标。判据(都在 tools/check.sh 第 5 步):node tools/web-frame-origin-guard-test.mjs 与 node tools/scene-url-token-guard-test.mjs。


10. 兼容性、限制与做不到清单

浏览器兼容性(实测参考)

浏览器推荐度表现与注意
Chrome / Chromium(桌面)⭐⭐⭐ 强功能最完整:backdrop-filter 与 color-mix 实现最佳、iframe.muted 生效、muted 自动播放放行
Edge(桌面)⭐⭐⭐ 强视频壁纸走独立 canvas 渲染路径(规避 Edge 悬浮工具栏);个别版本仅有首帧静态(非空白/崩溃)
Firefox⭐⭐ 中功能全支持(backdrop-filter 103+、编码不支持自动转码兜底);有三点减分,见下表后的说明
Android WebView / 移动端⭐⭐ 中偏弱autoplay 政策取决于宿主 WebView 配置;getBattery 可能缺失(有守卫跳过);极端组合建议静态图/GIF 或关 blur

Firefox 的三点减分:① backdrop-filter 性能弱于 Chromium(多模糊同开时低端机掉帧);② iframe.muted 不支持 ⇒ 有声 web 壁纸首次可能被自动播放策略拦停首帧;③ color-mix 需要 113+(旧版只有外观回退)。 源码已为各浏览器做了降级(无 requestVideoFrameCallback 回退 rAF、ResizeObserver/getBattery 有守卫、全部 play() 带 .catch、backdrop-filter 用 CSS.supports 检测并降级)。

没有 Wallpaper Engine 安装时(缺失 / 非 Windows)

「WE 安装」指 Steam 版 Wallpaper Engine(appid 431960)。宿主端 locateWallpaperEngine() 按这个顺序找:Windows 注册表 → 常见 Steam 目录 → 非 Windows 的 Steam 目录(macOS / Linux / Android / WSL)→ 各库 steamapps/libraryfolders.vdf 里含 431960 的库 → 只认 <库>/steamapps/common/wallpaper_engine/wallpaper32.exe 存在的那一个。找不到就返回 null,后续走降级路径:

场景真实行为
没装 WE(或找不到 wallpaper32.exe)steam-inventory 返回 200 {ok:true, installDir:null, wallpapers:[]} —— 不是错误、不抛 500
点「扫描本地壁纸库」列表空 + 顶部报错条「未检测到壁纸引擎安装」;空列表另有「未发现可用的壁纸」。扫描本身不报错
装了 WE 但素材目录都不存在每个根目录单独判存在 ⇒ 清单为空、且不弹「未检测到安装」;界面只剩空提示。未实现:这种情况没有专用提示
非 Windows / 移动端同"没装 WE"(注册表分支直接在非 win32 返回 null)
WE 原生播放列表只在 installDir 存在且 config.json 可解析时才有;否则写 rotSeeded:true 并不再重播种
宿主端整体不可用(方式四没装/端口不通)探测 /ping 失败 ⇒ 回退纯浏览器模式;超过 600MB 的素材无法处理
ffmpeg 缺失ffmpeg-check 返回 200 {ok:true, found:false, …};面板显示"未安装",只在点按后才走下载链,可直读的视频不转码

一句话:没有 WE 安装 = 少了"自动发现本地壁纸库"这一条便利通道,插件照常工作;手动目录、直接导入、URL/本地文件、场景提取与诊断都不依赖 WE,所有降级都是"返回空清单 + 明确文案 + 保留手动通道",不静默失败、也不报 500。

场景(Scene)壁纸适配现状

结论先说:WE 场景壁纸无法在 Web 端完整还原,这是引擎层面的限制。 场景由专有引擎渲染——Live2D 式木偶骨架(.mdl 二进制)、shader 特效、脚本;浏览器没有官方渲染器,格式也未公开(RePKG 只逆向过 PKG/TEX,MDL 骨架无公开文档)。

插件提供两条路径:

  1. 外部渲染器 iframe(首选):本机渲染器(默认 http://127.0.0.1:8902/webloader/,旧默认 :8899)在线时,场景以 iframe 挂载。渲染器离线/首帧超时则由看门狗回退静态帧并在提示条说明,可手动「重新挂载渲染器」。渲染器地址可用 sceneRendererUrl 覆盖。
  2. 容器内素材提取(兜底,lib/pkg-extract.js,MIT,采用自 elysia395/dsh-wallpaper-engine):
    • 静态帧:解析 PKG(LZ4 解压)+ TEX 纹理解码,按"面积 × 格式权重 × 路径惩罚"选主纹理
    • 图层合成:解析 scene.json 的全部 image 图层,按源坐标/尺寸在 canvas 上合成(最多 24 层)
    • 内嵌视频时段:scene.pkg 与 mpkg 同为 PKG 容器,含内嵌视频纹理的时段按 mpkg 方式解析 → 多时段切换

无法覆盖的:MDL 木偶人物(纹理层几乎为空)、shader 波浪/粒子、脚本交互。这些回退官方预览动图(preview.gif)。

格式与上限(lib/pkg-extract.js):PKG 魔数 PKGV####;TEX TEXV0005 + TEXI0001,mipmap 容器 TEXB0001–0004;可解码像素格式 = RGBA8888 / R8 / RG88 / DXT1 / DXT3 / DXT5(内嵌 JPEG/PNG 直通),其余抛出 unsupported format;尺寸上限 16384、mip ≤32、帧数 ≤4096。

需要完整动态效果的现实路径:外部渲染成视频 → 用本插件的视频壁纸功能。

网页壁纸(Web,实验性)

  • 类型判定按内容,不只看声明:detectWebWallpaperKind() 返回四态 web / scene / video / unknown,project.json 的 general.type 只是线索——谎报 web 但目录里是 scene.pkg 的按场景处理,谎报 scene/video 但只有 index.html 的按网页处理;application/exe/app 一律 unknown/excluded-application。
  • 两条加载模式(确认弹窗里选,模式记在 URL 里,刷新后照旧):
    • 沙箱模式(默认,推荐):sandbox="allow-scripts"(不透明源)。宿主在入口 HTML 的 <head> 最前注入 WE API shim,?mpwshim=1 是注入闸门。壁纸脚本读不到宿主 DOM / localStorage / cookie;帧内 fetch() 是跨源(Origin: null),宿主只对字面量 null 回 CORS 头
    • 兼容模式(同源):allow-scripts allow-same-origin allow-pointer-lock。Live2D 类的「网页壁纸选项」(分辨率/语言/音量,写同源 localStorage)需要它
  • WE API shim(注入在作者脚本之前):wallpaperPropertyListener、wallpaperRegisterAudioListener、wallpaperRegisterMedia{Properties,Thumbnail,Playback,Timeline,Status}Listener、wallpaperRequestRandomFileForProperty、wallpaperMediaIntegration、wallpaperPluginListener
  • 存储持久化:帧内 facade(真 localStorage 一读就抛时安装)+ 宿主 POST/GET /api/mpkg-wallpaper/web-store,按壁纸隔离;上限 64 键 / 单值 4096 字符 / 每壁纸 64KB / 最多 64 张壁纸,落 ~/.dsh-mpkg-wallpaper/web-store.json
  • 风险预检:⚠重动画(目录里有 .skel/.atlas 或名字含 spine/live2d,深度 ≤3)与 🌐外网(入口 HTML 前 256KB 含 http(s)://),只在 type === "web" 时显示;也可直接查 GET /api/mpkg-wallpaper/web-probe?folder=|ltoken=
  • CSP:命中阻断型 CSP 时不注入 shim、回原字节并加 x-mpw-shim-skipped: csp(这一处照抄上游 web-rewrite.ts,MIT,登记在 THIRD-PARTY.md §5);客户端 2.5 秒没收到 ready 则去掉标记在沙箱档内重载一次(不自动升同源)
  • 交互模式:壁纸层是背景层(不吃指针),点右下角「交互」按钮或 URL ?mpwinteract=1 后,指针/滚轮/触摸(full 档再含键盘与文本输入)会被送进壁纸内的作者脚本;一定会退出——60 秒无操作 / 180 秒总时长 / Esc / 右上角「退出交互」/ 切换壁纸。⚠ ; 只改档位、。交互、

细节(类型判定表、sandbox 逐项理由、shim API 表与控制协议、交互注入方案与安全边界、文件 URL 改写、错误边界、与参考实现的差异清单):docs/WEB-WALLPAPER.md。 回归:node tools/web-wallpaper-test.mjs + node tools/web-interaction-test.mjs(都在 tools/check.sh 第 5 步)。

安全说明

  • 默认无被动对外网络请求:插件后台不主动访问外部网络;日常播放只与本机 DSH 宿主(127.0.0.1)通信。例外都是用户显式触发:检查更新/一键更新访问 GitHub、下载 ffmpeg 访问 GitHub Releases / npm 二进制镜像;打开设置面板后 0.8s 会自动静默检查一次版本(只点亮徽标,不弹窗、不下载、不上传)。此外用户手输的网络图片 URL、网页壁纸自身加载的资源也属外部访问。
  • 无敏感内容:node tools/secret-scan-test.mjs 扫描全部 tracked 文件(凭据模式 + 本机路径模式)必须 0 命中。
  • 数据边界:所有解析在本机完成;localStorage 只存背景与参数;设置与网页帧内存储落在 ~/.dsh-mpkg-wallpaper/(诊断快照落在 ~/.dsh/.dsh-mpkg-wallpaper/)。
  • 系统媒体会话模块:命令名与参数分开传(argv 数组,从不经过 sh -c),播放器名白名单 + op 白名单 + seek 范围校验,不合规 ⇒ 0 条命令;超时后 SIGKILL。

11. 开发与测试

改完代码怎么自证没坏:一条命令跑完 12 步门禁。

bash tools/check.sh                    # 12 步全量门禁(默认档:键未变且上次真跑为绿 ⇒ 跳过,打印 SKIP-CACHED)
bash tools/check.sh --full             # 忽略缓存,12 步逐条真跑(CI / 发版 / 怀疑缓存时的权威档)
bash tools/check.sh --list             # 只列出 12 步与每步缓存状态 + 当前输入指纹,然后退出
bash tools/check.sh --quick            # 跳过组合矩阵(第 3 步)
node tools/integrity-check.mjs         # 文件齐全、元数据、白名单、无本机路径、客户端自包含、发布包内容
node tools/secret-scan-test.mjs        # 凭据 0 命中、本机绝对路径 0 命中、白名单无腐烂条目
node tools/style-scope-guard.mjs       # 末行口径:RED / REVIEW 必须为 0
node tools/switch-wiring-test.mjs      # 每个开关都必须真的改变产物(或按理由登记为"只影响运行时")
node tools/panel-smoke.mjs             # 面板渲染 + 语言字典 + 常用开关表与 diag-flags.json 一致
node tools/build-now-playing.mjs       # NP 生成区内联(生成物与源漂移即红)
node tools/build-audio-bus.mjs         # 音频总线生成区内联
node tools/build-bundle.mjs --check    # 宿主端单文件 bundle 与源码对拍
node tools/bundle-equivalence-test.mjs # bundle 构建可复现 + 路由逐字段对拍 + 装载布局 + 变异对照

断言条数不写死:各脚本的通过条数会随版本增加,请以实跑输出的汇总行为准(例:✓ 全部通过(pass=… fail=0))。 tools/check.sh 的锁与增量缓存只落 os.tmpdir()(可用 MPW_GATE_CACHE / MPW_GATE_LOCK 覆盖),仓库里不写本机绝对路径。

tools/check.sh 的 12 步:① 语法 ② 面板冒烟 + P-66 面板健壮性/语言回归 + 选择器回归 + 壁纸层可见性 + 持久化 + Now playing(生成区漂移 + 声音接线两套独立判据)③ CSS 组合矩阵(512 全组合 + 600 随机 + 边界)④ 场景看门狗/调试参数 ⑤ 沙箱与场景 token + 网页壁纸 shim + 转码资源 + P-204/P-205 安全闸门 ⑥ 发布完整性自检 ⑦ 音频扫描提速 ⑧ scene 视频索引 ⑨ 真机复刻 A/B(需无头 Firefox)⑩ better-sidebar 适配 ⑪ 单文件 bundle 等价性 ⑫ 样式作用域护栏 + 表面 token 命名空间。

提交前门禁(秒级 pre-commit):

git config core.hooksPath .githooks    # 装载(只影响本机 clone;git config --unset core.hooksPath 卸载)
git commit --no-verify                 # 单次绕过
MPW_SKIP_PRECOMMIT=1 git commit -m …   # 单次绕过(走脚本内显式口,恒 exit 0)

跑 tools/panel-smoke.mjs + tools/switch-wiring-test.mjs(串行),不跑 12 步门禁;暂存区只动了非产物路径时直接跳过;缺 node/缺脚本 ⇒ 打印一句就 exit 0。细节见 docs/PRE-COMMIT.md。


12. 文件结构

dsh-mpkg-wallpaper/
├── package.json      # 版本 + dsh.bundle + dsh.client 声明;files 白名单 = 发布面
├── cordis.patch.yml  # 插件安装声明(dsh plugin add 使用)
├── LICENSE           # MIT
├── THIRD-PARTY.md    # 第三方来历/洁净室记录与许可归属(随包发布)
├── icon.svg
├── README.md / README.en.md
├── lib/
│   ├── index.js            # 宿主端:上传/Range 流式播放、场景提取、音频清单、
│   │                       #   网页壁纸与 shim、web-store、media-audio、设置持久化、
│   │                       #   诊断、更新、ffmpeg、系统媒体会话(MPRIS/SMTC)等路由
│   ├── client.js           # 浏览器端(宿主按 exports["./client"] 单文件下发):mpkg 解析 + 设置页 +
│   │                       #   背景 DOM + 虚化体系 + 壁纸库 + 时间变化 + 网页设置 + 播放/省电 + NP 挂载
│   │                       #   内含多个**生成区**(勿手改):MPW-NP-GEN / MPW-AUDIO-BUS / MPW-DIRPICK /
│   │                       #   MPW-DIAG-SUBSYS / MPW-PROPS-MODEL / MPW-THUMB / MPW-WEJSON / MPW-BLOBRETRY
│   ├── audio-bus.js        # 音频总线(由 tools/build-audio-bus.mjs 内联进 client.js 的 MPW-AUDIO-BUS 区)
│   ├── pkg-extract.js      # scene.pkg 静态帧 / 图层合成 / 音轨索引 / 内嵌视频索引(MIT,来自 elysia395)
│   ├── web-wallpaper.js    # 网页壁纸:内容优先类型判定 + WE API shim 源码 + 入口注入 + 跨源策略 + 存储 facade
│   ├── web-interaction.js  # 网页壁纸交互:坐标换算 / 事件整形(含 touch)/ 状态机 / 舞台契约(MIT,自写)
│   ├── media-session.js    # 系统媒体会话宿主侧适配器(MPRIS / SMTC;**已接线**)
│   ├── now-playing.js      # Now playing 组件 + 侧栏挂载控制器(Bencho MIT 逐行移植 + 本仓的锚点/收起/让位判据)
│   ├── now-playing-math.js # Now playing 纯数学(零 DOM)
│   ├── liquid-glass/       # 遗留 WebGL 液态玻璃库(**仓库保留 · 不进发布面**)
│   └── liquid-glass-bundle.js  # 上者的打包产物(**仓库保留 · 不进发布面**)
├── tools/            # 门禁/测试/基准/探针(**不进发布包**):
│                     #   check.sh(12 步门禁)、pre-commit.sh、integrity-check.mjs、secret-scan-test.mjs、
│                     #   panel-smoke.mjs、switch-wiring-test.mjs、style-scope-guard.mjs、
│                     #   token-namespace-test.mjs、now-playing-test.mjs、np-media-test.mjs、
│                     #   media-session-test.mjs / media-session-wiring-test.mjs、
│                     #   web-wallpaper-test.mjs、web-interaction-test.mjs、
│                     #   build-now-playing.mjs / build-audio-bus.mjs / build-bundle.mjs(生成器与漂移门禁)、
│                     #   bundle-equivalence-test.mjs、gate-cache.mjs、真机探针(需 :3080 + headless Firefox)
├── docs/             # 研发笔记(**不进发布包**):WEB-WALLPAPER.md / NOW-PLAYING-DSH.md / MEDIA-SESSION.md /
│                     #   DIAGNOSTICS.md / RELEASE.md / WALLPAPER-LIFECYCLE.md / SECURITY-ROUTES.md /
│                     #   STYLE-SCOPE-GUARD.md / TOKEN-NAMESPACE.md / PRE-COMMIT.md / HEADER-FROST.md /
│                     #   TIMELINE-RAIL-TOKEN.md / TRANSCODE-*.md / DIR-PICKER-SCROLL.md / GATE-PERFORMANCE.md
└── dist/             # 构建产物(**不入库、不进包**):dsh-mpkg-wallpaper.bundle.mjs(方式四用,现生成)

排除规则:lib/liquid-glass/**、lib/liquid-glass-bundle.js、lib/**/*.bak* 由 files 负向模式排除;tools/、docs/、dist/、package-lock.json 不在 files 白名单里。tools/integrity-check.mjs 对"不在发布面"和"仓库内不能少"做双向机器断言。 lib/now-playing.js / lib/now-playing-math.js / lib/audio-bus.js 是源 + 生成内联形态:宿主把 exports["./client"] 指向的那一个文件整体下发,lib/client.js 里出现任何相对 import/require 线上就会模块解析失败 —— 判据是 tools/integrity-check.mjs。代价是必须有漂移门禁,所以生成器与产物对拍常驻在门禁第 2 步与第 11 步。


13. 许可与归属

  • 本包许可:MIT(LICENSE;package.json 的 license 字段 = "MIT")。第三方来历、洁净室记录、逐项归属与"抄了什么/为什么抄/哪些不是抄的"全部登记在 THIRD-PARTY.md(随包发布,是 MIT 署名义务的载体)。
  • 唯一 vendored 的第三方代码是 lib/liquid-glass/**(液态玻璃渲染器库):自 P-127 起移出发布面(files 负向模式),仓库内一个不少,仍如实登记全部 sha256(THIRD-PARTY.md §1.3)。宿主的 /api/mpkg-wallpaper/lg/* 托管路由仍是活路径(命中时真的读 lib/liquid-glass/<file>),从 npm 安装的副本上按设计返回 404。
  • Now playing 组件:Bencho 的 "Now playing"(MIT)逐行移植(注释原文保留);侧栏挂载控制器、自绘图标、token 映射与门禁为本仓自写(THIRD-PARTY.md §6)。
  • 网页壁纸:lib/web-wallpaper.js 的 API 名单与语义参考 oneincase/webwallgl(MIT),未 vendored;其中 hasBlockingCsp 一处照抄(逐行出处见 THIRD-PARTY.md §5)。差异清单见 docs/WEB-WALLPAPER.md §10。
  • 场景提取:lib/pkg-extract.js 采用自 elysia395/dsh-wallpaper-engine(MIT,文件头署名);音频索引段已依 docs/AUDIO-TRACK-SPEC.md 洁净室重写。
  • GPL 边界(永不进插件):MIT 插件 → GPL 渲染器 ✅;GPL 渲染器 → MIT 插件 ❌(本包只出不进)。本包不得 import / 内嵌渲染器(GPL-3.0-or-later)的任何代码,与渲染器的交互只走进程/HTTP 协议。若将来引入任何其它第三方代码(含 GPL-3.0 的渲染器侧代码),不得进入本 MIT 包。机器判据:tools/web-wallpaper-test.mjs F1(注释剥离后 grep:无 GPL 派生标识符、无 GPL 许可文本)。
  • 参考项目:dsh-bg-image(MIT,模板)、unmpkg(GPL-3.0,仅参考 mpkg 二进制格式)、repkg(MIT,仅研究 .tex 格式)。
  • 致谢:Bil812(PR #2 的取色/自适应文字色/统一遮罩构想 → 已吸收为 Aqua 实验模式,全部可开关、默认关)、elysia395/dsh-wallpaper-engine(场景提取器与"设置持久化到宿主端文件""Edge canvas 兼容渲染"思路)、oneincase/webwallgl(网页壁纸沙箱 + WE API shim 的 API 名单与语义参考)、 社区(收录与推广)。

命名说明:本插件对接的渲染器产品名为 WEwebLoader(渲染器仓的 npm 包名与仓库名保持不变,见该仓 README)。


14. 反馈 Bug

反馈问题时附上这些材料,一轮就能定位:

  • 原始 .mpkg 或 workshop 文件夹(复现问题所必需)
  • 一次「一键诊断上报」的结果(设置页「其他」→ 一键诊断上报;宿主不可用时会自动下载 JSON)
  • 浏览器控制台输出(F12 → Console),如有
  • 你的 DSH 版本与平台(Windows / Linux / 移动端)

更长的设计取舍、根因复盘与逐轮读数在工作区的研发笔记里(docs/,不进发布包):样式作用域护栏 docs/STYLE-SCOPE-GUARD.md、 表面 token 命名空间 docs/TOKEN-NAMESPACE.md、标题栏磨砂 docs/HEADER-FROST.md、右侧时间线条 docs/TIMELINE-RAIL-TOKEN.md、 转码资源与生命周期 docs/TRANSCODE-RESOURCE.md / docs/TRANSCODE-LIFECYCLE.md、选择器行为契约 docs/DIR-PICKER-SCROLL.md、 发布记录 docs/RELEASE.md。

清空 = 只允许回环
水平翻转(镜像)flipX关壁纸左右镜像关
垂直翻转(镜像)flipY关壁纸上下镜像关
解码帧率上限fpsCap无限制源帧率超限时宿主 ffmpeg 抽帧转码(24/30/48/60)选「无限制」
分辨率上限resMax原始分辨率ffmpeg 缩放(720p/1080p/2K,保持宽高比)选「原始分辨率」
视频倍速playbackRate1x0.5–2x(档位 0.5/0.75/1/1.25/1.5/2)1x
ffmpeg 状态——显示系统/缓存/环境变量来源;未装可下载,缓存装的可卸载(不动系统)—
可调参数(折叠区)propEdits空可改且改完即生效:mpkg 场景壁纸走 P-203 跨源属性通道(mpw-user-props,渲染器回执确认;见 docs/WE-USER-PROPS.md §3);网页壁纸走 shim 同源通道(分辨率/语言/音量等)壁纸级重置
磨砂模糊blur12px壁纸层模糊(0–40)0
镜头缩放zoom100%10–2000%100%
画面亮度brightness100%50–150% 滤镜100%
镜头位置(平移)lensX / lensY0 / 0水平/垂直平移,各自 ±20000
省电·页面隐藏/切页暂停powPauseHidden开visibilitychange关
省电·失焦暂停powPauseBlur关blur/focus关
省电·电池供电暂停powPauseBattery关getBattery;API 缺失静默跳过关
开 / 关 / 关 / 关 / 62% / 关
见上文;仅在检测到 better-sidebar 时显示
总开关关 = 全部不生效
备份与恢复——导出/导入 BACKUP_FIELDS 白名单内的设置(不含当前壁纸与扫描目录)—
恢复所有默认设置 / 前往反馈 / 检查更新——重置外观数值;一键更新从 GitHub 拉最新代码—
窗口失焦不会退出
?mpwinteract=full
不自动进入
不放宽沙箱
不读帧内 DOM
  • 作者脚本报错不拖垮插件:帧内 shim 兜住 listener 异常 / 全局 error / 未捕获 Promise,限流上报父页
  • 已知限制:音频频谱通道仍为空(WE 的频谱语义是系统音频,拿壁纸自身声音当频谱是语义造假,故不伪造);innerHTML 里拼出来的 file:/// 不覆盖;绝对系统路径映射不了;被导航到外部的页面拿不到 shim
  • awesome-dsh-plugin