2026 | Logs
一月
01.26~02.01
01.26
等待项目审批通过中。
01.27
今天从Max那里得知了Eva审批项目通过,可以开始(虽然教务处那边似乎还没给我录入系统)于是我翻出来了之前做的那个Demo并且结合了以往的那些问题向Gemini提问。之前,我用的是FunASR-LLM-XTTSv2的组成,你要说能用吧我那个demo就在那,确实能输入,能识别,能输出。但你要说不能用吧,我也认可。毕竟10秒往上的延迟,再加上那么烂的准确率,我只能说不如我自己翻。
对于这个项目,我比较担心的除了学分到底什么时候给我算上之外,主要的就是我到底能不能做出来,能做成什么样子。首先现在的保底就是Demo,能用,但只能用一点点。不过我不打算就此开摆,总要先试试。现在在一个很难开始的状况下,因为我希望了解的越多越好,这样开始之前有一个所谓的全局观,或许开发的时候才能少走点弯路。
开始之前我先在没有前情提要的情况下咨询了Gemini,它给出的模块确实是我之前没发现的一些东西。当然我在想怎么记录和LLM的对话,这也是个问题。在S-T-S这三部分里面,Gemini给出的建议是Faster Whisper + 本地小模型(Qwen/MarianMT) + GPT-SoVITS。
首先Faster Whisper这玩意我是用过很多的。我知道V3模型在识别中文的开头结尾的时候很容易产生幻觉,出现什么“请点点关注,谢谢观看xx频道”之类的数据污染问题。不过Gemini声称这玩意好解决,只要你不让它录到空白就行了,这事我们再看是不是真的。本地小模型么,我确实得筛选一批好用的出来,毕竟之前那套系统我单独把LLM放在16G的电脑上跑,这要给普通用户来用门槛有点高了。据我现在所知,如果不用额外数据调整小模型(3b以下)我知道效果很烂(也有可能是我打开方式不对罢),这也是一个要解决的点。最后呢就是这个我从未听说过的GPT-SoVITS,草率看了一眼似乎很强大的一个VITS,十秒语音就可以模仿并超越(划掉)。这估计比XTTS要强很多,甚至能在这个流程里代替RVC的存在。
Gemini建议我用cursor编辑器+Claude3.5,一点一点把代码写出来而不是一下子把所有的东西全部写出来。另外OBS串流字幕那边它也建议用html+css来实现,这确实之前没有想到。另外它也建议常用Git及逆行本地存档。不过其它可能存在但我预测不到的问题它也预测不到,所以这个再议。至于日志,我们可以写在这里。
Gemini建议从模块化的第一部分开始,用Faster-Whisper把听写部分跑通,然后再处理剩下的内容。这里主要的问题在于如何让听写系统预处理,片段化输入之类的。另外目前似乎没有办法把Faster-Whisper这部分客制化,也就是让客户自己训练一个声音识别模型(或许直接用Faster-Whisper已经足够了)。Gemini提到,为了让STT系统识别更准确,可以使用prompt让它吸收某领域的专业词汇,这样据说识别正确率会高很多。另外它还提到可以试试Whisper-Fine tuning,据说数据量也不大。这个也可以再议。
至于第二部分翻译层,则可以用RAG或者Few Shot来让模型知道我们在干什么,我们需要哪些信息。最后的TTS部分, Gemini似乎非常相信GPT-SoVITS这块的能力,我看了他们的Demo确实觉得挺厉害的。在目前的这个预计设定下,这个系统应该可以输入中英杂糅的内容,然后输出为英语或者中文。最后我目前能想到的一个希望实现的特殊点就是类似于Zoom会议自动字幕矫正错误的功能,Gemini提到用Rolling Buffer这种动态缓冲区来截取过去5-10秒的内容给Whisper,随着缓冲区音频越多,上下文越完整,识别内容就越准确。不过这可能会拖慢翻译速度。Gemini推荐把这些东西分为稳定文本和不稳定文本,在检测到“没想好”的内容时不推送给翻译程序,在半句话(标点分割)或者一句话(句号分割)结束之后再送去翻译。另外,它还推荐了faster-whisper-streaming这类封装库,比如whisper-streaming或者Faster-Whisper流式,结合VAD(语音活动检测)和重叠推理(Overlapping Inference)来提升正确率,减少一段只识别几秒钟的没头没尾风险。
Gemini也推荐我学一下Miniconda环境隔离。
所以目前看来计划是这样:
计划
第一阶段:基础设施 (W1-W2)
- 目标: 环境搭建与音频路由。
- 任务: * 安装 CUDA/cuDNN 环境。
- 跑通本地虚拟声卡路由(实现需求 10 的双向录音地基)。
- 写出第一个“录音机”脚本。
第二阶段:流式听写模块 (W3-W4)
- 目标: 实现低延迟、无幻觉的 STT。
- 任务: * 部署 Faster-Whisper,集成 Silero-VAD。
- 实现“动态刷新文字”的逻辑。
- 完成 SRT/TXT 两种格式的文件流写入。
第三阶段:翻译与定制化 (W5-W6)
- 目标: 专业领域翻译。
- 任务: * 部署 Qwen-1.8B 模型。
- 编写“术语注入”功能(通过修改 System Prompt)。
- 测试中英双向切换。
第四阶段:TTS 与声音克隆 (W7-W8)
- 目标: 让翻译开口说话。
- 任务: * 部署 GPT-SoVITS。
- 录制并微调你自己的音色模型。
- 难点攻克: 减少 TTS 推理的首字延迟(First-fix latency)。
第五阶段:集成与 OBS 字幕 (W9-W10)
- 目标: 联调与可视化。
- 任务: * 开发基于网页的实时字幕板(OBS Source)。
- 将 STT、NMT、TTS 串联。
- 实现双录音文件实时写入。
第六阶段:优化与轻量化 (W11-W12)
- 目标: 压榨性能,确保 8GB VRAM。
- 任务: * 模型量化(使用 4-bit 量化)。
- 显存回收机制优化。
第七阶段:交付准备 (W13-W14)
- 任务: 编写 README、录制 Demo、整理 180 小时开发日志。
最后Gemini推荐我用Cursor作为IDE。我暂且相信它一回,等学分确定下来了就开七天试用。
二月
02.02~02.08
02.07
这周本来应该要干活的,要干正式的活。只不过这周一直在测试之前写好的听写环节,于是基本没有什么新的进展。我们尝试了用RAG,也就是之前Gemini推荐的一个提升准度的办法,后来我才知道RAG对于文本处理流程来说是正确的,而对于音频处理流程来说基本毫无卵用。于是我们只剩下一个训练模型的路子可以走。所以目前来看我们还要做一套可以训练的框架,让用户通过上传他们自己需要的内容对这个模型的某一些层面进行训练。如果顺利,我们今天应该可以把这个东西的初始结构做出来,并且搞明白我们到底要用什么样的数据来进行训练。至于训练效果我不好说。
我们的训练将在5060上进行,希望有它所说的“一天时间”就可以训练出来一个完整的,有能效提升的模型。
折腾了俩小时之后我发现可能大概率不需要用训练来提升模型准确度,但我还是会准备一些训练用的材料。另外我们在做下一步的时候可以让它通过一开始的“xx地图”和我选择的xx英雄来引用不同的可能存在的英雄技能,这样说不定还能提升一些效率。
02.09~02.15
02.09
是时候把Github上真正的项目初始化了。在真正开始之前,让我们来梳理一下现在我们都有什么,接下来要做到什么。我们的系统目前还是分为三个部分,第一部分是STT,由FasterWhisper Large v3 Turbo驱动。第二部分是一个文本转译程序,由Qwen3-4B-Instruct (Q4_K_M)驱动。第三部分则是GPT-SoVITS驱动的TTS。这个项目充斥着大量的猜测和感觉,可以说是一个十分不专业的代码构建方式,毕竟我也不懂。
STT
这部分原来预定的计划是要做到:
- 可以识别语音输入
- 可以在短时间内把语音转换为文本
- 可以保证文本正确率足够
做着做着发现几个问题,首先仅仅让它识别对中文的语音输入就够折腾的了,要让它在保证正确率的情况下要达到一个低延迟的效果更是费劲。目前能识别这块没问题。但是具体到一些特定情况下就比较难说了。如果让它识别我的日常用语,假设我每天睡觉之前来个当日总结然后念给它听,这应该属于和它的知识储备更为接近的内容。不过说实话我还真没试过,只是感觉要想达到更高的识别率这里面需要规范化的东西太多,我很难知道我说的东西到底有什么它不知道有什么它知道,无从下手属于是。不如找一个已经有规范化的题材来进行测试,但这个规范化的内容又基本不和它的知识储备相融合,再加上这种数据我随手就能生产,那么是什么呢?守望先锋的游戏录播。
在我玩过的众多游戏里面守望先锋(下称OW)是为数不多节奏快,并且能让我多说话的一款游戏。如果我玩文明或者天际线,那我可能十个小时就说几句话。假设我未来要训练模型,我总不能每次都录十小时然后挑那五句话出来。那有人就要问了,诶你这个要说什么自己录好给他训练不就完了?并非这么简单。我只能说我知道我大概会说什么东西,我也有一些常用语,但我不能确保这些常用语出现的位置和时间每次都一样,而最好的(我猜)方式就是我每次录完统计下来,然后把真实的情况喂给它。于是OW的录播就成了既有不少既定术语,又有一些近音/同音字词,还有很多都不在它的知识范围内。所以我们的其中一个目标就是训练它能够识别我在玩OW的时候讲的话,并且达到一定的正确率。
然后就是关于转换延迟的问题。目前我们所能达到最低的转换延迟大概是1.3秒左右,这个延迟用在可以逐渐出现的实时字幕上勉强能行,毕竟从我说话开始到它出现再到我说完那一句话结束识别,这段时间肯定比1.3秒长,于是就不会给人一种永远慢半拍的感觉。只不过在这个延迟之下,我很难说正确率到底有多少。我们试过了更改窗口时间和上文时间,再短就识别不出来了。于是目前来看,我们拥有了至少1.3秒延迟。
LLM
这部分简单,至少目前在我看来,调整的部分应该要比STT那块轻松。大不了直接上RAG,目前我们纯LLM输出的时间大概在0.5秒左右,满打满算加上STTy也就2秒时间(最佳状况下)。
TTS
这块还没开始研究,但这个TTS的时间应该不会太长。目前大概在1.5s左右,所以再加上之前的流程最佳状况下能在3.5s之内出来第一句话。这对于同传效果来说还算不错。
接下来我们要把这之前的三样东西全部整合在一起,然后继续慢慢调整,增加一些新的功能。然后我遇到了硬盘空间不够的问题,让我先解决一下。不看不知道,一看吓一跳。我达芬奇项目文档里竟然有200G的代理文件,我寻思删完原视频也没山那玩意。
整合
接下来的工作是整合,然后在现阶段的成果上再提出一些功能性需求。总体上讲,所有的选择或者说开关最好都做成一触即发的,不需要用户重启系统或者重载模型。
首先我们从识别这块开始说起。第一是语言选项,我知道whisper支持一堆各种各样的语言,但我们这里只让他识别中文和英语,以及输出相同的识别语言。因为我试了auto-detect,这玩意老是把我发音不清晰的东西识别成别的语言,并且auto-detect这玩意初始化还需要几秒钟时间,完全就是拖累。我们如果在指定了语言代码之后再给它偶尔的中英杂糅,一般来说问题也不大。所以,这里我们只需要一个下拉菜单形式的语言选择器,放上中文和英文。
然后就是为了识别正确而准备的各种设定。首先是关于模型本身的各种设定,比如片段窗口时常,确认阈值,等等一系列已经存在的东西。这块我们暂时不详细列出来(待会再加上,毕竟我不是很懂这玩意)。这一块要注明哪些设置怎么调会拉长延迟但是提高精确度,哪些本质上影响不大。
接下来是几个附加功能,比如我们已经在用的RAG和模糊拼音比对,用户可以自行选择开启或者关闭。这里也要写上开启或者关闭带来什么样的正面和负面影响当然,RAG和模糊拼音比对这类东西的数据来源都是用户所产生的材料,因此还得有一个窗口来让用户可以轻易的编辑当前资源文件夹里面的那些文件,并且规定好文件格式以及文件内部格式,例如一行一换或是一空格一换等等。
最后考虑到以后我们可能要训练不同的模型,我们也要做一个单独的训练标签页,让用户可以方便的管理文本和音频素材,以及进行一件训练,查看训练进度以及测试训练结果。因此我们要在load model那里加一个下拉菜单,以及新建一个单独的训练标签页。在训练标签页里我们要把各种设置都预设好,做成一个用户友好的界面,让用户可以轻松的瞄准这个模型的某些层面进行微调,而不是上来就训练整个模型。
除此之外,涉及到训练和运行模型这一块,我们要提前准备好可能出现的环境问题。我们预设的场景是使用CUDA加速或者使用AppleSilicon运行,因此我们至少要满足Windows和Linux这两个平台上使用Nvidia GPU运行的环境。据我所知,我们需要单独搭建为Qwen3架构的模型准备的运行框架。另外在LLM这一块,我们也要准备好一个用户友好的界面,可以让用户随时修改提示词,挂载的知识库内容,以及其它东西。
最后是TTS。我们应该让用户可以轻松地更换和录制参考音频以便VITS发力。目前我还没研究到优化VITS输出速度这一块,等以后研究到了相应的面板也要加上。
所以整体流程有这些内容:
用户指定一个输入语言,一个输出语言 > 用户开始说话 > STT 开始识别转换 > 识别可能存在的误听(比如模糊拼音,使用模型自带的逻辑衡量是否为幻觉etc)并自我更正 > 输出内容 > 消除重复内容以及幻觉 > 写入OBS实时字幕 > 继续经过LLM+RAG或者某些提示词或者知识库校正 > 去掉标点的版本写入srt > 带标点的版本写入txt文档 > 继续经过LLM (按理说这里可以用同一个LLM来处理不同的文本,毕竟这玩意算的挺快的)将其翻译到目标语言(同时应用一些语体矫正之类的提示词,以及知识库,rag等) > 去掉标点的版本写入OBS实时字幕 > 另外还要写入SRT > 带有标点的版本写入TXT文档 > 发送给VITS/TTS > TTS进行朗读。
所以总的来说,我们的UI要有这些部分:
- UI分为几个不同板块,我们先将上下一分为二,形成A,B两个板块。A在上,B在下。
- 首先是A
- 在上面A部分的再进行左右的一分为二,将其分为A1与A2。A1在左A2在右。
- 将左侧的A1上下分开,分为A1a与A1b。A1a在上,A1b在下。
- A1a这部分展示实时语音转写的文本全文(逐渐以streaming方式呈现),A1b则展示实时转译完成的文本(逐渐以streaming方式呈现)。这就是A1部分的内容
- A2整个板块中则展示这几个值
- 当前GPU使用率(百分比)与 VRAM使用率(量/总量)
- 当前语音转实时文本延迟(OBS实时文本,也就是从用户说话开始到字幕出现在OBS那一刻的延迟),单位毫秒
- 当前语音转文本延迟(完整文本,也就是被二次修正过的文本,也就是即将等待翻译的那些文本,也就是展示在A1a当中的文本)毫秒
- 当前翻译延迟,也就是A1a文本从即将等待翻译的文本经过LLM转译到A1b那些已经被翻译完文本的延迟(毫秒)
- 当前文本转语音延迟,也就是A1b文本经过VITS转换为语音的延迟,毫秒。
- 当前系统状态:是否加载了某个模型,是否开启了STT,是否开启了OBS实时字幕,当前识别哪种语言,是否启用了LLM转译,当前正转译为哪种语言,以及是否开启了TTS
- 然后是B
- 这部分将由不同的选项卡组成,分别为
- 听写模型
- 一个开关,用于启用/停用STT部分。让用户注意,如果停用了该部分,将无法活得OBS实时字幕。但是我们可以仍旧单独让LLM翻译模块工作,也就是说如果用户往这个A1a那里手动写东西或者复写内容的话,我们要在A1b里展示翻译过的文本。这种情况下整个系统(假设只有LLM工作)就像一个普通的谷歌翻译/Deepl翻译器一样。由于没有时间轴,当单独启用时,不写入txt/srt文档
- 这里使用下拉列表来展示模型文件夹里的不同模型
- 使用一对按钮“加载”与“卸载”来控制模型是否加载。
- 加载/卸载后同步更新A区里模型的状态。一个模型已经加载时,用户必须先点击卸载后才能选择另一个模型然后加载。卸载模型时清理VRAM以及碎片化的缓存等。
- 设置一个下拉菜单,放入中文和英文和auto-detect三个选项,这个菜单用来指定用户说话的语言,也就是识别的语言。当用户选择了某一个选项,立刻更新语言代码或换为auto detect,不需要重复加载模型
- 设置一个“训练”按钮,点击后打开一个新UI页面专门供训练使用(这个页面回头再设计,我还不知道要加什么东西)
- 在模型标签卡里再设置不同的模型调整参数,来控制模型的各个参数,并写明每个参数的用途。这里可以在每个参数的标题(假设有一项是调节‘topk“,则在该词条后面加一个”info“的标志,当用户将鼠标悬停在info标志上可以展示该词条是什么意思,如何调整是最佳状态,以及调高了影响哪些些东西,调低了影响哪些东西)以及一个”重置“按钮以恢复默认值
- 输出
- 这里使用不同的复选框让用户来勾选他们想要得到的文件和功能
- 输出OBS实时字幕:勾选后展示一个地址,例如localhost:5123让用户可以在obs里设置
- 是否启用源语言的开关
- 是否启用目标语言的开关
- 输出实时字幕txt文本:将未经二次矫正的OBS实时字幕合为一个txt文档。由于这里本来就没有设定要让实时字幕带上标点符号,所以里面应该是中文字符短语+空格分隔
- 输出源语言完整字幕txt文本:将经过校对的字幕合为一个txt文档,这里应该有正确的标点符号
- 输出源语言完整字幕srt版本:这里应该使用正确的srt格式,并且不带标点以空格分隔,但是应该是校对过后的文本内容。
- 输出一个wav文件,用于重新复查和潜在的训练需求。
- 输出目标语言的完整字幕txt文本:将经过翻译的字幕写入一个txt文档,这里应该有正确的标点符号
- 输出目标语言的完整字幕srt版本:将经过翻译的字幕写入一个srt文档,这里里应该使用正确的srt格式,并且不带标点以空格分隔。
- 输出OBS实时字幕:勾选后展示一个地址,例如localhost:5123让用户可以在obs里设置
- 翻译模型
- 一个开关,用于启用/停用LLM翻译部分。就如同我在听写模型里面第一点写的一样,这东西应该可以独立开启,然后作为手动打字输入/输出的翻译引擎使用。当单独启用时,不写入txt/srt文档。
- 一个下拉菜单选择输入源语言是何种语言,提示用户这里要和听写模型那里一样。给的选项也是三个,中文,英文以及自动检测。这里也要做到用户选完不需要点确定就立刻应用。
- 一个下拉菜单选择翻译至何种目标语言,中文或者英语。这里也要做到用户选完不需要点确定就立刻应用。另外提示VITS参考音源应该优先使用这种目标语言的音频。
- 一个编辑提示词的地方
- 一个让翻译模型挂载知识库的地方(例如RAG,等等)
- 一个调整翻译模型本身数值的地方(参考听写模型的第六点)
- VITS
- 两个开关,一个用于启用/停用源文本(也就是纠正过的TXT那块输出内容的TTS。启用源文本时,这玩意就是个变声器(在STT运行情况下)或者纯TTS(在STT不运行时);另一个用于启用/停用目标语文本。两项可以同时启用,但是要提醒用户安排虚拟声卡来接入不同的内容,这样就可以达成多语言同传的效果,当然我们也要将其加上输出至不同声音设备的选项。如同源文本TTS一样,如果此时STT未启用则就是一个纯TTS,如果STT启用就是一个实时同传系统。
- 一个可以让用户轻松打开参考音源文件夹的按钮以及音源文本的按钮。(按说这俩应该在几乎同一个地方,所以可以用一个按钮)
- 一些参数调整(我还没研究到这,不知道有啥参数可以调整,总之到时候再加)。
- OBS实时字幕效果。
- 这里给一些控制选项来调整基于html/css的obs字幕控制效果,让两种语言分别应用效果。
- 源语言应该在OBS字幕里的上面一行(假设二者都启用)
- 目标语言应该在OBS字幕里的下面一行(假设二者都启用)
- 假设只有2选1启用,则放在两行字幕原有的中间位置。
- 一个预览窗口,可以让用户在输入框里打几个字之后在底下看到相应字符的预览样式。(当然源语言和目标语言都要有)
- 源语言和目标语言分别可调字体样式。可以让用户自行选择字体并放入一个资源文件夹,或者使用google的字体。
- 源语言和目标语言分别可选字体大小。
- 这里给一些控制选项来调整基于html/css的obs字幕控制效果,让两种语言分别应用效果。
- 单独的训练页面。这里我还没有任何想法,但我们可以留出来这一个功能。
- 首先是A
那么接下来让我想想怎么样把这套UI搞出来,然后连上我们现有的东西。现在是下午两点十六,让我们看看过多久我们能把这东西弄好。我们先试试这玩意会不会把我仅剩的50%token用爆了,如果即将用爆还搞不定的话,我打算试试cursor。
Gemini让我用pyqt而不是Gradio。它说这玩意更稳定更快。14:32
现在是16:39,目前正在创建项目中。Claude认为我们不需要3个venv,因为STT和LLM以及UI可以共用一套venv,而TTS因为有一些严格的依赖需求,所以即便三个python版本都用3.11也要分隔来。
现在是18:12,我没想到Claude4.6的三倍用量如此之丝滑。我们先把开发流程贴在下面,然后我们来讲每一步的进展。
新计划
Vocal10n Rebuild Plan
Decisions Made
Decision | Choice |
|---|---|
Venvs | 2 separate: Main/STT+LLM+UI (Python 3.11), TTS (Python 3.11) |
UI Framework | PySide6 (Qt6, LGPL) |
Directory Layout |
Python package with submodules |
TTS Architecture | GPT-SoVITS as separate subprocess, HTTP API on port 9880 |
Git | GitHub repo
, exclude
|
Target Directory Structure
Vocal10n/
├── .gitignore
├── README.md
├── LICENSE
├── pyproject.toml # Project metadata
├── setup_env.ps1 # One-click environment setup
├── start.bat # Launch script (Windows)
├── start.ps1 # Launch script (PowerShell)
│
├── src/
│ └── vocal10n/
│ ├── __init__.py
│ ├── app.py # Main entry point
│ ├── config.py # Global config loader (YAML)
│ ├── state.py # Thread-safe global state (SystemState)
│ ├── constants.py # Shared constants, enums
│ │
│ ├── stt/ # Speech-to-Text (FasterWhisper)
│ │ ├── __init__.py
│ │ ├── engine.py # FasterWhisper wrapper, streaming
│ │ ├── filters.py # Hallucination filter, phonetic correction
│ │ ├── audio_capture.py # Microphone input, VAD
│ │ └── transcript.py # Segment management, confirmation logic
│ │
│ ├── llm/ # Translation Engine (Qwen3-4B via llama-cpp)
│ │ ├── __init__.py
│ │ ├── engine.py # llama-cpp-python model loader
│ │ ├── translator.py # Translation logic, prompt templates
│ │ ├── corrector.py # Source text correction (punctuation, RAG)
│ │ └── rag.py # Knowledge base / RAG integration
│ │
│ ├── tts/ # Text-to-Speech (GPT-SoVITS client)
│ │ ├── __init__.py
│ │ ├── client.py # HTTP client to GPT-SoVITS API
│ │ ├── queue.py # TTS queue manager, buffering
│ │ ├── audio_output.py # Playback, device selection
│ │ └── server_manager.py # Subprocess launcher for GPT-SoVITS
│ │
│ ├── pipeline/ # Orchestration
│ │ ├── __init__.py
│ │ ├── coordinator.py # Main pipeline: STT→LLM→TTS flow
│ │ ├── events.py # Event dispatcher (pub/sub)
│ │ ├── latency.py # Latency tracker
│ │ └── file_writer.py # SRT, TXT, WAV output
│ │
│ ├── ui/ # PySide6 GUI
│ │ ├── __init__.py
│ │ ├── main_window.py # Main window (A/B split layout)
│ │ ├── section_a.py # Top: A1 (text streams) + A2 (metrics)
│ │ ├── section_b.py # Bottom: Tab container
│ │ ├── tabs/
│ │ │ ├── __init__.py
│ │ │ ├── stt_tab.py # STT settings tab
│ │ │ ├── translation_tab.py # LLM settings tab
│ │ │ ├── tts_tab.py # TTS/VITS settings tab
│ │ │ ├── output_tab.py # Output settings tab
│ │ │ ├── obs_tab.py # OBS subtitle styling tab
│ │ │ └── training_tab.py # Training placeholder tab
│ │ ├── widgets/ # Reusable custom widgets
│ │ │ ├── __init__.py
│ │ │ ├── param_slider.py # Parameter slider with info tooltip
│ │ │ ├── model_selector.py # Model dropdown + load/unload
│ │ │ └── stream_text.py # Streaming text display widget
│ │ └── styles/
│ │ └── theme.qss # Qt stylesheet
│ │
│ ├── obs/ # OBS overlay server
│ │ ├── __init__.py
│ │ ├── server.py # Flask/HTTP server for OBS Browser Source
│ │ └── overlay.html # HTML/CSS template
│ │
│ └── utils/ # Shared utilities
│ ├── __init__.py
│ ├── gpu.py # GPU/VRAM monitoring (pynvml)
│ └── logger.py # Logging setup
│
├── config/
│ └── default.yaml # Default pipeline config
│
├── models/ # Local model storage (git-ignored)
│ ├── stt/ # FasterWhisper models
│ ├── llm/ # Qwen3 GGUF files
│ └── tts/ # GPT-SoVITS pretrained models
│
├── reference_audio/ # TTS reference audio (git-ignored)
│
├── knowledge_base/ # RAG knowledge files
│ └── .gitkeep
│
├── output/ # Generated files (git-ignored)
│ ├── subtitles/
│ ├── audio/
│ └── training_data/
│
├── training/ # User training data (git-ignored)
│
├── vendor/ # Vendored dependencies
│ └── GPT-SoVITS/ # Embedded GPT-SoVITS (git-ignored)
│
├── venvs/ # Virtual environments (git-ignored)
│ ├── venv_main/ # Python 3.11 — STT + LLM + UI + Pipeline
│ └── venv_tts/ # Python 3.11 — GPT-SoVITS server
│
├── requirements/ # Per-venv requirements
│ ├── requirements-main.txt # STT + LLM + UI + Pipeline deps
│ └── requirements-tts.txt # GPT-SoVITS deps (for reference)
│
└── Vocal10n-prebuild/ # Legacy prebuild (git-ignored, local only).gitignore Plan
# === Environments ===
venvs/
venv*/
__pycache__/
*.pyc
.env
# === Models (large binaries) ===
models/
*.gguf
*.pth
*.ckpt
*.safetensors
*.bin
*.whl
# === Vendored code ===
vendor/
# === User data ===
reference_audio/
training/
knowledge_base/*.db
knowledge_base/*.index
# === Output ===
output/
*.wav
*.srt
# === Legacy prebuild ===
Vocal10n-prebuild/
# === IDE / OS ===
.vscode/
.idea/
*.swp
Thumbs.db
.DS_Store
# === Logs ===
*.log
logs/Master To-Do List
Phase 0: Project Foundation
- [x] 0.1 — Initialize git repo, connect to GitHub remote
- [x] 0.2 — Create
.gitignorewith all exclusion patterns - [x] 0.3 — Create directory skeleton (all dirs with
__init__.py/.gitkeep) - [x] 0.4 — Create
pyproject.tomlwith project metadata - [x] 0.5 — Create
config/default.yaml(port from prebuild'spipeline_config.yaml) - [x] 0.6 — Create
requirements/files (derive from prebuild deps) - [x] 0.7 — Write
setup_env.ps1to create 2 venvs and install deps - [x] 0.8 — Initial commit & push
Phase 1: Core Infrastructure
- [x] 1.1 — Implement
constants.py— enums (EventType,Language,ModelStatus,TTSSource) - [x] 1.2 — Implement
config.py— YAML config loader/saver (dot-key access, thread-safe) - [x] 1.3 — Implement
state.py— thread-safeSystemState(Qt signals for UI binding) - [x] 1.4 — Implement
pipeline/events.py— event dispatcher (port from prebuild, sync-only) - [x] 1.5 — Implement
pipeline/latency.py— latency tracker (Qt signal on update) - [x] 1.6 — Implement
utils/gpu.py— GPU/VRAM monitoring (pynvml) - [x] 1.7 — Implement
utils/logger.py— logging config
Phase 2: PySide6 UI Shell
- [x] 2.1 —
app.py— QApplication entry, theme loading - [x] 2.2 —
ui/main_window.py— Main window with A/B vertical split - [x] 2.3 —
ui/section_a.py— A1 (streaming text panels) + A2 (metrics/status) - [x] 2.4 —
ui/section_b.py— QTabWidget container - [x] 2.5 —
ui/widgets/stream_text.py— Streaming text display widget - [x] 2.6 —
ui/widgets/param_slider.py— Slider with info tooltip + reset - [x] 2.7 —
ui/widgets/model_selector.py— Model dropdown + load/unload buttons - [x] 2.8 —
ui/styles/theme.qss— Base dark theme stylesheet - [x] 2.9 — Verify UI shell launches and looks correct
Phase 3: STT Module (FasterWhisper)
- [x] 3.1 —
stt/audio_capture.py— Microphone capture with device selection - [x] 3.2 —
stt/engine.py— FasterWhisper model loader/unloader with VRAM cleanup - [x] 3.3 —
stt/transcript.py— Segment management (pending/confirmed) - [x] 3.4 —
stt/filters.py— Hallucination filter + phonetic correction (port from prebuild) - [x] 3.5 —
ui/tabs/stt_tab.py— STT settings tab (toggle, model select, language, params) - [x] 3.6 — Wire STT to pipeline events and UI streaming display
- [x] 3.7 — Test: mic → text appearing in A1a with latency metric
Phase 4: LLM Translation Module (Qwen3)
- [ ] 4.1 —
llm/engine.py— llama-cpp-python model loader (port from prebuild) - [ ] 4.2 —
llm/translator.py— Translation logic with prompt templates - [ ] 4.3 —
llm/corrector.py— Source text correction pass - [ ] 4.4 —
llm/rag.py— Knowledge base integration (stub, then implement) - [ ] 4.5 —
ui/tabs/translation_tab.py— Translation tab (toggle, lang select, prompt editor, RAG mount, params) - [ ] 4.6 — Wire LLM to pipeline: STT events → translate → display in A1b
- [ ] 4.7 — Test: standalone mode (manual input → translation output)
Phase 5: TTS Module (GPT-SoVITS)
- [ ] 5.1 — Copy GPT-SoVITS into
vendor/GPT-SoVITS/ - [ ] 5.2 —
tts/server_manager.py— Subprocess launcher for GPT-SoVITS API - [ ] 5.3 —
tts/client.py— HTTP client (port from prebuild'stts_client.py) - [ ] 5.4 —
tts/queue.py— TTS queue with buffering logic - [ ] 5.5 —
tts/audio_output.py— Playback with device selection - [ ] 5.6 —
ui/tabs/tts_tab.py— TTS tab (source/target toggles, ref audio, device select, params) - [ ] 5.7 — Wire TTS to pipeline: translation events → synthesize → play
- [ ] 5.8 — Test: end-to-end STT → LLM → TTS
Phase 6: Pipeline Orchestration
- [ ] 6.1 —
pipeline/coordinator.py— Full pipeline coordination (port & clean up from prebuild) - [ ] 6.2 —
pipeline/file_writer.py— Async SRT/TXT/WAV file output - [ ] 6.3 —
ui/tabs/output_tab.py— Output settings (checkboxes for each output type) - [ ] 6.4 — Wire file outputs to pipeline events
- [ ] 6.5 — Test: full pipeline with all outputs enabled
Phase 7: OBS Integration
- [ ] 7.1 —
obs/server.py— Flask HTTP server for Browser Source - [ ] 7.2 —
obs/overlay.html— HTML/CSS subtitle overlay (port from prebuild) - [ ] 7.3 —
ui/tabs/obs_tab.py— OBS tab (font, size, styling, preview) - [ ] 7.4 — Test: OBS Browser Source displays live subtitles
Phase 8: Launch Scripts & Polish
- [ ] 8.1 —
start.ps1/start.bat— Launch TTS server + main app - [ ] 8.2 — A2 section: live GPU metrics, latency display, module status indicators
- [ ] 8.3 — Error handling and graceful shutdown
- [ ] 8.4 — Manual A1a input mode (standalone translator when STT is off)
- [ ] 8.5 —
ui/tabs/training_tab.py— Training placeholder tab
Phase 9: Testing & Documentation
- [ ] 9.1 — End-to-end test: speech → subtitles → translation → TTS
- [ ] 9.2 — VRAM usage validation (target: <12GB total)
- [ ] 9.3 — Latency benchmarks (STT <1.5s, total <3.0s)
- [ ] 9.4 — Write README.md with setup instructions
- [ ] 9.5 — Final commit & push
Component Dependencies (per venv)
venv_main (Python 3.11) — STT + LLM + UI + Pipeline
PySide6>=6.6.0
pyyaml>=6.0
numpy>=1.24.0
pynvml>=11.5.0
requests>=2.31.0
psutil>=5.9.0
aiohttp>=3.9.0
faster-whisper>=1.0.0
sounddevice>=0.4.6
soundfile>=0.12.1
scipy>=1.11.0
opencc-python-reimplemented>=0.1.7
pypinyin>=0.49.0
llama-cpp-python>=0.2.77 # with CUDA support
flask>=3.0.0
flask-cors>=4.0.0venv_tts (Python 3.11) — GPT-SoVITS server
# GPT-SoVITS requirements (see vendor/GPT-SoVITS/requirements.txt)
# Launched as separate subprocess — does not need PySide6Models to Copy from Prebuild
Source | Destination | Notes |
|---|---|---|
|
| ~4GB |
FasterWhisper large-v3-turbo (HuggingFace cache) |
| Can auto-download, or copy cache |
(entire directory) |
| ~3GB+ with pretrained models |
|
| Sample audio files |
|
| Gaming terminology for RAG |
Key Architecture Decisions
- Event-driven pipeline — Keep the pub/sub
EventDispatcherpattern from prebuild. It cleanly decouples STT → LLM → TTS. - PySide6 signals — Qt signals/slots replace Gradio's polling. Real-time text updates via
QTextEdit.append()with custom signals from worker threads. - Worker threads — STT, LLM, and TTS each run in
QThreadworkers. The coordinator manages lifecycle and event routing. - Config-driven — Single
default.yamlconfig file controls all parameters. UI changes write back to config. Config is the source of truth. - Graceful VRAM management — Sequential model loading (TTS first as subprocess, then LLM, then STT). Explicit cleanup on unload with
gc.collect()+torch.cuda.empty_cache().
目前来看我们已经到了第三步,也就是测试STT这一块。它告诉我不要用RAG,直接把信息写在initial prompt里面(不过我确实还是怀疑这玩意的性能问题,所以一会再进行测试。比如第一行是能检测出来,最后一行的词是不是就该忘了。)在此之前,不得不说这新款UI确实好看,并且在实时更新之类的这一块完全没有任何问题。测试完STT之后,我们让它继续进行下一步的整合,也就是融合LLM进来。我们之前搭建了一套基于Qwen3的LLM翻译器,接下来我会让它从以前的文件里面找到这个build过的版本,这样就不用从零build一个让Qwen3跑起来的框架了。
然而这玩意跑了一下结果翻译一条竟然需要五秒时间,一眼就是没用Cuda加速。
我们目前似乎遇到了一些问题,遇到了之前一样的问题,也就是Qwen3不知道怎么的没法用CUDA支持,又要自己从头build了。我以为它能够自己找到老版本做好的那个文件,但似乎它并没有理解我的意思,我们一会看看怎么个事。现在是19:10
19:27, 它似乎找到了一个ggml-cuda.dll和llama.dll,然后我问了关于linux端,它说linux端用的是.so文件。所以我猜大概率也要重新build一个?另外就是我用的GGUF是mradermacher/Qwen3-4B-Instruct-2507-GGUF版本的,而不是lmstudio版本的。我需要搞清楚这俩有啥区别。问了Gemini,LMStudio版本的大概是为了LMStudio特制的,而mradermacher的则更为通用。本质上来讲区别不是特别大(大概)。
我们把Context这块的问题搞明白了,目前我们似乎是有rag系统的,只不过加载了200个term在初始提示词里。所以或许整体识别速度会更快一点。另外,我让它开始更改UI上的一些问题,主要是文字超出了按钮的显示范围导致没法完全显示成功。现在是19:52
破案了,我们让他用unicode编码的符号字符就完事了。另外顺便让它改一下UI的总体结构,毕竟现在很多按钮都重合到一起去了。
时间来到了22:20,我们成功再一次跑通了从我说话到系统说话的全流程,接下来就是完善UI和提升效率这块的问题了。首先我们现在的问题是TTS输出非常之慢,达到了9秒左右,而之前的老系统大概是2秒。在花了一点时间解决之后,现在我们的TTS系统可以达到惊人的25毫秒延迟,史无前例的低。
时间来到了22:56,我现在才知道这25ms是http响应时间,并非TTS响应时间,🤡。TTS响应时间似乎是500ms左右,但现在被搞成了交传并非同传,我们正在解决这个问题。
现在开始这玩意被越改越慢了。Claude意识到老架构比新架构强,但现在还是在老架构上打补丁。导致目前我们TTS的响应水平奔着18秒去了,而且越来越慢。终于在一番折腾下,我们在23:46基本解决了之前累积着不出声音的问题。不过现在的问题是我第一句话如果太长,他也要等我第一句话说完才开始说话。
时间一转眼来到了1:05, 现在是
02.10
目前我们已经解决了实时语音输出的问题,总体上来看暂时还行,后面我们再解决识别准确率和延迟的问题。现在的首要任务是把整个流程跑通。OBS现在字幕的效果不错,我给它加上了延迟消失,让看视频的用户阅读起来更方便。按照现在的进度来看,我们基本可以告一段落了,后面主要就是识别准确性,降低延迟以及模型训练的事情了。照着目前的测试结果来看,我念了一段新闻,STT大概平均1.3-1.5秒,LLM翻译0.5秒,但TTS要8秒开外。
目前接近2:00,我们打算让它写出一个RAG的标签页以及一个训练的标签页之后就收工。明天可以再从前面的STT消除幻觉开始,然后提升TTS的转换速度。