阶段一
先定义问题,再决定技术。
明确最终业务结果
输入用户只有文案、目标音色、图片和发布需求。操作把目标拆为音色克隆、语音生成、视频合成、质量检查、成品导出五个可独立验证的环节。输出两套独立应用和一条可组合工作流,而不是一段只能演示的脚本。确定本地优先的约束
输入Apple Silicon 设备、敏感参考音频、希望避免持续 API 费用。操作主路径选择 MLX;需要原生兼容时使用隔离的 PyTorch/MPS 子进程;模型权重与 ASR 全部本地保存。输出无云端密钥、参考声音不离开本机、可离线执行的基础架构。建立统一输入输出合同
TTS 合同统一为:文本、参考音频或音色缓存、模型模式、采样参数、任务控制回调、输出路径。视频合同统一为:音频、至少一张图片、可选文案、可选首页标题和画布参数。统一合同让界面与底层模型解耦。
把非功能需求写进产品规则
规则包括:大模型按需加载;任务必须可观察、可取消;已有输出不得覆盖;无文案时字幕自动关闭;视频方向由首图决定;商业页面必须如实区分原生能力、近似能力与授权边界。
阶段二
开发 IndexTTS2 多模型语音工作台。
搭建 Gradio 工作台骨架
先完成模型选择、音色选择、文本输入、参数区、生成按钮、进度状态、试听与下载区域。界面只负责收集意图,生成逻辑全部进入后端适配器。
关键模块mlx_indextts/webui.py接入 IndexTTS 2.5 主引擎
使用 MLX 8-bit 模型,在适配器中实现 speaker context 构建、音色条件缓存、按自然停顿分段、逐段生成、片段拼接与部分文件写入。中文安全上限高于拉丁文本,降低长句对齐崩溃风险。
关键模块generate_v25.py增加异常时长保护
生成后根据文字单位估算合理时长上限。若短句被异常扩展成长音频,系统不直接接受,而是缩短文本片段后重试,防止长文中出现局部失真和时间轴漂移。
接入 IndexTTS 2.0 情绪路径
保留参考音色克隆,同时开放 happy、sad、angry、afraid、disgusted、melancholic、surprised、calm 八类原生情绪向量和
emo_alpha强度。2.0 与 2.5 音色缓存分开保存,避免格式误用。接入 OmniVoice MLX 三种模式
实现 clone、design、auto。克隆模式将参考音频编码为 token,并要求准确参考原文;设计模式接收声音描述;自动模式不需要参考音频。输出统一为 24 kHz PCM WAV。
关键模块generate_omnivoice.py解决 OmniVoice 参考音频对齐
当用户没有填写参考原文时,对“实际送入模型的预处理音频”执行本地 Qwen3-ASR 转写,而不是转写另一份未经裁剪的文件。音频 token 与转写按文件路径、大小、修改时间和截取时长生成缓存键,防止串音色。
如实实现 OmniVoice 表达预设
耳语使用原生
whisper指令;平静、高兴、悲伤、激昂、严肃通过 OmniVoice 确实支持的音高、语速、温度等参数组合近似。界面和文档明确标注“表达近似”,不伪装成 IndexTTS 2.0 的情绪向量。接入 Fish Audio S2 Pro
增加克隆、自动/多说话人、行内表达标签和独立采样参数。输出 44.1 kHz;参考编码可以缓存。为避免长文一次推理申请过大统一内存,普通文案按最多 60 字、标点优先切分。
处理 Fish 长文截断与恢复
音频 token 安全下限设为 1024;触顶后自动加倍,最高 4096。每完成一个短片段立即更新进度并写入
.partial.wav,终止任务时保留已完成音频,避免整篇重做。接入 VoiceStudio 原生 OmniVoice
不启动完整桌面前端,只在独立 PyTorch/MPS 子进程中调用固定版本的原生引擎。语音模型走 MPS,audio tokenizer 走 CPU。切换到其他引擎时终止 worker,释放内存。
关键模块generate_voicestudio.py设计按模型隔离的参数档案
五个引擎各自保存设置。切换模型时恢复该引擎上次使用的参数,“恢复推荐设置”只重置当前引擎。无效控件动态隐藏,降低把 IndexTTS 参数误传给 OmniVoice 的风险。
建设音色库
参考音频、预览音频、音色条件、显示名称、常用状态和参考原文形成一个可复用音色档案。选择后可立即试听并作为当前音色;删除操作保留独立危险语义。
实现长任务状态机
任务状态包括 idle、running、paused、cancelled 和 completed。进度记录当前片段、总片段、开始时间、暂停时间与已完成耗时;取消信号在每个安全片段之间检查。
统一输出与质量检查
先生成浮点音频,再检查空结果、异常峰值、硬截断和时长,最终导出 WAV、MP3 或 FLAC。文件名取文案开头的有效字符,同名追加序号,不覆盖历史文件。
完成界面信息架构与浏览器验证
针对长音色名重新分配音色选择区、常用按钮与删除按钮宽度。实测选择区约占 83.3%,操作按钮保留语义和可点面积;相关回归测试通过后才进入发布版本。
阶段三
开发视频首页 MP4 生成器。
定义最小输入合同
音频和至少一张图片是必需项;口播文案可空;字幕默认关闭。第一张图片是首页,后续图片是内容图,上传顺序就是播放顺序。
建立 Flask 异步任务接口
POST /api/generate只负责校验、落盘、创建job_id和启动后台线程。页面通过状态接口轮询,避免长时间请求因编码耗时而断开。关键模块webui.py保存可审计任务目录
每个任务目录保存原始输入、解析后的逐句文本、处理后画面、字幕 PNG、日志、状态、结果 JSON 与最终 MP4。问题发生时可以定位到图片处理、字幕对齐或编码阶段。
解析口播文案
跳过 Markdown 标题,将正文按中文和英文句末标点拆句;标点不足时按原始行回退。没有有效句子时自动进入无字幕模式。
确定画布和方向
读取第一张图片并应用 EXIF 方向。自动模式保留原始横屏、竖屏或方形比例;H.264/YUV420P 遇到奇数边长时只补 1 像素,不进行无谓缩放。
生成首页和内容画面
所有图片进入同一画布处理流程;只有首页叠加主题、副标题、遮罩、描边和阴影。内容图保持干净,避免标题重复。
关键模块scripts/make_homepage_bg.py构建图片时间线
单图时覆盖全部音频。多图时播放
1 → 2 → … → N → 1,首尾首页各不超过 3 秒,其余内容图均分剩余时长;短音频按所有播放段均分,不产生负时长。检测音频停顿
FFmpeg
silencedetect使用约 -38 dB、0.15 秒参数提取停顿,排除头尾静音后,选取最长的“句数减一”个停顿作为句界,再恢复时间顺序。预渲染逐句字幕
PIL 将每句字幕绘制成透明 PNG,提供颜色、描边、阴影和自动换行。存在首页副标题时,字幕区域从副标题下方开始,并自动缩小字号避免越界。
使用绝对时间戳合成
每个字幕使用
overlay enable='between(t,t0,t1)'显示。所有字幕、背景和音频在一个 FFmpeg 命令中完成,避免多次转码和逐句累计误差。关键模块scripts/compose_video.py按内容选择帧率
无字幕单图使用 1 fps;无字幕多图至少 5 fps,并根据最短图片段自适应提高;有字幕使用 10 fps,将时间对齐误差控制在约 100 ms 内。
硬件编码与自动回退
macOS 首选
h264_videotoolbox + aac_at。VideoToolbox 或 AudioToolbox 当前不可用时,自动回退libx264 ultrafast + AAC,任务无需用户重新提交。解决桌面启动环境差异
从桌面 App 启动时往往没有 Homebrew PATH。程序依次探测
/opt/homebrew/bin、/usr/local/bin、/opt/local/bin,再回退系统查找,保证能找到 FFmpeg 与 ffprobe。汇总结果与历史记录
结果 JSON 写入音频时长、视频时长、源图尺寸、输出尺寸、方向、字幕状态、图片数和同步表。成品复制到统一输出目录,文件名沿用首页图片主体,同名自动追加序号。
阶段四
把两套应用串成十万字、二十万字级项目。
按章节建立项目清单
项目规模不设置业务层固定篇幅上限。10 万字可以作为一个受保护任务或多个章节任务;20 万字及更大项目按书、章、节拆成批次。每个批次记录文本范围、音色、模型、参数、随机种子、输出文件和状态。
任务内继续安全分段
“项目批次”解决规模问题,“模型安全片段”解决推理稳定性。即使一个章节包含几万字,送入模型的每次推理仍控制在该模型经过验证的安全范围。
逐段落盘与可恢复执行
生成一个片段就落盘并更新清单。发生暂停、取消、机器重启或单段失败时,从未完成的片段继续,而不是从项目开头重做。
统一合并与章节边界
按清单顺序合并音频,在章节之间插入可配置静音或交叉淡化。最终既可交付单章文件,也可合成整本长音频。
长视频由音频时长驱动
视频合成本身没有写死分钟数上限,总时长取决于音频。数小时内容可以输出为单个 MP4,也可以按章节拆成多集;实际限制来自磁盘空间、编码时间和目标平台上传规则,而不是页面人为截断。
批量视频保持确定性
每集使用明确的首页图、内容图顺序、音频、文案和参数。结果清单记录成品路径、时长、画面尺寸、字幕句数与校验状态,便于后续平台发布。
准确表述:当前 TTS WebUI 单任务设有 100,000 字符保护上限;20 万字及更大项目通过章节和批次队列完成。这样既能承接大规模内容,又不会把“无限”误解为一次性把整本书塞进模型。
阶段五
测试、验收与失败恢复。
| 测试对象 | 正常路径 | 边界路径 | 验收证据 |
|---|---|---|---|
| TTS 模型切换 | 五个引擎逐一加载并生成 | 切换时释放旧模型;隐藏无效参数 | 输出文件、参数档案、内存释放日志 |
| 音色克隆 | 清晰参考音频和匹配原文 | 缺原文、本地 ASR、不同音色缓存隔离 | 参考转写、音色条件、试听结果 |
| 长文生成 | 多段连续输出 | 暂停、取消、token 触顶、异常时长 | 进度、partial WAV、重试日志 |
| 图片时间线 | 单图与三图 | 短音频、奇数尺寸、EXIF 旋转 | ffconcat、播放顺序、输出宽高 |
| 字幕同步 | 停顿充足的逐句口播 | 停顿不足、长字幕、副标题避让 | 同步表、PNG 尺寸、帧对齐时间 |
| 视频编码 | VideoToolbox + AudioToolbox | 硬件编码失败后软件回退 | ffprobe 编码、时长、播放检查 |
“页面显示完成”不是验收。音频要能播放且无明显截断;视频要核对时长、宽高、H.264/AAC 编码、首尾画面、字幕边界、下载名和输出目录。失败时保留日志与中间产物,先定位具体阶段,再决定重试、降级或调整输入。
阶段六
让人能看懂,也让 AI 能准确检索。
每个主题使用独立 URL
首页、IndexTTS2、视频生成器、完整开发过程和模型比较分别有独立中英文地址,避免所有内容埋在一次 JavaScript 切换中。
先写事实,再写宣传
页面保留模型名、运行时、采样率、输入条件、接口、状态、算法、优点、缺点和限制。检索系统可以直接抽取事实,不需要从口号推断。
提供结构化入口
HTML 中加入 SoftwareApplication、HowTo、FAQPage 与 ProfessionalService Schema;同时提供
llms.txt、llms-full.txt、模型 JSON、开发步骤 JSON 和 sitemap。保持中英文一一对应
使用
hreflang标记语言版本,中文为默认;英文页面保留相同事实结构,方便跨语言 Agent 与搜索引擎建立对应关系。公开可访问并持续验证
部署后确认页面、图片、纯文本索引和 JSON 端点均返回成功状态。后续每次修改继续更新最后核对日期与结构化数据。
下一步