🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

TapTap 制造助手 swyaoguai/dsh-taptap-maker-dev

DeepSeek 客户端
swyaoguai4 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

TapTap Maker 本地开发的 DSH 插件:额度红线、可更新游戏 skills、自建生图/CC0…

36.5/100
综合分
5
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/31 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/swyaoguai/dsh-taptap-maker-dev.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/10/23·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 4 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-taptap-maker-dev(未发布到 npm,仅可源码安装)
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/29 04:17:28

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 169 处,展示前 103 条)
  • 执行外部命令来自配置/变量
    index.js:179
    const child = spawn(bin, args, { cwd, env, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] })
  • 发起网络请求
    index.js:676
    const response = await fetch(url, {
  • 读取密钥环境变量
    index.js:1182
    const mmxKey = mmx.apiKey || (process.env.MINIMAX_API_KEY ?? '').trim()
  • 读取密钥环境变量
    index.js:1237
    const mmxKey = (readMinimaxConfigRaw(home).apiKey || (process.env.MINIMAX_API_KEY ?? '')).trim()
  • 读取密钥环境变量
    index.js:1294
    const mmxKey = (readMinimaxConfigRaw(home).apiKey || (process.env.MINIMAX_API_KEY ?? '')).trim()
  • 读取密钥环境变量
    index.js:1360
    const mmxKey2 = (readMinimaxConfigRaw(home).apiKey || (process.env.MINIMAX_API_KEY ?? '')).trim()
  • 读取密钥环境变量
    index.js:1408
    const key = cfg.apiKey || (process.env.MINIMAX_API_KEY ?? '').trim()
  • 读取密钥环境变量
    index.js:1446
    const key = (merged.apiKey || (process.env.MINIMAX_API_KEY ?? '')).trim()
  • 执行外部命令来自配置/变量
    index.js:1481
    const child = spawn(process.execPath, argv, { detached: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:1548
    const child = spawn(process.execPath, argv, { detached: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:1618
    const child = spawn(process.execPath, argv, { detached: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:1968
    const out = spawnSync(process.execPath, argv, { encoding: 'utf8', maxBuffer: 8 * 1024 * 1024 })
  • 执行外部命令来自配置/变量
    index.js:2130
    const out = spawnSync(process.execPath, [cli, '--probe', target], { encoding: 'utf8', maxBuffer: 4 * 1024 * 1024 })
  • 发起网络请求
    client.js:146
    fetch(`${API_BASE}/policy`, { headers: { accept: 'application/json' } })
  • 发起网络请求
    client.js:157
    fetch(`${API_BASE}/policy`, {
  • 写入剪贴板
    client.js:228
    await navigator.clipboard.writeText(text)
  • 发起网络请求
    client.js:265
    const r = await fetch(`${API_BASE}/bgm-file?name=${encodeURIComponent(name)}`)
  • 发起网络请求
    client.js:447
    const r = await fetch(`${API_BASE}/bgm-library`, { headers: { accept: 'application/json' } })
  • 发起网络请求
    client.js:576
    const r = await fetch(`${API_BASE}/bgm-${mode}`, {
  • 发起网络请求
    client.js:770
    fetch(`${API_BASE}/bgm`, { headers: { accept: 'application/json' } })
  • 执行外部命令来自配置/变量
    src/taptap-image.mjs:208
    const probe = spawnSync(bin, ['-version'], quiet)
  • 执行外部命令来自配置/变量
    src/taptap-image.mjs:210
    const r = spawnSync(bin, [...pre, src, '-resize', `${wh.w}x${wh.h}`, dst], quiet)
  • 执行外部命令来自配置/变量
    src/taptap-image.mjs:217
    const r = spawnSync(bin, ['-c', py], quiet)
  • 发起网络请求
    src/taptap-image.mjs:285
    response = await fetch(url, {
  • 发起网络请求
    src/taptap-image.mjs:336
    const img = await fetch(item.url, { signal: AbortSignal.timeout(120000) })
  • 发起网络请求
    src/taptap-image.mjs:494
    response = await fetch(url, {
  • 发起网络请求
    src/taptap-image.mjs:517
    response = await fetch(url, {
  • 发起网络请求
    src/taptap-image.mjs:554
    const img = await fetch(item.url, { signal: AbortSignal.timeout(120000) })
  • 执行外部命令来自配置/变量
    src/taptap-audio.mjs:114
    const r = spawnSync(ffmpeg, ['-y', '-hide_banner', '-loglevel', 'error', '-i', src,
  • 执行外部命令来自配置/变量
    src/taptap-gpt.mjs:117
    const r = spawnSync(bin, ['-c', 'import playwright; print(1)'], { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    src/taptap-gpt.mjs:137
    spawnSync(process.execPath, ['-e', 'setTimeout(()=>{},400)'], { stdio: 'ignore', timeout: 3000 })
  • 执行外部命令来自配置/变量
    src/taptap-gpt.mjs:211
    const ch = spawn(py, [tmp], {
  • 执行外部命令来自配置/变量
    src/taptap-zaiduyu.mjs:81
    const r = spawnSync(bin, ['-c', 'import sys; print(sys.version_info[0])'], {
  • 执行外部命令来自配置/变量
    src/taptap-zaiduyu.mjs:188
    const child = spawn(py, [zaiduyuScriptPath(), ...argv], {
  • 执行外部命令来自配置/变量
    src/taptap-sfx.mjs:56
    const r = spawnSync(bin, ['-c', 'import sys; print(sys.version_info[0])'], {
  • 执行外部命令来自配置/变量
    src/taptap-sfx.mjs:112
    const r = spawnSync(py, [sfxEnvScript(), subcommand, ...extra], {
  • 执行外部命令来自配置/变量
    src/taptap-sfx.mjs:130
    const child = spawn(py, [sfxEnvScript(), subcommand, ...extra], {
  • 执行外部命令来自配置/变量
    src/taptap-sfx.mjs:208
    const r = spawnSync(py, buildGenArgv(sfxGenScript(), prompt, {
  • 执行外部命令固定命令
    src/taptap-skills-update.mjs:160
    const result = spawnSync('git', ['clone', '--depth', '1', repoUrl, dest], {
  • 发起网络请求
    src/taptap-skills-update.mjs:172
    const response = await fetch(url, { signal: AbortSignal.timeout(60000) })
  • 发起网络请求
    src/audio-library.mjs:50
    const response = await fetch(page, { headers: { 'User-Agent': UA }, signal: AbortSignal.timeout(timeoutMs) })
  • 发起网络请求
    src/audio-library.mjs:70
    const response = await fetch(url, { headers: { 'User-Agent': UA }, signal: AbortSignal.timeout(timeoutMs) })
  • 执行外部命令固定命令
    src/audio-library.mjs:76
    const r = spawnSync('powershell', [
  • 发起网络请求
    src/taptap-bgm-web.mjs:62
    const response = await fetch(site.url, {
  • 执行外部命令来自配置/变量
    src/taptap-bgm-web.mjs:116
    const r = spawnSync(bin, ['-c', 'import playwright; print(1)'], { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    src/taptap-bgm-web.mjs:152
    spawnSync(process.execPath, ['-e', 'setTimeout(()=>{},400)'], { stdio: 'ignore', timeout: 3000 })
  • 执行外部命令来自配置/变量
    src/taptap-bgm-web.mjs:210
    const child = spawn(py, [tmp], {
  • 执行外部命令固定命令
    src/taptap-bgm-web.mjs:580
    const r = spawnSync('powershell', ['-NoProfile', '-Command',
  • 执行外部命令固定命令
    src/taptap-bgm-web.mjs:591
    const r = spawnSync('esentutl', ['/y', cookieFile, '/d', tmp, '/o'],
  • 读取密钥环境变量
    src/paths.js:808
    process.env.TAPTAP_IMAGE_API_KEY,
  • 读取密钥环境变量
    src/paths.js:877
    apiKey: pick(fromFile.apiKey, process.env.MINIMAX_API_KEY) ?? '',
  • 读取密钥环境变量
    src/paths.js:929
    const envKey = str(process.env.MINIMAX_API_KEY)
  • 读取密钥环境变量
    src/paths.js:961
    const envKey = (process.env.MINIMAX_API_KEY ?? '').trim()
  • 写入本地文件
    src/video-sequence.mjs:95
    mkdirSync(path.join(root, sub), { recursive: true })
  • 读取本地文件
    src/video-sequence.mjs:356
    if (!existsSync(legacy)) return undefined
  • 读取本地文件
    src/video-sequence.mjs:360
    if (existsSync(target)) return target
  • 写入本地文件
    src/video-sequence.mjs:362
    renameSync(legacy, target)
  • 读取本地文件
    src/video-sequence.mjs:381
    if (typeof job.dir !== 'string' || !existsSync(job.dir)) {
  • 读取本地文件
    src/video-sequence.mjs:383
    if (target && existsSync(target)) {
  • 读取本地文件
    src/video-sequence.mjs:444
    const head = readFileSync(file).subarray(0, 16)
  • 读取本地文件
    src/video-sequence.mjs:464
    if (!existsSync(source)) throw new Error(`读不到文件:${source}`)
  • 写入本地文件
    src/video-sequence.mjs:475
    mkdirSync(path.dirname(dest), { recursive: true })
  • 写入本地文件
    src/video-sequence.mjs:476
    writeFileSync(dest, readFileSync(source))
  • 删除本地文件
    src/video-sequence.mjs:618
    rmSync(tmp, { force: true })
  • 删除本地文件
    src/video-sequence.mjs:624
    rmSync(tmp, { force: true })
  • 写入本地文件
    src/video-sequence.mjs:947
    writeFileSync(absPath(home, id, target), bytes)
  • 写入本地文件
    src/video-sequence.mjs:1003
    mkdirSync(path.dirname(dest), { recursive: true })
  • 删除本地文件
    src/video-sequence.mjs:1042
    if (existsSync(dest)) rmSync(dest, { force: true })
  • 删除本地文件递归
    src/video-sequence.mjs:1055
    rmSync(backupDir, { recursive: true, force: true })
  • 删除本地文件递归
    src/video-sequence.mjs:1065
    rmSync(staging, { recursive: true, force: true })
  • 删除本地文件
    src/video-sequence.mjs:1071
    if (!expectedNames.includes(name)) rmSync(path.join(destDir, name), { force: true })
  • 发起网络请求
    src/minimax-video.mjs:336
    response = await fetch(url, { ...init, signal: timeout })
  • 发起网络请求
    src/minimax-video.mjs:530
    const response = await fetch(url, { signal: timeout })
  • 请求外部主机www.minimax.cn
    src/minimax-video.mjs:599
    const response = await fetch('https://www.minimax.cn/v1/token_plan/remains', {
  • 发起网络请求
    src/minimax-video.mjs:599
    const response = await fetch('https://www.minimax.cn/v1/token_plan/remains', {
  • 读取本地文件
    src/minimax-video.mjs:664
    const bytes = readFileSync(file)
  • 发起网络请求
    src/video-relay.mjs:274
    response = await fetch(url, { ...init, signal: timeout })
  • 读取本地文件
    src/video-relay.mjs:306
    const bytes = readFileSync(filePath)
  • 发起网络请求
    src/video-relay.mjs:310
    response = await fetch(url, { method: 'POST', headers, body: bytes, signal: timeout })
  • 发起网络请求
    src/video-relay.mjs:463
    const response = await fetch(url, { headers, signal: timeout })
  • 发起网络请求
    src/video-relay.mjs:570
    const response = await fetch(url, { headers, signal: AbortSignal.timeout(Math.max(60_000, timeoutMs || 300_000)) })
  • 读取本地文件
    src/video-relay.mjs:616
    const bytes = readFileSync(file)
  • 执行外部命令固定命令
    src/win-proc.mjs:63
    spawnSync('powershell', ['-NoProfile', '-Command', script], { stdio: 'ignore', timeout: timeoutMs })
  • 执行外部命令固定命令
    src/win-proc.mjs:81
    const probe = spawnSync('powershell', ['-NoProfile', '-Command', script], { encoding: 'utf8', timeout: timeoutMs })
  • 执行外部命令来自配置/变量
    src/taptap-audio-convert.mjs:65
    const probe = spawnSync(name, ['-version'], { stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    src/taptap-audio-convert.mjs:79
    const r = spawnSync(bin, [
  • 执行外部命令来自配置/变量
    src/taptap-audio-convert.mjs:97
    execFile(bin, [
  • 执行外部命令来自配置/变量
    src/taptap-audio-convert.mjs:200
    const r = spawnSync(bin, args, { encoding: 'utf8' })
  • 执行外部命令来自配置/变量
    src/taptap-audio-convert.mjs:231
    const r = spawnSync(bin, ['-y', '-hide_banner', '-loglevel', 'error', ...inputs,
  • 执行外部命令来自配置/变量
    src/reference-image-preparation.mjs:208
    try { child = spawn(bin, args, { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }) }
  • 执行外部命令固定命令
    src/video-media.mjs:51
    const out = execFileSync('reg.exe', ['query', key, '/v', name], {
  • 读取本地文件
    src/video-media.mjs:83
    if (!existsSync(packages)) return []
  • 读取本地文件
    src/video-media.mjs:86
    for (const pkg of readdirSync(packages)) {
  • 读取本地文件
    src/video-media.mjs:89
    for (const inner of readdirSync(base)) {
  • 读取本地文件
    src/video-media.mjs:91
    if (existsSync(bin)) out.push(bin)
  • 读取本地文件
    src/video-media.mjs:117
    const found = candidates.find((c) => path.isAbsolute(c) && existsSync(c))
  • 执行外部命令来自配置/变量
    src/video-media.mjs:140
    child = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] })
  • 读取本地文件
    src/video-media.mjs:413
    const bytes = readFileSync(jpegOut)
  • 写入本地文件
    src/video-media.mjs:437
    writeFileSync(listFile, pngFiles.map((f) => `file '${f.replace(/'/g, "'\\''")}'`).join('\n'), 'utf8')
  • 删除本地文件
    src/video-media.mjs:446
    try { rmSync(listFile, { force: true }) } catch { }
  • 发起网络请求
    src/audio-sources.mjs:91
    const response = await fetch(url, { headers, signal: AbortSignal.timeout(timeoutMs) })
  • 发起网络请求
    src/audio-sources.mjs:261
    const response = await fetch(item.url, { headers, signal: AbortSignal.timeout(60000) })
  • 执行外部命令固定命令
    src/win-focus.mjs:53
    const r = spawnSync('powershell', ['-NoProfile', '-Command', script], { encoding: 'utf8', timeout: 15000 })
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:www.minimax.cn

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(87 字)↓

TapTap Maker 本地开发的 DSH 插件:额度红线、可更新游戏 skills、自建生图/CC0 音效/MiniMax BGM 通道,全部不消耗 Maker 内置额度

README

由 DeepSeek 最新模型翻译生成
dsh-taptap-maker-dev 为 TapTap 制造(Maker) 本地开发而生的 DeepSeek Harness 插件:守住「不花冤枉钱」的额度红线,接入可更新的游戏开发技能,并提供自建的图片 / 音效 / BGM 素材通道——全部走你自己的 Key 或 CC0 素材库,不消耗任何 Maker MCP 内置额度。 章鱼默认模型与免费素材优先 设置页 →「生成通道」→「章鱼生图(积分站)」:点「模型价目」,选定模型后点「保存默认模型」。模型单独保存,不重新登录、不提交账号密码、不改通道顺序或开关。 后续调用按「本次明确模型 > 已保存默认」执行,不每次重问;没有默认或模型失效时安全停止,绝不使用站点默认/第一项或替你改模型。原始 Python 脚本必须传 --model;插件包装层会自动传入你选过的默认。 HTTP 409「请刷新页面以获取服务器分配」不等于账号未登录。插件先执行站点的服务器分配握手,再向分配节点提交一次请求,站点 Cookie/凭据不传给节点;分配失败不会提交生图。超时/结果未知、旧异步错误不自动重投;低余额提醒不会把未知结果误判为额度拒绝。实际费用与任务状态以站点为准。
展开完整文档(README 剩余 1 节)
dsh-taptap-maker-dev

为 TapTap 制造(Maker) 本地开发而生的 DeepSeek Harness 插件:守住「不花冤枉钱」的额度红线,接入可更新的游戏开发技能,并提供自建的图片 / 音效 / BGM 素材通道——全部走你自己的 Key 或 CC0 素材库,不消耗任何 Maker MCP 内置额度。

章鱼默认模型与免费素材优先

设置页 →「生成通道」→「章鱼生图(积分站)」:点「模型价目」,选定模型后点「保存默认模型」。模型单独保存,不重新登录、不提交账号密码、不改通道顺序或开关。 后续调用按「本次明确模型 > 已保存默认」执行,不每次重问;没有默认或模型失效时安全停止,绝不使用站点默认/第一项或替你改模型。原始 Python 脚本必须传 --model;插件包装层会自动传入你选过的默认。

HTTP 409「请刷新页面以获取服务器分配」不等于账号未登录。插件先执行站点的服务器分配握手,再向分配节点提交一次请求,站点 Cookie/凭据不传给节点;分配失败不会提交生图。超时/结果未知、旧异步错误不自动重投;低余额提醒不会把未知结果误判为额度拒绝。实际费用与任务状态以站点为准。

找素材先查六个优先来源,但优先来源不是免费/版权白名单:GameUI、Interface In Game、enotsixlm UI Kits、LemoUI、Pixlab24、Kenney。Kenney 的用户输入 /games 是游戏目录,免费资产应查 /assets;参考站截图不能直接切图,MIT 代码与字体另查许可。只用逐项已核实零成本、原作者授权、商用/修改/游戏分发和通知/依赖条件的素材;不明、付费、NC/ND、盗取或有已知争议的素材停用。

详细规则与证据见免费素材技能,只读目录见 GET /api/taptap-maker-dev/asset-sources。不会自动爬站、登录、下载、生成或改用户配置。如果运行实例仍是旧版,请重载插件或重启 DSH 后使用新界面;已保存的章鱼凭据独立保留,无需重填。

你会得到什么

| 能力 | 说明 |
| 额度红线 | 注入系统守则:非你在对话中明确要求,禁止调用 12 个消耗 Maker 额度的生成工具。设置页有开关,关闭需二次确认,即时生效无需重启 |
| ChatGPT 网页生图(首选) | 走你自己的 ChatGPT 账号在网页里出图(免费账号即可)。登录一次,之后全自动;支持多账号轮询,一个触配额自动换下一个 |
| 中转站生图(回退) | OpenAI 兼容 /images/generations。填 Base URL / Key / Model,支持「获取模型」自动列出可用模型。尺寸按需传,支持高质量缩小做图标 |
| 章鱼生图(可选第三通道) | 整合第三方技能:pai.zaiduyu.top 多模型积分站(gpt-image-2 / Z-image / Banana 等,价格实时读取)。花的是你自己买的积分,所以默认排在最后、需要你自己在设置页排序或显式调用;凭据由你在设置页输入并验证后存于本机;环境变量仅作兼容兜底,插件不在对话中代填或回显密码 |
| CC0 音效库 | Kenney 九个包共 706 个音频(CC0,可商用免署名),首次使用自动下载;本地没有时回落到 Mixkit / 小森平 / 効果音ラボ |
| 本地音效生成(兜底) | Stable Audio Open 1.0 在你自己显卡上跑,零额度、不联网付费。库里没有合适素材时才用;模型约 5.3GB 需你手动下载(先体检硬件,插件绝不自动拉大文件) |
| 完整 BGM | 自动生成提示词 + 打开 MiniMax Audio 网页;下载后自动导入(转格式 + 装进 assets/audio/bgm/ + 生成 .meta) |
| BGM 工作台挂件 | 主界面输入框旁的 🎵 挂件:试听刚生成的 BGM、拖波形裁剪选区间(可加淡入淡出防爆音)、一键导入项目;生成完自动亮红点提醒 |
| 音频转换 | ffmpeg 批量转格式 / 压缩 / 响度归一 / 去静音 / 淡入淡出 / 短音拼循环 |
| 视频动作帧 | 视频模型按首尾帧出一段动作 → 精确时间点抽帧 → 本地抠像(绿/蓝/品红幕,带逐帧自检)→ 对齐合成透明序列帧 → 一键导入 Maker(.meta + seq.json + Lua 切图)。只有出视频那一步花钱,抽帧/抠像/合成可无限重调 |
| 视频三后端 | MiniMax 官方(订阅 Key / 按量 Key 自动识别)/ 视频中转站(OpenAI 兼容 / MiniMax 协议 / 自定义路径映射)/ 自选本地视频(零额度)。auto 按可用性挑,也可按作业指定 |
| 分组式设置页 | 十几张卡按「生成通道 / 音频素材 / 治理与工具 / 怎么用」四组收拢,顶部一条通道状态总览(绿点=现在能用),不用再在长页面里翻找 |
| 可更新技能 | 内置游戏开发技能 + 周期更新检测;设置页可勾选禁用不需要的 |
| 初始化引导 | 直接用中文说「帮我初始化 taptap maker」即可触发,不必记斜杠命令 |

视频动作帧(视频 → 序列帧素材)

手里只有一张静帧、想让角色动起来,这条链路就是干这个的:

/taptap-video doctor # 自检 ffmpeg / Key / 站点 / 有没有视频额度 /taptap-video new 剑士行走 /taptap-video first ./refs/swordsman.png # 首帧(绿幕全身图最理想) /taptap-video last ./refs/swordsman_end.png # 尾帧可选(H3 / Hailuo-02 才支持) /taptap-video prompt 角色原地走三步,全身入镜,相机固定,绿幕背景 /taptap-video run # 唯一花钱的一步:提交视频 /taptap-video poll # 1~6 分钟,可反复调;重启后也能接着查 /taptap-video frames --count 12 --arrange loop # 抽帧(本地) /taptap-video key --chroma auto --tol 40 # 抠像(本地,带逐帧自检报告) /taptap-video sheet --cell 256 # 对齐合成整图(本地) /taptap-video import ../my-game --fps 12 # 导入 Maker

零额度路径(没有视频额度时):

/taptap-video use ./downloaded.mp4 # 挂本地视频(MiniMax Code 签到积分出的片也行)
/taptap-video frames && /taptap-video key && /taptap-video sheet

设计上的几个取舍:

- 抽帧排法可选:uniform(等分取中点,首尾都不碰 —— 第 0 帧往往是还没动的静帧)、 first-last(首尾帧模式想让两张图都算数)、loop(行走/跑步/待机要无缝循环)。
- 抠像主判据是四边洪水填充,不是绿色优势值 —— 视频模型常把纯色背景重新打光成渐变,只认绿色在那类帧上会整片失效。调色板只取背景主色簇,角色贴边时不会被顺着身体吃进去。
- 逐帧自检:每帧给背景占比与「可信」标记。主体只占画面一小块时占比 > 95%、标记不可信是正确结论,不是 bug;真素材主体一般占 15%~50%。
- 对齐用同一包围盒:所有帧共用一个 alpha 包围盒、贴底放在同一基线,上下起伏不会飘。
包围盒必须在抠完的帧上算 —— 在原帧上算等于没裁,主体会被缩成一点。
- 只把成品写进 assets/:中间的视频与原始帧留在作业目录(<项目>/sucai/video/<作业名>-<id>/),因为 Maker 运行时会给 assets/ 下任何新文件补 .meta 并打进构建 —— sucai/ 整棵是自忽略的,放中间产物正合适。

三个后端(与生图中转站同一套思路)

| 后端 | 怎么配 | 计费 | 适合 |
| MiniMax 官方 | 设置页填 Key(订阅 sk-cp-… 或按量 sk-api-…),或直接复用本机 mmx 登录态 | 套餐额度 / 账户余额 | 有 Explore+ 档或愿意按量付费 |
| 视频中转站 | 设置页填 Base URL / Key / 模型;三种协议(OpenAI 兼容 / MiniMax 协议 / 自定义路径映射) | 你的中转站 | 官方额度用完、或中转站更便宜 |
| 自选本地视频 | /taptap-video use <mp4> | 零额度 | MiniMax Code 签到积分生成的、录屏、别人的素材 |

auto 按设置页里排的顺序选第一条「开着 + 配好了 + 不是本地文件」的通道(默认顺序即上表顺序)。
你可以在设置页「生成通道优先级」里拖拽调序、逐条开关,并决定额度不足时要不要自动换下一条 (默认关;打开后可能在你不知情的情况下动用付费通道)。也可以按作业显式指定: /taptap-video backend relay|minimax|local(显式指定时不回退)。命令行改顺序: /taptap-video lanes --order minimax,relay --off local --fallback on。

🚫 模型不会被自动替换(视频按秒计费)

你在设置页「MiniMax」里选了哪个模型,/taptap-video 就用哪个,一个字都不会改。 这条是硬约束,不是建议:

- 新建作业继承你设置的模型(以前会悄悄退回内置的 MiniMax-H3);
- 模型与首尾帧不兼容、或模型为空时,直接报错并停下,绝不「顺手挑一个能用的」;
- 报错会给出你自己换的命令(/taptap-video set --model <模型名>)和替代方案(如 /taptap-video last --clear 清掉尾帧),但换不换由你决定。

给 AI 助手的同一条规定:即使它认为「换个模型更合适」,也只能停下来把情况讲清楚并询问你,不能替你改 —— 视频按秒计费,替你选模型就是替你决定花多少钱。

🛡️ 防呆护栏(不只靠守则,代码层硬拦)

注入给 AI 的守则只是建议,弱模型不一定照做。所以下面这些不可逆动作在 命令层也做了硬拦截:不带 --yes(或你没明说)就会停下来,把「会发生什么」和「怎么撤销」讲清楚,然后等你决定 —— 既不擅自执行,也不默默跳过。

| 动作 | 以前 | 现在 |
| /taptap-skills reset | 一句清空全部禁用表,无确认无备份 | 先备份 → 停下询问;新增 /taptap-skills restore 一行恢复 |
| /taptap-skills disable | AI 觉得没用就禁用 | 属于你的清单,要你点头 |
| /taptap-video use <mp4> | 静默覆盖已生成的视频 | 已有付费视频时停下询问,并告诉你原文件在哪 |
| /taptap-video set --model | 换模型 = 换价 | 停下询问,讲清「现在 → 想改成」 |
| /taptap-video lanes --order/--on/--off/--fallback | AI 可能拨乱你排好的顺序 | 停下询问(换通道可能走到另一条要花钱的通道) |

设计上刻意不把插件变成「什么都问」:抽帧张数、抠像阈值这类纯技术参数不受限制,随便调。护栏只拦「不可逆」和「属于你的决定」两类。

⚠️ 已有的生成结果不会被自动改动 —— 护栏只拦住新的破坏性动作,不追溯清理。

💸 不白烧额度:提交「结果未知」时不许重跑

视频按秒计费,而最贵的坑是这个:提交请求其实成功了,只是本地网络抖了一下 / 进程被打断,没拿到 task_id。此时服务端已经在跑、额度可能已经扣了,但用户(尤其 AI)看到的是「提交失败」—— 于是很自然地再跑一次,两次都扣钱。

现在的处理:

| 环节 | 做法 |
| 发请求之前 | 先把提交台账写进 video-submit-ledger.json(状态 inflight)。断网、进程被杀都留痕 |
| 拿到 task_id | 台账转 confirmed,作业转 running |
| 服务端明确拒收 | 4xx + 业务错误码 → 台账 failed,此时换通道重试是安全的 |
| 传输层故障 | fetch failed / 超时 / ECONNRESET 等 → 作业状态记为 uncertain(结果未知),不是 error |
| uncertain 时再提交 | 被拦下,必须你显式 --yes;拦住时会把「为什么可能已扣费」讲清楚 |
| 幂等键 | 同一次提交(含跨通道重试)复用同一个 Idempotency-Key,服务端可去重 |
| poll 限流 | 只提示「隔 30~60 秒再查」,不改任务状态(查询本身不花钱) |

关键设计:uncertain 用独立状态而不是 error。因为 error 会诱导「失败了就再来一次」,而 uncertain 的文案会直接劝阻重投,并指向 status / poll 去把片子找回来。

/taptap-video status 会显示台账(提交号、时间、task、是否可能已扣费),所以「上次到底提交了没有」永远有一处可查,而不是靠猜。

生图链路同样处理:网络异常不再自动重试(以前会重试 7 次,很可能重复扣费),如实报错并说明风险。但服务端明确答复的情况仍会安全重试 —— content_policy 误判、尺寸不支持、透明底参数不认,这些换请求就能过。

💾 配置不会莫名其妙丢

三个独立原因,都会造成「配置/Key 凭空消失」,已一并修掉:

| 问题 | 原因 | 现在 |
| 写配置写到一半被中断 / 并发读 | writeJson 原来直接 writeFileSync | 原子写(先写 .tmp 再 rename),崩溃或并发都不会留半截 JSON |
| 配置文件损坏后静默当作「没配置」 | readJson 吞掉异常 | 另存一份 .corrupt-<时间戳> 留现场,事后可找回 |
| 改一个字段抹掉另一个 | 设置页不回显明文 Key,表单里 apiKey 恒为空;保存时把空串写回去 | 空串 = 不修改;真要清空用 clear: true |

第三条是最隐蔽也最要命的:以前你在设置页只改个模型点保存,API Key 就被静默清空了,生图通道当场失效,且界面上没有任何提示。

🎬 抽帧 / 抠像:先备后换,不做「先删后写」

抽帧和抠像都是覆盖式产物。以前抽帧是「先 rmSync 整个 frames/,再逐张写」——写到一半失败(磁盘满、权限、Ctrl-C)时,上一轮的帧就被删光了,只剩半截新帧,而作业状态还没更新。用户既没新结果,也丢了旧结果。

现在统一「先写临时目录 → 全部成功才落位 → 失败自动回滚」:

- 抽帧写 .frames-staging/,抠像写 .keyed-staging/;
- 落位时先备份成 .frames-prev/ / .keyed-prev/,逐个文件替换;
- 中途失败回滚,恢复到本轮开始前的样子(注意:回滚必须覆盖已换上去的新文件,只补「缺失的」会得到新旧混杂的结果,比全丢更难判断);
- 逐文件 rename 而非重命名整个目录 —— Windows 上重命名仍被占用的目录会 EPERM (实测踩过)。

另外顺手堵了一个内存坑:chooseLayout 以前只卡宽度不卡高度,于是「64 帧 × 2048 格子」会算出 8192×32768 的成品图 —— 既超纹理上限,单张 RGBA 还要 1 GB;格子再大就直接 OOM。现在宽高一起卡,超限明确报错并告诉用户 --cell 该调到多少,auto 和手动指定 columns 两条路都拦。

🔊 音效 / 素材落盘

- ffmpeg 用 ffmpegPath() 解析,不是裸名字。ffmpeg 可能装在 FFMPEG_PATH、注册表或 winget 目录里而不在 PATH 上 —— 裸 spawnSync('ffmpeg') 会 ENOENT,用户只看到一句毫无线索的「转换失败」。音频转换另有 5 分钟超时,不会无限挂起。
- 写进工程的 .meta / .seq.json 一律原子写(.partial + rename)。
Maker 会监听 assets/ 并在构建时解析这些文件,非原子写留下的半截 JSON 会让构建报「meta 损坏」——而且 PNG 已经就位,那个窗口正好最容易被监听到。

🔐 登录时浏览器窗口会自动弹到前台

点「登录」或「添加并登录」后,Chromium 窗口会主动拉到前台。

以前窗口会开在 DSH 窗口后面,从来没被置前过 —— 用户点完按钮什么都没发生,以为按钮坏了(进程其实在跑、profile 也建好了)。Windows 不允许后台进程直接抢焦点,所以这里用「AttachThreadInput + ShowWindow(SW_RESTORE) + SetForegroundWindow」这套经典做法,并且按 profile 路径匹配窗口而不是抓「最新的 chrome」—— 否则同机开着别的浏览器时,会把用户自己的窗口抢到前台。

实测:修复后约 3.8 秒窗口自动置前。

另外「添加并登录」改成服务端一步到位(/gpt-pool add 直接启动登录,带上该账号的 --account 用独立 profile);前端不再补发第二次 /gpt-login,避免同时开两个窗口、第二个把第一个的 profile 锁清掉。

网页生图与 BGM 要在超时后按 profile 路径清理残留的 Chromium,音效库要解压 zip、读 cookie。原先这些都是把路径直接拼进 PowerShell 的单引号字符串:

Where-Object { $_.CommandLine -like 'C:\Users\…\browser-profile' }
Copy-Item -LiteralPath 'C:\…\Cookies' -Destination '…' -Force PowerShell 里单引号必须写成两个才表示一个。所以路径里只要出现一个 ' (用户名 O'Brien、把 DSH_HOME 指到带引号的目录等),字符串就提前闭合,后面的内容被当成命令执行。已实测可注入:

Write-Output 'C:\x' ; Set-Content -Path '<marker>' -Value 'INJECTED' ; #'
标记文件被创建了吗: True 内容: INJECTED

现在统一走 src/win-proc.mjs:路径先转义(' → ''),-like 模式里的 ? 转成 [] [?],并且六处调用不再各自拼字符串。测试里有真实 PowerShell 的往返一致性断言(含 O'Brien、x'; Write-Output 'INJECTED' ; ')。

中转站的「OpenAI 兼容」协议只实现公共约定,不绑定任何一家:

| 项 | 实现 |
| Base URL | 保留 /v1(只剥掉用户多粘的 /videos、/videos/{id}) |
| 素材 | 本机图片先上传换公网 url;上传路径由你自己填(留空则要求直接传公网 URL) |
| 参考素材字段 | 可选两种形态:metadata.mode + first_frame_url / last_frame_url,或 input_reference 数组 |
| 画幅 | metadata.ratio;全角 16:9、1920x1080、9/16 会自动纠正成 16:9 |
| 清晰度 | 默认不下发 size(很多型号自带清晰度档位) |
| 幂等 | 每个任务带 Idempotency-Key(UUID) |
| 状态 | completed + delivery_status=ready 才算完成;delivering 继续等 |
| 下载 | 带 Bearer 下 /content,按文件头校验容器;JSON/HTML 不会被当成片 |
| 过期 | download_expired 直接报「需要重新生成」,不空转轮询 |

不内置任何型号名、价格、能力表(时长范围 / 画幅支持 / 是否支持首尾帧)——各家中转站不一样,写死一家会误导其他家。型号列表用设置页「获取模型」从你自己的 /models 拉,或者手填;超范围时平台返回的 400 原文会直接回显。

各家协议不一样时切到「自定义」,填提交/查询路径与响应字段路径即可 ——报错会明确说「哪个字段没取到」,不会只给一句「失败」。

额度与计费(实情)

| Key / 套餐 | 能否出视频 |
| M Plan Go(最低档) | ❌ 官方明确不含视频模型,调用返回 1008 insufficient balance / HTTP 402 |
| M Plan Explore / Build | ✅ 含 H3,视频只受周窗口限制 |
| 积分包(¥7 / 1000 积分) | ✅ 支持 H3,套餐额度先用、超出扣积分 |
| 按量计费 Key(sk-api-…) | ✅ H3 768P ≈ ¥0.5/秒、2K ≈ ¥0.8/秒,4 秒 ≈ ¥2 |

设置页会自动识别 Key 类型并说清额度从哪扣,不用你自己判断该填哪一种 ——两种 Key 打的是同一批接口,区别只在计费来源。

⚠️ 别只看前缀判断订阅(2026-10-21 修)。MiniMax 的 Key 至少有三种形态: sk-cp-…(订阅)、sk-api-…(按量)、以及控制台签发的 JWT(eyJ…,payload 里带 TokenType,4 = 订阅)。本机用户的 M Plan 订阅 Key 就是最后这种,之前被插件无条件判成「按量 Key,不走 M Plan 套餐额度」—— 明明有订阅额度却提示得像是没有。

现在 JWT 会解出 payload 看 TokenType 判定;解不出来就说「不确定」并引导跑自检,不会再断言「你不是订阅」(猜错的代价是让用户白充值一次)。
最终以 /taptap-video doctor 的实测为准 —— 它打的是 token_plan/remains,返回 status_code: 0 就是有套餐额度,并会报出「本周剩 85% · 本周期剩 94%」这类数字。

⚠️ MiniMax Code 每日签到积分 ≠ 开放平台积分包:签到积分只用于 MiniMax Code 应用内的多模态创作(30 天有效),不能拿来让本插件通过 API 出片。想白嫖就在 MiniMax Code 里用签到积分生成视频、下载 mp4,再 /taptap-video use 挂进来 —— 抽帧/抠像/合成照样全本地。

BGM 试听 / 裁剪挂件(主界面)

BGM 生成是「用法」不是「配置」,所以它不在设置页,而是主界面输入框旁的 🎵 BGM 挂件:

- /taptap-bgm 生成完成后,挂件亮红点并弹出提示条,一键打开试听
- 每条 BGM 可播放(流式加载,可拖进度),选中后看波形、拖两个手柄选区间、「只听选中段」循环试听、可选淡入淡出(0.3s/0.5s,防裁剪点爆音)
- 「✂ 裁剪并导入项目」:ffmpeg 按 -ss/-t 精确裁剪 → 转 wav → 写 .meta → 落进当前项目 assets/audio/bgm/(不覆盖同名,自动加序号)
- 「原样导入」不裁直接用;全程本地 + 零额度(不碰 Maker/MiniMax 配额)
- 挂件每 10 秒轮询下载目录(窗口聚焦时立即刷新),挂载在主界面 conversation.composer.dock,出错只隐藏自己,绝不影响聊天界面

安装

dsh plugin --profile <profile> add dsh-taptap-maker-dev

或手动:把仓库克隆到插件目录,在 profile 的 package.json 加上依赖,重启 DSH。

⚠️ 本插件必须装在 Maker 工作区之外。所有持久化(含 API Key)写在 $DSH_HOME/taptap-maker-dev/ 下。
原因:TapTap Maker 运行时会自动把整个工作区提交并推送,明文 Key 一旦落进工作区就会泄露。

素材存到哪里(sucai/)

在 Maker 项目目录里执行生图 / 视频 / BGM 命令时,三类素材统一收在项目下:

<项目>/sucai/images/ 生图(网页生图与中转站生图都落这里) <项目>/sucai/video/<作业名>-<id>/ 一个视频作业一整个目录 refs/ 参考图 · videos/ 成片 · frames/ 抽帧 keyed/ 抠像结果 · out/ 拼好的序列帧 <项目>/sucai/bgm/ 背景音乐

- 自动忽略提交:每个目录自带 .gitignore(* + !.gitignore),Maker 自动 commit 整个工程时不会把它们推上去。只写自己的目录,不碰你的根 .gitignore。
- 不在项目里就退回 $DSH_HOME:命令可能在任意目录执行;不做这个判断就会在盘符根目录凭空造一个 sucai/。
- 目录实时可见:设置页「生成通道优先级」卡顶部会如实显示三类素材此刻的真实路径。
- 视频作业目录带作业名(如 奔跑-v7k2p),资源管理器里一眼认得出。改名不会 搬目录 —— 已生成的帧和视频都靠相对路径关联,搬了会全部失联。
- 换项目 / 换目录也找得到:作业位置记在 $DSH_HOME/taptap-maker-dev/video-index.json,不依赖当前工作目录。
- 老作业自动搬迁:改造前建在 $DSH_HOME/…/video-jobs/<id>/ 的作业,在首次访问时自动搬到项目下的 sucai/video/,已生成的视频和帧不会失联。

参考图上传前处理(本地、零生成额度)

通过插件的网页、中转站或章鱼图片入口传参考图时,先完整解码校验,再按需要缩放/转码;处理完成才进入浏览器/API 提交。不是再次生图,不调用 Maker 内置生成工具。

| 通道 | 默认最长边 | 单张 / 整组上传字节目标 | 需要转码时 |
| ChatGPT 网页 | 2048 px | 1 / 8 MiB | WebP |
| 中转站图片编辑 | 2048 px | 4 / 16 MiB | PNG,兼容只接受 PNG 的编辑端点 |
| 章鱼插件入口 | 3072 px | 2 / 16 MiB | WebP |

- 这些是本地优化目标,不是服务商承诺的 HTTP 限额。多图会共同分配总量预算;默认最多 16 张。不符合预算则停止,不偷偷少传参考图。
- 保留比例、不放大,处理 EXIF 朝向并验证实际透明度。默认单张最多 3200 万像素,防止小体积压缩图在解码/旋转时占用过多内存;这不是操作系统级内存上限。损坏文件、动画参考图及超出安全像素限制的图片会在提交前拒绝;动画请自行导出所需静态帧。
- 已满足要求的静态图不重新编码;文件扩展名按真实格式规范化。上传使用已校验字节的独立快照,不再重新读取可能已改变的原图。
- 缓存在 $DSH_HOME/taptap-maker-dev/reference-images/ref-upload-v2/,不进入游戏 assets/。按内容与处理策略寻址,完整写入后才发布;不覆盖/删除原图或旧缓存。损坏缓存会报错并保留现场。完成标记与临时文件保留,不自动清理;跨进程竞争失败的临时文件可能是独立副本,因此缓存会占用额外磁盘空间,清理需用户另行同意。
- 本地需要 Python 3 + Pillow(支持 WebP)或 ImageMagick 来完整解码校验;不会自动安装。已有 TAPTAP_PY / PYTHON 可指定解释器,TAPTAP_IMAGE_MAGICK 可指定 ImageMagick。找不到可用处理器、处理超时或体积无法达标时,返回 phase: preflight, submitted: false,不会拿未处理原图继续上传、重登或换付费通道。
- 可用 TAPTAP_IMAGE_REF_MAX_EDGE、TAPTAP_IMAGE_REF_MAX_BYTES、TAPTAP_IMAGE_REF_MAX_TOTAL_BYTES 调整本地目标(字节单位),TAPTAP_IMAGE_REFERENCE_CACHE 调整缓存目录。程序调用的显式参数优先于环境变量,环境变量优先于通道默认值;不会改动已选模型和通道顺序。
- 结果中的 referencePreparation / notes 给出处理前后大小、尺寸、MIME、SHA-256、透明度、处理器版本和缓存命中情况,不公开本地完整路径。--out 及派生输出若与任一原参考图同路径、符号链接或硬链接指向同一文件,会被拒绝。

范围:只处理插件图片入口的参考图,不压缩生成结果(输出缩小仍由 --downscale 负责),也不修改 DSH 主对话的完整 JSON 请求。不能据此保证消除所有 413,更不能修复上游 503 model_not_found。直接运行章鱼原始 Python 脚本仍只有其原有校验/体积上限,不经过这层预处理;其按内容去重参考图的既有规则不变。

实现:共享预处理 · Pillow 解码器。

离线验证(完整格式测试需本机已有 Node 与支持 WebP/AVIF 的 Pillow;可用当前终端的 TAPTAP_PY 指定 Python,不自动安装):

node --test scripts/verify-reference-image-preparation.mjs scripts/verify-reference-image-processors.mjs scripts/verify-reference-image-integration.mjs scripts/verify-reference-image-host.mjs
python -B scripts/verify-reference-image-codec.py
python -B scripts/verify-reference-image-diagnostics.py

这些测试真实解码/压缩本地构造的图片;浏览器、图片 API、站点账号与 ImageMagick 进程边界使用模拟,不发送付费请求。包含真实导入中转站函数后检查 multipart / JSON 上传字节的用例。测试临时目录也保留、不清理;不是对当前在线站点的实测。

配置

设置 → TapTap Maker 页,直接填并保存(存到 $DSH_HOME/taptap-maker-dev/,不进任何 Maker 工作区):
- 额度红线 — 开关,关之前会弹确认
- 生成通道优先级 — 三条链路(生图 / 视频 / 背景音乐)共用一张排序表:拖拽或用 ↑↓ 调顺序、每条通道一个启用开关、一个「额度不足时自动换下一条通道」总开关。
每行同时显示开关(要不要用它)、顺序(第几顺位)、就绪状态点(配好没有)——「关着」和「开着但没配」分开显示,因为这两件事的下一步完全不同。
存到 $DSH_HOME/taptap-maker-dev/lanes.json,即时生效。
- 默认顺序与改造前一致(视频:中转站 → MiniMax → 本地视频;生图:网页 → 中转站),升级后行为不突变。
- 自动切换默认关闭:打开后可能在你不知情的情况下动用付费通道。
- 只有额度 / 配额 / 限流类失败才换通道;参数写错这类问题换了也一样错,不会白跑一轮。
- 「自选本地视频」参与排序但不会被自动回退选中 —— 它需要你手动挑文件,不该被悄悄代入。
- 所有通道被全关时系统会自动保留一条,避免把自己锁死。
- ChatGPT 生图(首选) — 总开关(关掉后整条通道停用,模型改走中转站)+ 账号列表
+ 常驻的「添加并登录」输入框(唯一的新增入口,一步完成"建条目 + 打开登录")+ 多账号轮询开关
+ 图片下载目录(默认跟随项目 <项目>/sucai/images,可自定义,支持 {project} / {home})
- 顶部状态按 「N / M 个账号已登录」 显示,与下面每行状态一致 —— 以前只要池里有任一账号登录,顶部就笼统显示「已登录」,而某一行可能写着「未登录」,两处自相矛盾。
- 账号卡片不再有「主账号」那一行:它的「登录」按钮只是登默认 profile,不会新建账号,却和「添加并登录」并排摆着,最容易被误认成添加入口(2026-10-23 反馈)。
- 中转站(回退) — Base URL / Key / Model(「获取模型」按钮自动拉取)/ 缺省尺寸
- 完整 BGM — 填风格描述 → 生成提示词 → 一键打开网页 → 下载后自动导入
- BGM 账号 — 与生图卡同结构(同样去掉了「主账号」行、同样是常驻「添加并登录」)
+ 查额度 / 换号 + 额度用完自动轮换(每个账号独立浏览器 profile)
- CC0 音效库 — 状态、搜索、「更新库」
- 小资源图标 — 出图 + 缩小的最佳实践
- Skill 管理 — 勾选禁用不需要的 skill,即时生效
- 关于 — 当前版本 + 更新检查(设置页新增「关于」标签页)

🔄 检查更新

插件会自动检查新版本:后台每 6 小时对比一次本机版本与 GitHub 仓库 main 分支 package.json 里的版本,结果缓存到 version-check.json。

- 设置页新增 「ℹ️ 关于」标签页:显示当前版本、上次检查时间、是否有新版本;点「检查更新」可立即检查(绕过冷却)。
- 有新版本时显示醒目提示,并给出更新命令(git pull 后重启 DSH)。
- 网络失败也如实记录:显示「上次检查失败:原因」,不会显示一个过期的好消息。
- 检查失败 / 超时都不影响插件任何功能 —— 版本检查是纯增强,优先级最低。
- 版本比较按完整 semver 三段比:0.2.9 → 0.2.10 这种补丁位进位也能正确识别(字符串比较会把 10 判成小于 9,这里按数值比)。

命令行

视频通道:查看 / 调整顺序、开关、额度不足是否自动换 /taptap-video lanes /taptap-video lanes --order minimax,relay --off local --fallback on

生图首选:ChatGPT 网页(首次登录一次)
node <plugin-dir>/src/taptap-gpt.mjs login
node <plugin-dir>/src/taptap-gpt.mjs gen --prompt "蓝色盾牌图标,扁平,居中留白" --out icon.png --downscale 128x128

出图慢时:把「已经生成好但没下到」的图抓回来(不重新生成,省额度)
node <plugin-dir>/src/taptap-gpt.mjs pending # 有没有待抓取的对话
node <plugin-dir>/src/taptap-gpt.mjs grab # 抓 pending 那个对话
node <plugin-dir>/src/taptap-gpt.mjs grab --url https://chatgpt.com/c/xxxx

网页生图总开关(关掉后改走中转站)
node <plugin-dir>/src/taptap-gpt.mjs lane status
node <plugin-dir>/src/taptap-gpt.mjs lane off

图片存放位置:默认跟随当前项目(<项目>/sucai/images),也可自定义
node <plugin-dir>/src/taptap-gpt.mjs dir # 看当前解析结果
node <plugin-dir>/src/taptap-gpt.mjs dir --set "D:\my-images"
node <plugin-dir>/src/taptap-gpt.mjs dir --set "{project}/imgs"
node <plugin-dir>/src/taptap-gpt.mjs dir --reset # 恢复跟随项目

账号轮询:添加账号 → 各登录一次 → 之后自动轮换
node <plugin-dir>/src/taptap-gpt.mjs pool add --id a2 --label "小号"
node <plugin-dir>/src/taptap-gpt.mjs login --account a2
node <plugin-dir>/src/taptap-gpt.mjs pool list # 看状态
node <plugin-dir>/src/taptap-gpt.mjs pool unban --id a2 # 恢复冷却账号

生图回退:中转站(尺寸按需,支持透明底 + 缩小)
node <plugin-dir>/src/taptap-image.mjs --prompt "蓝色盾牌图标" --out icon.png --transparent --downscale 128x128

章鱼生图(积分站,可选通道;先看模型价与余额再决定用哪个模型)

node <plugin-dir>/src/taptap-zaiduyu.mjs status # 脚本/Python/账号 三态
node <plugin-dir>/src/taptap-zaiduyu.mjs models # 实时模型清单 + 单张积分 + 余额
node <plugin-dir>/src/taptap-zaiduyu.mjs gen --prompt "小猫赏月" --model gpt-image-2 --ratio 16:9

站点账号在【设置页】登录(无需命令行):

设置页 → 生成通道 → 「章鱼生图(积分站)」卡 → 填账号密码 → 点「登录并保存」

插件会先连站点做一次只读验证(不扣积分),通过才保存,即时生效、不用重开宿主。

凭据存本机 $DSH_HOME/taptap-maker-dev/zaiduyu.json,密码不回显、不进 Maker 工作区。

兼容:环境变量 ZAIDUYU_USER / ZAIDUYU_PASS 仍可用(文件值优先)。不建议把密码

写进终端命令 —— 那会落进对话记录与本机日志。

BGM 账号池:添加账号 → 各登录一次 → 额度用完自动轮换

node <plugin-dir>/src/taptap-bgm-web.mjs login # 主账号
node <plugin-dir>/src/taptap-bgm-web.mjs pool add --id b2 --label "小号"
node <plugin-dir>/src/taptap-bgm-web.mjs login --account b2
node <plugin-dir>/src/taptap-bgm-web.mjs pool list # 看状态
node <plugin-dir>/src/taptap-bgm-web.mjs gen --prompt "史诗管弦战斗音乐" # 自动选可用账号

音效:搜索 / 安装 / 查看来源

node <plugin-dir>/src/taptap-audio.mjs search "金币音效"
node <plugin-dir>/src/taptap-audio.mjs add "金币音效" --project <maker-project> --out coin.wav

本地音效生成(CC0 库没有合适素材时的兜底;零额度,需 NVIDIA 显卡)

node <plugin-dir>/src/taptap-sfx.mjs check # 硬件体检(不够就止步)
node <plugin-dir>/src/taptap-sfx.mjs guide # 打印 5.3GB 模型【手动】下载命令
node <plugin-dir>/src/taptap-sfx.mjs verify --fast # 下载后校验(--fast 只比大小)
node <plugin-dir>/src/taptap-sfx.mjs deps # 打印依赖命令;确认后才加 --yes
node <plugin-dir>/src/taptap-sfx.mjs doctor # 装好后体检
node <plugin-dir>/src/taptap-sfx.mjs gen "coin pickup, bright arcade blip" -s 3 --project <maker-project>

模型权重本插件【绝不自动下载】:先体检、用户同意、用户自己在终端逐条跑 curl。

node <plugin-dir>/src/taptap-audio.mjs sources

BGM:生成提示词 + 打开网页(对话里用 /taptap-bgm 即可)

/taptap-bgm 史诗管弦战斗音乐,紧张激烈

网页下载后,自动导入项目(转格式 + 装进 bgm + 生成 meta)

node <plugin-dir>/src/taptap-audio.mjs import --in "C:\Users\<你>\Downloads" \
--project <maker-project> --kind bgm --to wav --latest

音频转换(需要 ffmpeg)

node <plugin-dir>/src/taptap-audio-convert.mjs --in sfx --out out --to wav --mono --rate 44100 --normalize

skills 更新

node <plugin-dir>/src/taptap-skills-update.mjs

对话里也可直接用斜杠命令:/taptap-image、/taptap-audio、/taptap-bgm、 /taptap-audio-convert、/taptap-skills、/taptap-setup。

素材来源与授权(重要)

所有来源都经过逐个核实官方授权条款——「免费」不等于「可商用」:

| 来源 | 授权 | 自动获取 |
| Kenney | CC0 — 可商用、可修改、无需署名 | ✅ 整包下载 |
| Mixkit | Mixkit Free License — 可商用、无需署名 | ⚠️ 索引(安装时单文件下载) |
| 小森平 | 中文页原话:商业利用、加工、应用或工业产品的使用也可;禁把音效本身再贩卖 | ✅ 单文件按需 |
| 効果音ラボ | FAQ 原话:商用無料、料金発生なし、報告不要、クレジット表記不要,明写可嵌入游戏有偿销售;禁再配布 | ✅ 单文件按需 |

未接入(有原因):

- Freesound — 需要用户自己的 API Key(实测裸请求 401)
- OpenGameArt — 授权混杂,含 CC-BY-NC 等禁止商用 的协议

开源致谢

本插件整合了第三方开源项目的方法论与判据(引擎无关的那部分)。完整来源、许可与逐项对应见 THIRD-PARTY-NOTICES.md。

3AGameFactory(OpenDCAI)· Apache-2.0

感谢 OpenDCAI/GameFactory-3A 公开他们的 3A 游戏资产生成框架。我们从中学到并落地了两件事:

| 整合到 | 学到的核心洞见 |
| skills/asset-orientation-qa | 朝向无法由几何计算得出:朝 +Z 与朝 −Z 的模型导出后包围盒、节点树、动画完全一致,加载文件分不出来,只能「看」。以及「不要用 gameplay 代码补偿旋转」这条硬规则 |
| skills/asset-visual-qa | 结构检查 ≠ 视觉可用;编译通过 / 能启动 / 日志无错 ≠ 验证完成;以及游戏内复核的完整维度(朝向、附着、穿模、尺度、风格、光照、VFX、可玩性) |

我们只取其方法论,不搬运引擎专属代码 —— 它的参考实现面向 UE5 / Unity / Godot / Blender / three.js,与本插件的 TapTap Maker(UrhoX + Lua) API 完全不通用,硬搬会让智能体调用不存在的接口。

@misc{gamefactory3a,
title = {3AGameFactory: Open-Source 3A Game Generation Skills and Asset Framework},
author = {OpenDCAI},
year = {2026},
howpublished = },
}

诚实限制

使用前请读完这几条,我们不假装它们不存在:

1. 没有可无缝循环的完整 BGM。Kenney 音乐包只有 1~3 秒短 jingle。完整 BGM 要走网页版生成。
2. 完整 BGM 无法全自动。MiniMax 音乐 API 对新用户账号直接返回 HTTP 410(实测:真 key 调 music-3.0/music-2.6/music-cover 全 410,假 key 才 200/1004);其网页版是需登录的单页应用、没有公开 API(实测 /api/music 返回 HTML 页面),脚本无法代你生成/下载。
所以插件能自动的只有前后两段:生成提示词 + 打开网页,以及下载后自动导入项目。中间「点生成 + 下载」必须你亲手做。不要反复重试 API,也不要据此判断接口故障。
3. 効果音ラボ 的 robots.txt 禁止 AI 爬虫抓 mp3。它的授权允许你把音效嵌进有偿游戏,但本插件只在你要装某一个文件时才下载它,串行 + 限速 + 遇错退避,绝不整站抓取。
4. 设置页的保存依赖宿主 web 服务(webServer)。若你的 DSH 组合没启用,卡片会提示改用命令,不会白屏。
5. 生图 / 音乐用的是你自己的 Key,账单在你那边;本插件不代付、不代理、不上传你的 Key 到任何第三方。
6. ChatGPT 网页生图依赖界面选择器。OpenAI 改版频繁,脚本可能失效——失效时它会如实报告卡在第几步(no_composer / no_image / download_failed),不会假装成功;此时回退到中转站。
7. 网页出图要 1~3 分钟。脚本会等「生成中」结束、只认本次新出现的图再下载(不会把上一轮对话里的旧图当结果)。真等超时会记住那个对话的链接:用 grab 抓回来即可,不要重新生成(会白烧一次额度)。
7. 多账号轮询违反 OpenAI 服务条款。轮换账号会绕过单账号配额,可能导致账号被封。这是应要求实现的功能,风险由你承担;每个账号用独立浏览器 profile 隔离,且不会自动重试被标记封禁的账号。
8. 视频动作帧有三个诚实限制:
- M Plan Go 档没有视频模型,订阅 Key 打视频接口会收到 1008 insufficient balance。这不是插件 bug,也不是 Key 不对(鉴权是通的)。Explore/Build 档、积分包、按量 Key 才能出片。
- M Plan 每日签到积分不能用于 API:它只在 MiniMax Code 应用内有效。想在插件里出片,只能在 MiniMax Code 里生成后下载视频再导入。
- 抽帧率的上限由视频本身决定:模型只生成了 4 秒 24fps,就抽不出 60 帧真正不同的画面,帧数要按动作时长配,别指望插值。

关于「额度红线」

它守的是这 12 个消耗 Maker MCP 内置额度的工具: generate_image、batch_generate_images、edit_image、create_video_task、query_video_task、 text_to_music、text_to_sound_effect、batch_sound_effects、audition_voices_for_character、 confirm_character_voice、text_to_dialogue、create_3d_asset。

只读 / 状态 / 构建 / 反馈 / LSP 类工具不受限。

隐私

- API Key 只写进 $DSH_HOME/taptap-maker-dev/{image,music,minimax}.json,绝不进入会自动提交的 Maker 工作区。
- 素材落在 <项目>/sucai/(图片 / 视频 / BGM 三类分开),每个目录自带 .gitignore 自我忽略,所以即使 Maker 自动提交整个工程也不会把它们推上去。只有最后合成的那一张整图会被复制进项目 assets/image/。
- 本插件不联网上报任何遥测;联网只发生在你主动下载素材或调用你自己的生图 / 音乐 / 视频端点时。
- 发布前可运行 node scripts/sanitize-for-release.mjs 清掉本机路径与密钥残留。

DeepSeek Harness 插件,用于本地 TapTap Maker 游戏开发:守住「不花用户额度」这条红线,提供可更新的游戏开发技能,并自带自托管的图片 / 音效 / BGM 通道——全部走你自己的 API Key 或 CC0 素材库,绝不消耗 Maker MCP 内置额度。
亮点:可实时开关的额度红线;ChatGPT 网页生图作为主出图通道(登录一次,可选多账号轮换);OpenAI 兼容中转通道作为兜底;706 个文件的 CC0 Kenney 音频库,并回退到 Mixkit / Taira Komori / 効果音ラボ;BGM 助手会写好提示词、打开 MiniMax Audio 页面,再自动导入下载结果;基于 ffmpeg 的音频转换;复选框式技能管理——全部都能在设置页配置,无需手动编辑 JSON。

各资源的许可证核实结果见上方表格,也请读一读如实说明的限制:CC0 库里没有可无缝循环的 BGM,而且完整 BGM 无法全自动完成——MiniMax API 对新用户账号返回 HTTP 410,其网页是仅限登录的 SPA,没有公开 API,所以「点生成再下载」只能手动做。插件自动化了两端:写提示词、打开页面,然后导入成品文件。効果音ラボ的 robots.txt 限制 AI 批量抓取(我们每次安装只顺序取一个文件,绝不爬站)。

License

MIT。仅覆盖插件代码——每个下载的资源各自带许可证(上文已注明),你需要自行遵守这些许可证。
预览分享卡片长什么样 ↓swyaoguai/dsh-taptap-maker-dev
分享 · DeepSeek Harness Hub
swyaoguai/dsh-taptap-maker-dev

TapTap Maker 本地开发的 DSH 插件:额度红线、可更新游戏 skills、自建生图/CC0…

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部