Skip to content

Latest commit

 

History

History
136 lines (101 loc) · 8.16 KB

File metadata and controls

136 lines (101 loc) · 8.16 KB

技术速查

写代码时直接抄这页。实测细节的完整出处:00-original-plan.md 第 5 节。App 架构图(谁管什么)见 03-android-primer.md 第 9 节。

本机构建环境(2026-07-08 探测)

SDK 路径 C:\Users\XYQ\AppData\Local\Android\Sdk(platforms: android-35;build-tools: 34.0.0 / 35.0.0)
adb C:\Users\XYQ\AppData\Local\Android\Sdk\platform-tools\adb.exe(不在 PATH,用全路径)
JDK 系统 PATH 有 Microsoft JDK 17;Android Studio 自带 JBR 21
Gradle 无系统安装,项目自带发行版在 D:\vtuber-live-translate\tools\gradle-8.9\
版本组合 Gradle 8.9 + AGP 8.7.3 + Kotlin 2.0.21,compileSdk 35 / minSdk 29
命令行构建 android/ 目录下运行 ../tools/gradle-8.9/bin/gradle assembleDebug(生成 wrapper 后用 ./gradlew assembleDebug
APK 产物 android/app/build/outputs/apk/debug/app-debug.apk

Gemini Live Translate 接口

WebSocket 入口:

wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key=<API_KEY>

模型:gemini-3.5-live-translate-preview

setup 消息(字段位置是坑,照抄这个结构)

{
  "setup": {
    "model": "models/gemini-3.5-live-translate-preview",
    "generationConfig": {
      "responseModalities": ["AUDIO"],
      "translationConfig": {
        "targetLanguageCode": "zh",
        "echoTargetLanguage": true
      }
    },
    "inputAudioTranscription": {},
    "outputAudioTranscription": {},
    "systemInstruction": {
      "parts": [{"text": "<当前会话的组合提示词>"}]
    }
  }
}

已实测的报错规律:

  • translationConfig 必须在 generationConfig 里;放到 setup 顶层 → close 1007
  • inputAudioTranscription / outputAudioTranscription 必须在 setup 顶层;放进 generationConfig → close 1007
  • systemInstruction 放 setup 顶层,可用,对专名识别有实测改善

官方文档核对(2026-07-10,live-translate 专页 + 模型页

  • 云端可调参数就这么多translationConfig 只有 targetLanguageCode(BCP-47,默认 en)和 echoTargetLanguage(默认 false;true=输入已是目标语言时照常复述输出,false=保持沉默)两个字段,外加 inputAudioTranscription / outputAudioTranscription 两个转写开关。没有 VAD、voice、temperature 等常规 Live API 配置
  • 官方示例把转写开关放 generationConfig 里,与我们实测的"必须放 setup 顶层"不一致;我们的结构实测可用,不改。若某天升级报 1007,先试官方结构
  • 官方声称翻译模式"不支持 tools 和 instructions",但 systemInstruction 实测可用且对场景约束、专名和翻译风格有改善——依赖的是未文档化行为,模型更新后可能失效,届时需要评估 transcript 后处理等替代方案
  • 语言代码表:中文官方写法是 zh-Hans(简体)/ zh-Hant(繁体);我们用的 zh 实测可用
  • 模型能力表:函数调用 / Search grounding / 结构化输出 / 思考均不支持;输入仅音频(文本输入不支持);翻译语音输出为 24kHz PCM(本 App 丢弃不播)
  • token 限制:输入 131,072 / 输出 65,536(直播场景配合 8 分半轮换用不满)

音频推送

  • 格式:PCM16 little-endian / mono / 16kHz,每 100ms 一块(= 3200 字节)
  • 消息格式:
{"realtimeInput": {"audio": {"data": "<base64 pcm>", "mimeType": "audio/pcm;rate=16000"}}}
  • 有限音频测试结束时发:{"realtimeInput":{"audioStreamEnd":true}}(直播场景用不到)

连接寿命与重连

  • 实测单连接约 590 秒后服务端发 GoAway 并关闭(close 1008)
  • 默认约 505 秒主动轮换(高级设置可调 120–580 秒):到点后在 scheduler 单线程里 connect() 新连接,再关闭旧连接;不是双连接无缝切换。新连接 ready 前音频会进发送队列。
  • 发送队列最多约 200 块 / 20 秒(100ms 一块),满了丢最旧;chunksSent 表示已交给 OkHttp 本地发送,不等于上游已消费。
  • 异常断线:立即重连,并把最近约 1 秒(10 块)已发送音频前置到队列;主动轮换本身不做这段 overlap。
  • 静音时长时间无返回是正常行为(Windows 版 README 也确认:无声就不发数据),不要误判成断线。运行页「聆听中…」只按译文更新时间派生,不能当断线判定。

安卓关键 API

能力 API 备注
内录 MediaProjection + AudioPlaybackCaptureConfiguration + AudioRecord API 29+;每次会话需用户授权;旁路复制,YouTube 原声照常播,无需回放原声
悬浮窗 SYSTEM_ALERT_WINDOW + WindowManager 窗口类型 TYPE_APPLICATION_OVERLAY
后台常驻 ForegroundService Manifest 声明 `mediaProjection
网络 OkHttp WebSocket Base URL 做成可配置
配置存储 SharedPreferences + 加密存储(Keystore) API key 不落明文;自用版足够简单可靠

可被捕获的音频 usage:USAGE_MEDIA / USAGE_GAME / USAGE_UNKNOWN。YouTube 属于媒体播放。

内录能力已在本机验证(2026-07-08):腾讯会议共享屏幕可带系统声音(第三方 App 走同一套 API),系统录屏支持内录。

网络

  • App 需能访问 generativelanguage.googleapis.com:手机代理软件开分应用代理,把本 App 勾上
  • 备选方案:VPS 上用 nginx 做 wss 纯转发(只是网络管道,不是"后端"),App 的 Base URL 指向 VPS
  • 注意:VPS 上现有的 aistudio-to-api 不支持 Live WebSocket(已实测探测过),别绕这条路

参考项目对照(要做什么,抄哪里)

要做的事 抄哪里
WS 客户端(setup / 收发循环 / 重连) gemini-live-translate 的 gemini_client.py,Python→Kotlin 对照移植
PCM 重采样 + 分块 同项目 pcm_processor.py
自定义 API Base URL 的设置设计 同项目 settings.py / settings_window.py
悬浮窗交互(拖动/缩放/收起小圆点) Gemive 的 content/overlay 部分
结构化历史与 Markdown 文本 App 私有历史为唯一自动存储;详情页按需复制,不自动写入公共 Downloads
多 key 逗号分隔、会话开始随机选 Gemive 的设置页

仓库地址:

Prompt 组合

当前由 PromptBuilder 在会话启动前一次性生成 systemInstruction

  1. 简短且中性的隐藏翻译规则;
  2. 语言方向;
  3. 只描述输入来源差异的同传或视频模式规则;
  4. SceneLibraryStore 解析出的可编辑场景提示词;
  5. 仅本场使用的临时上下文。

DefaultSceneCatalog 只在首次使用或用户主动恢复时提供初始化模板,不参与新会话的运行时场景解析。场景库是唯一长期配置层;TranslationPlan 草稿只保存语言方向与场景 ID。同传和视频分别读取自己的场景库、默认场景和草稿。会话启动时冻结完整 Prompt 与场景名称,本场上下文不写入场景库。术语库与旧「方案库」已从当前提示词链路移除。

字幕与历史

  • SubtitleStabilizer:主线程处理碎片重叠合并、句末切句、连续复读去重;一个服务端碎片若含多句,确认回调保留全部句子,不只最后一句。
  • 默认 idle 转正约 2500ms、当前行约 42 字上限(高级设置可调);idle 只影响「转正写历史」,当前行仍即时渲染。
  • 运行态确认行上限 80StatusBusCaptureService.sessionLines 一致)。
  • TranscriptLogger 把确认段写入 App 私有 history_v2 JSON;写盘走单线程后台队列,避免阻塞悬浮窗与主界面。