2258 字
11 分钟
加载中...

重写 VRChat 翻译助手:当 VRCT 的网络问题让人抓狂

重写 VRChat 翻译助手:当 VRCT 的网络问题让人抓狂#

目录#

Tip

可直接点击文字跳转至对应章节


为什么要重写#

VRCT 是个很棒的 VRChat 翻译工具,功能强大,支持语音识别和实时翻译。但用起来有几个让人头疼的问题:

VRCT 的痛点#

  1. 网络问题

    • 模型文件托管在 Hugging Face
    • 国内下载经常失败或速度极慢
    • 需要手动配置镜像源或代理
  2. 配置繁琐

    • 需要手动下载模型文件
    • 配置路径容易出错
    • 首次使用门槛高
  3. 启动卡顿

    • 启动时立即加载 AI 模型
    • 模型加载需要几秒钟
    • 这段时间整个应用卡死

我的解决思路#

既然问题这么明显,那就重写一个:

  • 懒加载模型:启动时不加载,首次翻译时才加载,避免启动卡顿
  • 自动化配置:首次启动向导,引导用户下载模型,降低使用门槛
  • 现代化架构:Tauri + React + Python,UI 和 AI 推理分离
  • 开箱即用:尽可能减少配置步骤

于是就有了 VRC-GoTrans


技术选型#

为什么选 Tauri?#

最初考虑过 Electron,但 Electron 打包体积太大(动辄 100MB+),而且内存占用高。

Tauri 的优势:

  • 体积小:打包后只有几 MB(不含 Python 运行时)
  • 性能好:基于系统 WebView,内存占用低
  • 安全性:Rust 后端,类型安全
  • 跨平台:Windows、macOS、Linux 都支持

为什么选 React?#

前端框架选择 React 19,主要原因:

  • 生态成熟:组件库、工具链完善
  • Radix UI:无障碍、可定制的组件库
  • TypeScript:类型安全,减少运行时错误

为什么用 Python Sidecar?#

AI 推理需要 Python 生态(llama-cpp-python、faster-whisper),但 Tauri 主进程是 Rust。

解决方案:Sidecar 模式

  • Python 以独立进程运行
  • 通过 HTTP 接口与 Rust 通信
  • AI 推理不阻塞主应用

技术栈总览#

前端:React 19 + TypeScript + Radix UI + Vite
桌面壳:Tauri 2 (Rust)
AI 推理:Python 3.11 + llama-cpp-python + aiohttp
包管理:uv (Python) + pnpm (Node.js)

架构设计#

整体架构#

┌─────────────────────────────────────────────────┐
│ React 前端(Tauri WebView) │
│ - 用户界面 │
│ - 配置管理 │
│ - 翻译日志 │
└─────────────┬───────────────────────────────────┘
│ Tauri IPC
┌─────────────▼───────────────────────────────────┐
│ Rust 后端(Tauri 2) │
│ - OSC 客户端(rosc) │
│ - Sidecar 生命周期管理 │
│ - 配置持久化 │
│ - 系统信息查询 │
└─────────────┬───────────────────────────────────┘
│ HTTP (127.0.0.1)
┌─────────────▼───────────────────────────────────┐
│ Python Sidecar(uv 管理) │
│ - llama-cpp-python 推理 │
│ - HY-MT1.5 模型加载 │
│ - 异步 HTTP 服务(aiohttp) │
└─────────────────────────────────────────────────┘
↓ OSC (UDP)
┌─────────────────────────────────────────────────┐
│ VRChat (OSC 端口 9000) │
└─────────────────────────────────────────────────┘

数据流#

用户输入文本
React 组件调用 Tauri 命令
Rust 后端转发到 Python Sidecar (HTTP POST /translate)
Python 加载 HY-MT1.5 GGUF 模型
llama-cpp-python 推理生成翻译
返回翻译结果(JSON)
Rust 通过 rosc 发送 OSC 消息到 VRChat
VRChat 聊天框显示翻译

为什么要三层分离?#

  • UI 层(React):负责界面交互,不关心底层实现
  • Shell 层(Rust):负责系统调用、进程管理、网络通信
  • AI 层(Python):负责模型推理,不阻塞主进程

这样做的好处:

  • UI 永远不会因为 AI 推理而卡顿
  • Python 进程崩溃不会影响主应用
  • 各层独立开发、测试、部署

核心功能实现#

1. Python Sidecar 自动引导#

问题:用户不一定安装了 Python,也不知道如何配置环境。

解决方案:使用 uv 自动安装 Python 和依赖。

实现src-tauri/src/sidecar.rs):

pub async fn bootstrap_and_start(app: &AppHandle) -> Result<SidecarHandle, SidecarError> {
let src_python = src_python_dir();
// 自动运行 uv sync,安装 Python 3.11 + 依赖
run_uv_sync(app, &src_python).await?;
// 启动 Python sidecar
start_sidecar(app, &src_python, model_path.as_deref()).await
}

效果

  • 首次运行时,自动下载 Python 3.11
  • 自动安装 llama-cpp-python、aiohttp 等依赖
  • 支持镜像源配置(清华、阿里云、豆瓣、PyPI)
  • 用户完全无感知

2. 懒加载翻译模型#

问题:VRCT 启动时立即加载模型,导致启动卡顿。

解决方案:首次翻译时才加载模型。

实现src-python/src/vrc_gotrans/translator/local.py):

class LocalTranslator:
def __init__(self, model_path: str, ...):
self._llm: Llama | None = None # 懒加载
self._lock = threading.Lock()
def _call_sync(self, prompt: str) -> str:
with self._lock:
if self._llm is None:
# 首次翻译时才加载模型
self._llm = Llama(model_path=..., n_ctx=1024, ...)
result = self._llm(prompt, **_GEN_KW)
return result["choices"][0]["text"]

优势

  • 启动时不加载模型,启动速度快
  • 首次翻译时加载,用户有心理预期
  • 线程安全(threading.Lock
  • 推理在线程池执行,不阻塞 asyncio 事件循环

3. VRChat OSC 集成#

问题:如何将翻译结果发送到 VRChat 聊天框?

解决方案:通过 OSC(Open Sound Control)协议。

实现src-tauri/src/osc.rs):

pub fn send_chatbox_message(&self, message: &str, send_immediately: bool) -> Result<(), String> {
let msg = OscMessage {
addr: "/chatbox/input".to_string(),
args: vec![
OscType::String(truncated.to_string()),
OscType::Bool(send_immediately),
],
};
let packet = OscPacket::Message(msg);
let buf = rosc::encoder::encode(&packet)?;
self.socket.send_to(&buf, self.target_addr)?;
Ok(())
}

支持的 OSC 地址

  • /chatbox/input - 发送消息到聊天框(最多 144 字符)
  • /chatbox/typing - 显示/隐藏打字指示器

效果

  • 翻译结果自动显示在 VRChat 聊天框
  • 延迟低于 10ms(本地 UDP)
  • 支持打字指示器

4. 首次启动向导#

问题:新用户不知道如何配置。

解决方案:首次启动时引导用户配置。

实现src/components/FirstRunWizard.tsx):

5 步引导流程

  1. 欢迎页面:介绍 VRC-GoTrans
  2. 翻译引擎选择:在线 API vs 本地模型
  3. 模型下载/定位:自动下载或手动选择模型文件
  4. OSC 配置:默认端口 9000,可自定义
  5. 完成页面:配置完成,开始使用

配置持久化到 ~/.vrc-gotrans/config.json

5. 类型安全的多语言支持#

问题:多语言翻译容易漏 key 或写错。

解决方案:TypeScript 类型约束。

实现src/locales/):

// zh-Hans.ts 定义类型
export const zhHans = {
app: { title: "VRC-GoTrans" },
translate: { input: "输入文本" },
// ...
};
export type TranslationShape = typeof zhHans;
// 其他语言必须匹配此类型
const en: TranslationShape = {
app: { title: "VRC-GoTrans" },
translate: { input: "Enter text" },
// 缺 key 会编译失败
};

效果

  • 编译时检查,缺 key 会报错
  • 支持 4 种语言:简体中文、English、日本語、한국어
  • 类型安全,减少运行时错误

开发中的坑#

1. llama-cpp-python 编译问题#

问题:llama-cpp-python 依赖 C++ 编译器,Windows 上编译困难。

解决方案:使用预编译的 wheel 包。

[tool.uv]
find-links = [
"https://github.com/abetlen/llama-cpp-python/releases/download/v0.3.33/"
]

2. Sidecar 握手超时#

问题:Python sidecar 启动慢,Rust 端等待超时。

解决方案:握手机制 + 健康检查。

// 等待 sidecar 启动
for _ in 0..30 {
if health_check().await.is_ok() {
return Ok(handle);
}
tokio::time::sleep(Duration::from_millis(100)).await;
}

3. OSC 消息长度限制#

问题:VRChat 聊天框最多 144 字符。

解决方案:自动截断。

let truncated = if message.len() > 144 {
&message[..144]
} else {
message
};

4. 模型推理阻塞事件循环#

问题:llama-cpp-python 推理是同步的,会阻塞 asyncio。

解决方案:在线程池执行。

async def translate(self, text: str, ...) -> str:
loop = asyncio.get_running_loop()
return await loop.run_in_executor(self._executor, self._call_sync, prompt)

使用体验#

安装#

  1. Releases 下载安装包
  2. 运行安装程序
  3. 首次启动会自动安装 Python 环境(约 1-2 分钟)

首次配置#

  1. 选择界面语言(简体中文 / English / 日本語 / 한국어)
  2. 选择翻译引擎(推荐:本地模型)
  3. 下载/定位 HY-MT 模型文件(约 1.1GB)
  4. 配置 OSC(默认端口 9000)
  5. 完成设置

日常使用#

  1. 启动 VRChat 并启用 OSC(Settings → OSC → Enable OSC)
  2. 启动 VRC-GoTrans
  3. 点击”开始”按钮启动翻译会话
  4. 输入要翻译的文本,按 Enter 发送
  5. 翻译结果自动显示在 VRChat 聊天框

性能指标#

  • 模型加载时间:~1.5 秒(首次)
  • 翻译延迟:0.3-0.5 秒/句(CPU,Q4_K_M 量化)
  • 内存占用:~1.5-2GB(模型加载后)
  • 磁盘空间:~2GB(含模型)
  • OSC 延迟:<10ms(本地 UDP)

与 VRCT 的对比#

特性VRC-GoTransVRCT
启动速度快(懒加载)慢(立即加载模型)
配置难度低(向导引导)高(手动配置)
网络依赖低(镜像源支持)高(Hugging Face)
UI 现代化React 19PyQt
语音识别开发中✅ 支持
跨平台Windows(macOS/Linux 开发中)Windows

未来计划#

短期#

  • ✅ OSC 集成(已完成)
  • 🚧 faster-whisper 语音识别
  • 📋 麦克风/扬声器设备选择

中期#

  • macOS/Linux 支持
  • GPU 加速(CUDA)
  • 批量消息队列

长期#

  • 实时语音翻译
  • 自定义翻译模型训练
  • 云端配置同步

总结#

重写 VRC-GoTrans 的初衷很简单:VRCT 的网络问题和配置繁琐让人抓狂。

这次重写学到的:

  • Tauri 的 Sidecar 模式很适合集成 Python AI 应用
  • 懒加载模型可以显著改善启动体验
  • 首次启动向导可以大幅降低使用门槛
  • 类型安全(TypeScript + Rust)可以减少很多运行时错误

这个项目适合谁?

  • VRChat 玩家,想用翻译但嫌 VRCT 配置麻烦
  • 开发者,想学习 Tauri + React + Python 的跨语言集成
  • 对 AI 桌面应用开发感兴趣的人

项目地址: https://github.com/ChuranNeko/VRC-GoTrans

如果你也在玩 VRChat,可以试试这个工具。有问题欢迎提 Issue,也欢迎加 QQ 群交流:初然的猫猫头窝


谢谢阅读。

参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
重写 VRChat 翻译助手:当 VRCT 的网络问题让人抓狂
https://blog.crneko.top/posts/vrc-gotrans-rewrite/
作者
初然
发布于
2026-07-10
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
初然
一切都是因为好奇,所以想要知道那些未曾知晓的事物。
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
13
分类
8
标签
31
总字数
33,047
运行时长
0
最后活动
0 天前
累计访问
加载中...
累计访客
加载中...

目录