# 发布指南:dsh-gptsovits-tts > 目标:把插件发布到 DSH 插件市场(awesome-dsh-plugin.com),用户装完就能说话、能换音色、能训新音色。 > 插件本体很小(~200KB),真正的体积在「语音引擎」:11.45 GB,切 7 片放 GitHub Releases,首次使用时由插件下载。 --- ## 0. 发布物一览 | 产物 | 大小 | 放哪里 | 谁来做 | | --- | --- | --- | --- | | 插件包 `dsh-gptsovits-tts` | ~200 KB | npm 公开包(可选) | 我(打包)→ 你(`npm publish`) | | 源码仓库 | 4.6 MB | GitHub 公共仓库 | 你建仓库,我推代码 | | 市场条目 `data/plugins/<你>__dsh-gptsovits-tts.yml` | 1 KB | awesome-dsh-plugin 的 PR | 我生成 → 你提 PR | | 图标 `docs/assets/icon-180.png` + `screenshots.json` | 17 KB + 4 张图 | 你自己仓库 | 已完成 | | 引擎分片 `engine.part01..07.zip` | 11.45 GB | GitHub Releases(tag `engine-v1`) | 我生成 → 你上传 | | 引擎清单 `engine.manifest.json` | ~2 KB | 同上 | 我生成 → 你上传 | | 介绍短片 / 截图 | 3.4 MB | 仓库 `docs/` + README | 已完成 | --- --- ## 1. 建 GitHub 仓库(5 分钟) 1. 在 GitHub 新建公共仓库,例如 `dsh-gptsovits-tts`(空仓库,不要初始化 README)。 2. 把仓库地址告诉我,我会把 `plugin/`(包)与 `README`、`LICENSE`、`docs/` 整理成仓库结构并改掉 package.json 里的占位地址: ```jsonc "repository": { "url": "git+https://github.com/<你>/<仓库>.git" }, "homepage": "https://github.com/<你>/<仓库>#readme" ``` 3. 本地推送(或你把仓库给我配好 remote,我来推): ```powershell git init -b main git add . git commit -m "feat: dsh-gptsovits-tts 0.2.0" git remote add origin https://github.com/<你>/<仓库>.git git push -u origin main ``` --- ## 1.1 一条命令组装仓库 仓库内容不要手工复制,跑脚本: ```powershell # 换成你的 GitHub 用户名;--scope 是你的 npm 作用域 python tools/make_repo.py --owner --scope "@" --strict ``` 它会: | 动作 | 说明 | | --- | --- | | 复制 `plugin/lib`、`cordis.patch.yml`、`README.md`、`LICENSE`、`package.json` | 排除 `__pycache__`、`shadow`、`data`、`*.log` 等运行期垃圾 | | 复制 `docs/*.md` 与截图、短片到 `docs/assets/` | README 里已经引用 | | 替换 `` 占位符 | `package.json` 的 author/repository/homepage/bugs、`lib/index.js` 的默认下载源、`docs/market-entry.yml` | | 改包名 | 传了 `--scope` 就变成 `@/dsh-gptsovits-tts` | | 生成 `.gitignore`、`CHANGELOG.md`、`docs/market-entry.yml` | 市场提交用的条目模板 | | 自检 | 本机用户名、整合包目录名、本机盘符路径、`private:true`、缺字段、残留 `` | `--strict` 的意义:只要还有 `` 占位符就直接失败,避免把占位地址发上 npm。 不传 `--strict` 时只提示不失败,方便本地反复组装。 产物在 `release/repo/`,进去 `git init` 即可推送。 --- > 安装器的磁盘策略:**边下载边解压**(下完一片 → 校验 → 解压 → 删片), > 峰值占用约「最大分片 + 解压后总量」≈ 12 GB,而不是「全部分片 + 解压后」≈ 23 GB。 > 开始前会用 `statfs` 检查可用空间,不够就直接报中文错误(需要多少 / 可用多少)。 ## 1.2 引擎分片清单 ```powershell python tools/build_release.py --build # 11.45 GB,约 7 片,写到 release/parts/ ``` 生成 `release/parts/engine.manifest.json`(version / layout / parts[{name,bytes,sha256}] / total_bytes), 分片名固定为 `engine.partNN.zip`。上传到 Release 后,插件按 manifest 顺序下载并逐片校验 sha256。 ## 2. 发布 npm 包(10 分钟) > 建议用 scoped 名字,避免和别人撞:`@<你的npm用户名>/dsh-gptsovits-tts`。 ```powershell npm login # 浏览器里输账号 + 2FA cd <仓库>/plugin npm publish --access public # package.json 已带 publishConfig.access=public ``` 发布成功后验证: ```powershell npm view @<你>/dsh-gptsovits-tts version ``` > 插件市场里的安装命令是 `dsh plugin --profile web add `。 --- ## 3. 上传引擎分片(30 分钟,主要在上传) 1. 在本机生成分片(我在工作区执行): ```powershell python tools/build_release.py --build ``` 产物:`release/parts/engine.part01.zip … part07.zip` + `release/engine.manifest.json`(每片 ≤1.9 GB,ZIP 存储模式,从整合包硬链接出来,不额外占盘)。 2. GitHub Release:新建 tag `engine-v1`,把 7 个分片 + manifest 全部作为 release asset 上传。 > GitHub 单文件上限 2 GB,所以切成 7 片;总上传量 11.45 GB。 3. 如果我给的下载地址前缀和你实际的 release 地址不一致,改两处即可(不需要重打包): - `plugin/cordis.patch.yml` 的 `downloadBase:` - `plugin/lib/index.js` 里的 `DEFAULT_DOWNLOAD_BASES` 默认值是 `https://github.com/gptsovits-tts/engine/releases/download/engine-v1/`,把 `gptsovits-tts/engine` 换成你的仓库即可。 > 也可以放对象存储(OSS/S3/R2)——只要支持 Range 下载与直链,填进 `downloadBase` 就行。 --- ## 4. 提交到插件市场 市场是**索引 GitHub 仓库**的(awesome-dsh-plugin.com,6.6K+ 插件),规则写在 。 按官方要求,投稿 = **一个 PR 只加一个文件** `data/plugins/__.yml`: ```yaml # data/plugins/<你>__dsh-gptsovits-tts.yml url: https://github.com/<你>/dsh-gptsovits-tts # 必须与仓库完全一致 name: <你>/dsh-gptsovits-tts category: voice # 语音类的固定取值 description: en: "Local GPT-SoVITS text-to-speech for DSH: reads replies aloud, switches voices from the right sidebar, and trains a new voice from a dropped audio sample." zh: "基于 GPT-SoVITS 的本地语音合成:朗读 DSH 回复、在右侧边栏换音色,拖一段声音就能训练新音色。" icon: https://raw.githubusercontent.com/<你>/dsh-gptsovits-tts/main/docs/assets/icon-180.png ``` `tools/make_repo.py --owner <你>` 已经按这个形状生成好了(`release/repo/docs/market-entry.yml`), 直接复制改名提交即可。要点: 1. **不要写 `npm:` 字段**——会被校验直接拒;npm 关联靠 `package.json` 的 `repository` 自动匹配。 2. 描述里含 `": "` 必须加引号(上面已经加了),`description.en` 必填且以句号结尾。 3. 仓库硬性条件:`package.json` 里有 `dsh.bundle`(本仓库有)、仓库创建满 1 天、给仓库加 **`dsh-plugin`** topic、代码真实可用。 4. 截图声明在**你自己仓库根**的 `screenshots.json`(已生成,4 张,路径相对该文件、不要 `..` 开头)。 5. 图标必须是 GitHub 托管的位图(`docs/assets/icon-180.png` 已生成 180×180 PNG)。 6. peerDependencies 要用「带预发布分支」的写法,否则会静默排除 harness 预发布版本: `">=0.1.7-0 <0.2.0-0 || >=0.2.0-0 <0.3.0-0"`(本仓库已按此修正 `dsh-host-webserver`)。 7. CI 顺序:条目数 ≤3 → 读 `dsh.bundle` → 仓库年龄 → awesome-lint 与站点构建;首次提交建议**只提这一条**。 npm 发布是可选的:不发布也能被收录、能从 GitHub 安装;发布了才会在详情页显示下载量。 --- ## 5. 发布前门禁 ```powershell node test/run_all.mjs # 7 个套件,约 7 秒;全 PASS 才发 ``` 覆盖:Host 路由、Client 渲染(自写迷你 hooks)、拖入/训练面板、引擎安装器(断点续传 / sha256)、 首装向导(manifest → 分片 → 解压 → use-dir)、bundle patch。 ## 6. 发布前检查清单 - [ ] `npm pack --dry-run` 只包含 `lib/`、`cordis.patch.yml`、`README.md`、`LICENSE`、`screenshots.json` - [ ] 仓库里有 `screenshots.json`、`docs/assets/icon-180.png`、`docs/market-entry.yml` - [ ] GitHub 仓库加了 `dsh-plugin` topic - [ ] 干净机器(没装过 GPT-SoVITS)首装:面板出现「语音引擎 未就绪」→ 点下载 → 走完 7 片 → 自动解压 → 服务起来 → 能出声 - [ ] 「用已有目录」:指到一个已解压的引擎目录能直接用 - [ ] 训练一条全新音色(3 分钟素材)能从拖入跑到注册 - [ ] 卸载/重装后 `%LOCALAPPDATA%\dsh-gptsovits-tts\` 里的配置不会丢 - [ ] README 里有:安装命令、首次使用说明、常见问题(显存、防火墙、杀毒误报) - [ ] LICENSE 明确:代码 MIT,模型权重遵循 GPT-SoVITS 上游协议,内置音色仅供演示 --- ## 7. 已知风险 | 风险 | 说明 | 对策 | | --- | --- | --- | | 11.45 GB 首次下载 | 国内直连 GitHub 可能很慢 | 后续加国内镜像前缀(`downloadBase` 可多值,按顺序回退 + 断点续传) | | 杀毒误报 | 打包的 python + torch 体积大、行为像"下载执行" | 首次下载时明示来源与校验 sha256(manifest 里已有) | | CUDA 兼容 | 引擎带 cu118,需 NVIDIA 驱动 ≥ 522 | README 写明;无 CUDA 时回退 CPU(很慢,不推荐) | | 内置音色版权 | 诺艾尔/爱莉希雅来自游戏角色 | 演示用途,README 注明;正式分发建议换成自录或授权音色 | | npm 名字被占用 | 公共包名冲突 | 用 scoped `@<你>/...` |