Repository navigation
TTS MultiModel v2.2.2
v2.2.2
三引擎本地 TTS(VoxCPM2 / IndexTTS 2.5 / IndexTTS 2.0)+ FastAPI/htmx 界面 + OpenAI 兼容口。
本版主要是 v2.2.1 之后累积的桌面/便携分发链路 + 一轮发布前置回归的修复。
一定要知道的四条
- 干净环境装出来的镜像/便携包此前起不来默认引擎。 vendored VoxCPM 在模块顶层
from einops import rearrange,而einops只在trainingextra 里声明过,funasr/modelscope
又只在 extras 里要它 —— 于是任何按requirements.txt/[project].dependencies
装出来的环境(Docker 镜像、便携包)导入tts-1引擎就ModuleNotFoundError。
开发机永远看不见这件事(einops从训练链路传递进来了)。现已提为核心依赖,并补上同样缺席的
addict,另加守卫:核心声明的每个包必须在两份钉版集里都有钉版。 - 镜像构建的间歇性失败已根治。 真因不是日志里那条
update-alternatives ... bash-builtins.7.gz
(它是良性噪声),而是apt-get update对「某个索引没抓下来」只报W:并返回 0,
两行之后才炸成E: Unable to locate package python3.12。现在两段 RUN 都以
「PPA 索引里真查得到 python3.12」为前置条件,重试 5 轮仍取不到就硬停并给出可操作原因。 - IndexTTS 的 device-side assert 已修,且真因不是"第二次引擎切换"。 是预热绕过了串行队列、
与用户请求并发(预热从后台加载线程直接调engine.infer,用户侧那把 per-engine 信号量管不到它),
而 IndexTTS 推理不可重入 → 整个 CUDA context 被毒化,同进程后续合成全废。
修法在引擎层按注册名加锁;真机并发下字节数与串行完全一致(2.5 = 336,642 B / 2.0 = 239,674 B)。 - CSRF 防护不再会静默关闭。 以前
data/.csrf_secret写不出来时只 warning,然后以空密钥
继续挂中间件(等于把 HMAC 绑定摘掉照常接请求);现在直接拒绝启动并说明怎么修
(容器/桌面部署要给data/可写卷)。密钥改0o600落盘,老文件自动收紧。
安全与依赖台账
- Dependabot:20 条告警已逐条 triage + 绑定理由 dismiss(open 归零),台账在
docs/SECURITY_DEPENDABOT_TRIAGE.md。注意:其中 8 条只有 PYSEC 号、没有 GHSA 记录,
Dependabot 从没为它们开过单 —— 别把"告警清零"当"风险登记完成"。 - transformers 停在 4.52.1 是实测决定的:
indextts 2.0.0钉transformers==4.52.1+
tokenizers==0.21.0;抬到 4.57.6 时 IndexTTS 2.0/2.5 直接 ImportError(三引擎只剩一个能用)。
代价按 OSV 实测是 16 个公告,其中 8 条上游根本没有修复版本;已逐条写可达性判据与理由后
在 pip-audit / Trivy 里绑由头豁免(Trivy 侧带 2026-12-31 到期,pip-audit 没有到期机制,靠文档复审约定)。 - CodeQL 存量:open 110 → 76,critical 1 → 0,差额逐条对上账;
分诊表见docs/SECURITY_CODEQL_TRIAGE.md。 - 发布物已剔除曾随包分发的本机 HTTPS 私钥(
app/cert.pem/key.pem),并加进门禁负向断言。
其它
- OpenAI 口
tts-1-hd(IndexTTS 2.5)此前必然 500(该口没有参考音频通道),现返回 400 并指明应走哪个端点。 - 桌面/便携链路:Tauri 壳自绘标题栏与窗口控制、NSIS 安装器(中文安装须知 + 许可页)、
便携三组件分卷(core/torch/model)+ SHA256SUMS 全覆盖 + 回读校验、增量更新契约、
完整性自检 Ed25519 签名 +enforce阻断、篡改模拟门禁。 - CI 两处"永远绿的假信号"已修:
gpu-smoke的 job 因缺 secret + 零注册 runner 一直skipped
而 run 顶层 success(现会 warning + 写进 step summary);镜像内的引擎模块此前从没被导入过(新增探针)。
本次 Release 附带的资产
tts_multimodel-2.2.2-py3-none-any.whl(28,375,881 B)tts_multimodel-2.2.2.tar.gz(28,318,388 B)SHA256SUMS.txt(对上述两件;已做回读校验)
两件产物由 python -m build 产出并通过 twine check。
wheel 的 METADATA 现在带 Requires-Dist: einops>=0.7.0 与 Requires-Dist: addict>=2.4.0
(已安装包内核对),所以这条修复对 pip 安装方同样生效,不只是镜像与便携包。
不含 ~26 GB 的便携分卷(core/torch/model)与桌面增量包 —— 那需要
scripts/release_gate.ps1 -ModelDir ... -RuntimeDir ... -TorchWheelDir ... 真实构建并单独确认;
本批改动不含权重变化,重传 13 个 model 分卷是逐字节浪费。
也没有 GPG 分离签名:仓库只配了 1 个 Actions secret(MANIFEST_SIGNING_KEY_B64),
GPG_PRIVATE_KEY 不存在,所以 gpg-signed-release.yml 只会 notice 跳过。
tag 为注解读但不过 GPG 签名 —— 与本仓历史一致(v2.1.0/v2.2.0/v2.2.1 是轻量 tag,
v2.0.1 是无签名的注解 tag),不做无法验证的签名承诺。
版本口径(如实说明)
本批含 43 个 feat: 提交,按 SemVer 应为 2.3.0;仍标 2.2.2 是仓库所有者的显式决定 ——
内容与 2026-09-16 那次建了又撤销的 v2.2.2 tag 属同一批,CHANGELOG 沿用该号。
另:release-please.yml 此前是结构性空转(skip-github-pull-request: true 而仓库从无 release PR,
且 5 个入参被 action 静默忽略、配置文件根本不存在、job 没声明 outputs),
所以本次 Release 是手工打的 tag + 手工建的 Release,不是 CI 自动发的。
已知未覆盖(发版时点的事实,不粉饰)
- 桌面安装包链路(staging → 7z 分卷 → NSIS)没有任何 workflow 覆盖,本机也无从安装验证;
上面的"干净环境缺依赖"结论在镜像侧是实测(探针 run 35618578940),在便携侧只到
"清单缺项"的证据强度。 - GPU 冒烟(真加载 + 真合成)需要一台带
gpu标签的 self-hosted runner,本仓库没有注册 runner,
因此它在 CI 上永远 skipped。真机验收由维护者本人完成。 - 锁集的"全新 venv 真装"复验(GB 级下载)仍待执行。
- 新查出、本次未动的一处打包缺口:wheel 里
integrated_app/security/只有.py,
integrity_manifest.json与其.sig.ed25519、签名公钥都没被打进包(已按产物核对)。
而integrity_selfcheck.py:166在清单不存在时只logger.info("跳过自检")并返回
skipped=16 / manifest_signed=False,enforce=True也不会拦 —— 也就是说
纯pip install那条部署路径上,Ed25519 完整性保护实际从不运行。
桌面便携包与 Docker 镜像不受影响(两者都另外拷了源码树,所以容器启动探测是绿的)。
修法两步:补package-data;并把"enforce 模式下没有清单"从 info 跳过改成硬失败。
发版当天不改它 —— 它会改变随包内容,且 enforce 行为得在装出来的环境里实测,不是照读代码。