# 游戏素材大师 · 详细工程文档 > 本文档由 README 的完整版迁来,保留算法细节、自检契约与历史踩坑记录。 > 简洁的入门文档见 [../README.md](../README.md)。 --- # 游戏素材大师 · DSH 插件 从一张设定图出发,批量产出游戏要用的角色素材。**火山方舟 Seedream** 负责生图, **MiniMax** 负责图生视频,抠绿幕与合成全部在本地用 ffmpeg + 内置 JS 完成—— 不需要任何系统图像库,也不需要把素材传到第三方服务。 插件包含四个功能模块,共用同一套 API 配置与抠像默认值: | 模块 | 做什么 | |---|---| | **八方向图生成** | 一张人物设定图 → 8 方位 × 8 帧精灵图(含行走动画验收与 WASD 操控预览) | | **图片生成** | 按提示词出图,可带参考图 → 可一键抠绿幕导出透明 PNG | | **序列帧生成** | 首帧图 **或** 参考图+参考视频 → 生成视频 → 抽帧 → 抠像 → 横向合成,并可循环播放预览 | | **骨骼动画生成**(实验性) | 角色整图 → 自动拆件 → 装配定位 → 推骨骼与动画(待机/行走/奔跑/挥手/跳跃/攻击)→ 打包 Spine 图集 | > ⚠️ 骨骼动画生成是**实验性模块**:界面上页签带角标、每次进入弹窗说明、模块内常驻提示条 > (`RigExperimentalDialog` / `RigExperimentalBar` / `MODULES[].experimental`)。功能不完善, > 共建入口见 [GitHub 仓库](https://github.com/universe-st/dsh-game-material-master)。 每个阶段都有独立的验收界面:看图、改提示词、单独重跑、打「通过」。任何一步不满意都可以只重做那一步。 四个模块的**全部功能都可以通过对话调用**:agent 用工具驱动同一条流水线, 多步流程(八方向图这种)能自己推进、等待、审查,也可以在每一步停下来让你验收—— 详见下面的[对话调用](#对话调用agent-也能驱动整条流水线)。 --- ## 一些绕不开的坑(先说,省得踩) - **不要用「剪影」这个词写提示词。** 实测生图模型会按字面把角色画成纯黑轮廓。 - **提示词里要区分「转身」和「视线」。** 只写「朝画面左上方」时模型会理解成抬头仰视, 必须补一句「只绕竖轴转身,禁止抬头低头,视线始终水平」。 - **图生视频不保证守住纯色背景。** 同一段素材里有的帧背景保持绿色,有的会逐渐打光成橙黄渐变。 所以抠像不能只认绿色——见下面的「抠像」。 - **重复提交会白花钱。** 三个模块都做了重复提交拦截:同一张图 / 同一段视频在跑时再点一次会被拒绝。 agent 走对话调用时同样受这条约束(工具层不重复拦一次,报错信息才清楚)。 --- ## 对话调用:agent 也能驱动整条流水线 插件挂载时会把自己的控制面注册成一组模型工具,并追加一段系统提示词, 约定**固定流程**与验收协议。所以「帮我做个八方向的角色」这句话本身就能跑完整条链路。 ### 工具 | 工具 | 作用 | |---|---| | `game_material_intake` | **固定流程第 0 步**:按真实状态算出「还缺哪些关键参数」与「必须先解决的阻塞」,并把「自动审核 / 每步人工审核」这个必问项一起交出来 | | `game_material_call` | 万能通道:插件界面上有的功能都能调(63 个方法,含配置、提示词、抠像参数、删除等),描述里逐个列了入参与用途 | | `game_material_upload` | 按**本机路径**上传素材(源图 / 参考图 / 首尾帧 / 参考视频),宿主自己读盘,不用把 base64 贴进对话 | | `game_material_reviewMode` | 记录用户选的审核模式,存在项目 / 任务上;界面与对话读写同一份 | | `game_material_status` | 读进度:项目 / 任务清单,或某个目标的阶段进度与产物 URL | | `game_material_wait` | 阻塞等待「没有任务在跑」或超时(默认 120s,上限 900s),回来就是可审查状态 | | `game_material_review` | 出**验收包**:每个产物的绝对 URL、状态、通过标记、报错与建议的下一步 | | `game_material_approve` | 打「通过 / 取消通过」(八方向图按阶段+方位,图片按张,序列帧按步骤,骨骼动画按阶段+部件) | 底层没有第二套实现:工具直接复用界面用的那个 Typert 远程服务,所以 「界面上做到的事」与「对话里做到的事」永远是同一件事、同一份数据。 ### 固定流程 ``` 第 0 步 先问,再动手 agent 必须先用 game_material_intake 把缺的参数问清楚, 并且必须问「自动审核 还是 每一步人工审核」——合并成一次提问。 两个问题都拿到答复之前,不允许调用任何生成 / 删除类方法。 第 1 步 逐阶段推进(八方向图:images → videos → frames → sheet; 骨骼动画:parts → layout → rig → atlas,其中只有 parts 花钱) 每次提交类调用之后立刻 game_material_wait。 第 2 步 每步都审:game_material_review 看逐项 status / error / URL。 第 3 步 按审核模式分岔 auto → agent 自己判断没问题就 approve 并进入下一步 manual → 贴出验收链接并停下等用户回复,用户说「通过」才继续 ``` 审核模式也可以在界面上直接改(四个模块都有下拉),因为它就是同一份数据。 没设置时界面显示「未设置(对话里会先问)」。 ### 点链接切界面 工具返回里的 `openUrl` 是给用户点的深链接,形如: ``` http://127.0.0.1:43120/?dsh-gmm=1&module=sprite&project=p…&stage=videos ``` agent 会把它原样写成 Markdown 链接贴出来。用户点一下: - 浏览器半区装了**捕获阶段的点击拦截器**,命中就 `preventDefault` 原地切到 「游戏素材大师」面板,并落到对应模块 / 项目 / 阶段——不跳转、不新开标签; - 若用户用中键 / Ctrl+点击强制新开标签页,链接会真的被打开,应用在 `/?dsh-gmm=…` 上正常启动,插件读到参数后完成同样的切换(两条路径共用同一份意图)。 为什么链接必须是 `http(s)`:会话正文的 Markdown 渲染器对链接做了协议白名单 (只放行 http/https/mailto),自定义 scheme 会被丢掉、连 `` 都不生成。 又因为宿主不知道对外 origin(可能被反代改写),浏览器半区会在挂载时把自己真实的 `location.origin` 上报给宿主(`reportClientOrigin`)。没收到上报时退化成 `http://localhost` —— 拦截是按参数匹配的,origin 不对也不影响点击。 拦截器只认 `dsh-gmm` 参数,其余链接(含站外的)一律放行。 --- ## 安装 ```bash dsh plugin --profile web add /path/to/dsh-game-material-master ``` 装完**重启 DSH**(新增 bundle 只在启动时读取)。 > **改了代码之后**:浏览器半区是按磁盘上的 `lib/client.js` 现取的,**刷新浏览器**就能用上; > 宿主半区(工具注册、系统提示词、远程方法)是启动时装入的,**必须重启 DSH**。 > `node scripts/verify-live-bundle.mjs` 可以确认运行中的宿主到底在提供哪一版浏览器束。 - 需要宿主提供 `webServer` 与 `typert`,二者由 `@deepseek-ai/dsh-base` / `dsh-web-app` 提供,无需额外依赖。 - 需要 **ffmpeg / ffprobe** 在 `PATH` 上(macOS:`brew install ffmpeg`), 也可用 `FFMPEG_PATH` / `FFPROBE_PATH` 指定绝对路径。设置页会显示探测结果。 - 本包**没有任何运行时 npm 依赖**:`zod`、`@deepseek-ai/dsh-typert-protocol`、`@deepseek-ai/cordis` 都从 DSH 自身的安装树解析,避免出现两份不同版本的实例。 > 从旧版本(`dsh-8dir-sprites`)升级时,首次启动会把数据目录 `8dir-sprites/` > 整体迁移到 `game-material-master/`,已有项目和配置无缝接上。 ## 配置 **设置 → 游戏素材大师**: | 项 | 说明 | |---|---| | 火山方舟 API Key | 「测试连接」会**真实生成一张 1K 小图**(产生少量费用),同时验证 Key 与模型 / 接入点 | | 生图模型 | 默认 `doubao-seedream-4-0-250828`;也可选 4.5 / 5.0 Lite / Pro,或填自定义接入点 ID | | MiniMax API Key | 「测试连接」只查一个不存在的任务,**免费**,能区分 Key 无效与其它错误 | | 视频模型 | 默认 `MiniMax-H3`。选 H3/H3-Max 自动走 v2 协议,选 Hailuo/I2V 走 v1;**优云智算版 H3** 在同一个下拉里显式选择 | | Base URL | **主机根**,不含 `/v1`、`/v2`。国内站 `https://api.minimax.cn`,国际站 `https://api.minimaxi.com`。选中「优云智算版 H3」时该字段固定为 `https://cp.compshare.cn`、不可编辑 | | 默认参数 | 单格宽高、抽帧张数与工作尺寸、像素块边长、抠像阈值等 | Key 只写入本机 `/game-material-master/config.json`,回传界面时始终脱敏(只给尾号)。 > **模型是插件级设置,三个模块共用。** 「生图模型」「视频模型」只在设置页里改, > 图片任务 / 序列帧任务内部**不允许**再存一份自己的模型副本——模块里那两个字段是 > 只读展示。原因:网关地址与 API Key 都是全局的,任务里若留一份旧模型快照, > 切换模型后就会把请求打到错误网关(实测:任务存官方 H3 + 全局切优云智算 → > `cp.compshare.cn/v2/…` 404)。任务在保存与提交时会自动对齐当前模型, > 时长 / 分辨率档位也一并按当前模型收敛。 ### 视频参数与模型的对应关系 | 视频模型(下拉选项) | 协议 | 分辨率 | 时长 | |---|---|---|---| | `MiniMax-H3` | v2 | `2K` / `768P` | 4~15 秒 | | `MiniMax-H3 优云智算` | v2 | `2K` / `1080P` / `768P` | 4~30 秒 | | `MiniMax-H3-Max` | v2 | `768P` / `480P`(不支持 2K) | 5~15 秒 | | `MiniMax-Hailuo-02` | v1 | `768P` / `1080P` | 6 / 10 秒 | | `I2V-01` / `I2V-01-Director` | v1 | `720P` | 6 秒 | > **优云智算版 H3** 是 MiniMax H3 的第三方网关版:与官方 H3 是同一个模型,但走 > `https://cp.compshare.cn`,请求路径多一层 `/minimax`(`/minimax/v2/video_generation`), > 分辨率支持 1080P 后置超分,时长放宽到 4~30 秒。 > > 它是一个**显式选项**:在「视频模型」下拉里选择 `MiniMax-H3 优云智算` 即启用, > 插件**不会**根据 Base URL 或 Key 前缀自动判断。选中后 Base URL、路径前缀、 > 分辨率/时长档位全部自动跟着它走;切回官方模型时 Base URL 自动还原。 切换模型时非法值会被自动收敛(例如从 Hailuo 换到 H3 时 `1080P` → `2K`)。 **参考图 / 参考视频模式是 v2 才有的能力**,选 v1 模型时会明确报错而不是静默失败。 --- ## 模块一:八方向图生成 ### 方位约定 这是 **RPG 地图上的八方向行走**,不是「抬头 / 低头」。约定画面上方为北: | 方位 | 屏幕朝向 | 能看到什么 | |---|---|---| | **北 N** | 朝画面**上**方走 | 后脑勺,**完全看不到脸** | | **东北 NE** | 朝画面右上走 | 斜背面,**完全看不到脸** | | **东 E** | 朝画面**右**走 | **右侧脸**(纯侧面) | | **东南 SE** | 朝画面右下走 | 正脸,转向右侧约 45° | | **南 S** | 朝画面**下**方走 | **完整正脸** | | **西南 SW** | 朝画面左下走 | 正脸,转向左侧约 45° | | **西 W** | 朝画面**左**走 | **左侧脸**(纯侧面) | | **西北 NW** | 朝画面左上走 | 斜背面,**完全看不到脸** | 提示词把**转身**(`{facing}`)和**可见部位**(`{visibility}`)分成两段写, 这是为了避开上面说的「抬头」坑。 ### 生成顺序 依赖是**有向的**,所以生成也一层层来;同层内并发(并发数可配): | 顺序 | 方位 | 参考图 | |---|---|---| | 1 | 南(正对镜头) | 源图 | | 2 | 北(背对镜头) | 南 | | 3 | 西南 / 东南 | 南 | | 4 | 西北 / 东北 | 北 | | 5 | 西 / 东 | 南 **+** 北 | 重新生成某个方向时,依赖它的下游会自动标成 **「需重做」**。 ### 阶段①的两种生成方式:转圈截帧(默认)与逐方向生图 `Project.imageMode` 决定阶段①怎么产出那八张 `images/<方向>.png`;**两条路的产物形态完全相同**, 所以阶段②(行走视频)、③(抽帧)、④(整图)完全不必知道用的是哪一种。 | | `turn` 转圈截帧(默认) | `direct` 逐方向生图(备选) | |---|---|---| | 怎么来 | 一段「原地匀速转一整圈」的绿幕视频,按时间轴截出八个方向 | 八个方向各自一次 Seedream 生图,按依赖顺序 | | 花费 | 一次视频调用(几分钟) | 八次生图调用 | | 一致性 | **好**:八个方向同源(同一个角色、同一段光线、同一套画风) | 一般:模型每次都要「重新理解」角色,脸型/发色/服装容易漂移 | | 清晰度 | 受视频分辨率限制(默认 768P/2K) | 受生图分辨率限制(默认 2K,更高) | | 可调 | 时间轴上八个圆圈,随时重切(本机、免费) | 每个方向单独重跑 | 新项目默认 `turn`;**老项目**(还没有 `imageMode` 字段时建的)自动沿用 `direct`—— 它们已经有八张图了,直接跳到空白的转圈页只会让人以为产物丢了。切换用 `setImageMode({projectId, mode})`,切换**不删任何产物**。 转圈模式的三步: 1. `runTurnVideo({projectId})`:一次 MiniMax 调用,整圈只有这一段视频。首帧优先用 已经存在的 `images/front.png`(正面绿幕图),没有就退回源图——源图不一定是绿幕, 所以提示词里明确要求「纯色绿幕 #00FF00」,由模型把背景重画成绿幕。实际用的是哪张 记在 `turn.video.firstFrame` 里,排查「第一帧就不是正面」时全靠它。 2. 视频落地后宿主**自动**抽候选帧(本机 ffmpeg,免费):默认 32 张,按 `fps = 张数 / 时长` 均匀取样,第 i 张对应 `i × 时长 / 张数` 秒;同时把整圈缩略条带 写进 `turn/strip.png`——界面上那八个圆圈就是对着这条条带拖的。 3. 按 `turn.frames.picks`(八个方向各自选中第几帧)把八张方向图切出来,覆盖 `images/<方向>.png`。这一步只读 `turn/raw.bin` 缓存,所以拖动圆圈是**本地、免费**的。 **为什么位置必须可拖**:默认位置假设「视频从正面开始、匀速转满一圈、方向是顺时针」, 而模型经常不遵守——起步有一两秒静止、转速前快后慢、或者干脆往反方向转。任何一种都 会让八个默认位置整体偏掉,所以轴上给了八个圆圈(`setTurnPick({projectId,key,index})`) 和「换个转圈方向重排」(`resetTurnPicks({projectId,direction})`)。拖动只重切那一张, 但会**作废该方向的行走视频与序列帧**(它们拍的是另一个朝向),整图同样作废。 改候选帧数(`saveSettings({turnFrameCount})`,8~64)会**自动重抽**,并把用户拖过的位置 按比例换算(32 帧里的第 12 帧 → 8 帧里的第 6 帧);直接保留下标会把八个位置整体打乱。 另外,八个位置在**第一次**抽帧时按这次的张数重新等分——否则「新建项目默认 32、第一次 却抽 16 张」时,四个方向会一起被夹到最后一帧。 ### 统一附加提示词 「八方向绿幕图」这一步有一个**统一附加提示词**输入框:非空时会被追加到**每一张**生图 提示词末尾,用来写跨方向的共同注意事项(例如「必须穿同一双靴子」「不要出现文字」)。 改一次全部生效,不必逐个方向去改。每个方向仍然可以单独覆盖自己的提示词。 ### 行走视频 提示词要求**固定机位 / 固定背景 / 原地走三步**。八个任务并发提交,宿主后台每 15 秒轮询一次; **提交完可以离开页面**,插件重启后还会把没跑完的任务接上。 某个方向不满意可以点**「重新生成」**:宿主会先作废这一段旧视频**和它抽出来的序列帧** (整图同样作废,需要重新抽帧再合成),然后重新提交——帧是从视频里抽的,不重抽就会 把上一版动作混进整图。**其它方向不受影响**。工具栏的「生成全部视频」只提交还没完成的 方向,已经成片的不会重跑;要是八个方向都已完成,它会直接告诉你该点哪个按钮而不是 转一圈了事。 ### 抽帧与合成 `ffmpeg` 用 `fps = 帧数 / 视频时长` 按时长平均取样。抽帧抽到的是**工作尺寸** (长边上限,默认 768),不是最终格子尺寸——自动裁剪、统一缩放和像素量化都在 JS 里做, 这样八个方向才能共享同一个裁剪框、脚底对齐同一条基线。 ### 行走预览 用 **WASD 或方向键**操控角色,验证八方向接起来顺不顺: - 角色以**脚底中心**为锚点,帧推进按**走过的距离**而不是时间——步频和移动速度才对得上 - 「播放速度」只改步频快慢,「移动速度」只改走得多快,两者互不影响 - 切图用的是**整图自己记录的**行序与格子参数,所以改完行序即使还没重新合成,预览也不会取错方向 - 需要**点击画面取得键盘焦点**后才响应按键,避免和输入框抢键 --- ## 模块二:图片生成 按提示词出图,可选带参考图(最多 10 张;多张时可在提示词里写「图一」「图二」)。 每张生成完,若开着抠像会自动抠一遍;也可以**把已有图片直接传进来只做抠像**—— 这样它同时也是一个通用的绿幕抠像工具。 - 生成张数 1~8,按 Seedream 刊例约 0.2 元/张 - 每张可单独重新生成、删除、下载透明 PNG - 每张会记录**背景占比**,用来判断抠像是否可信(占比异常说明绿幕没生成好) - 每张可单独打「通过」,也可以一键全部通过;对话里的 `game_material_approve` 改的是同一份标记 --- ## 模块三:序列帧生成 两种输入模式,**平台规定互斥**: - **首尾帧模式**:上传首帧图(必填)+ 尾帧图(选填) - **多模态参考模式**:上传参考图(≤9 张)+ 参考视频(≤3 段,每段 2~15 秒) > 参考视频要转成 base64 内联在请求里,平台请求体上限 64 MB,所以本地文件卡在 40 MB; > 更大的文件平台要求改用公网 URL。 流程:**生成视频 → 抽帧(张数可配)→ 抠像 → 横向合成**,其中抽帧完成后会自动接着抠像与合成。 界面里可以: - 播放生成出来的视频(`