杰理 SDK 文档中心
首页
首页
  • 快速开始

    • 环境要求与权限配置
    • 集成SDK依赖
    • 运行示例应用
  • 核心架构与协议

    • RCSP协议与数据通道
    • 蓝牙连接与设备管理
    • TWS双耳功能
    • 基础功能接口与自定义命令
  • 设备功能控制

    • 设备音乐控制与ID3信息
    • 文件浏览与传输
    • FM收音与发射
    • 灯光控制
    • 闹钟与时间管理
    • 查找设备与防丢
    • ANC与噪声处理
    • 按键功能设置
    • 彩屏仓控制
    • AI翻译
  • 音效与音频处理

    • 均衡器音效调节
    • 录音与语音控制
    • Line-in、SPDIF与声卡功能
    • 音频编解码库
  • 扩展功能库

    • OTA固件升级
    • 数据加密与解密
    • 图片与动图格式转换
  • 示例应用 btsmart

    • 应用架构与界面导航
    • 设备功能适配与数据层
    • 设备配置JSON与资源文件
  • 参考与版本

    • 错误码参考
    • 版本历史与更新日志
    • 开发文档中心导航

AI翻译

AI翻译(AI Translation)是杰理蓝牙 SDK 应用(btsmart)中基于蓝牙设备 + 云端大模型实现的双向语音/文本翻译能力:设备端录音采集语音,经蓝牙链路回传手机,由 AITranslationImpl 转发至豆包(Doubao)云端翻译服务,再将译文合成音频回传给设备播放,同时将翻译过程持久化到本地 Room 数据库。

Purpose and Scope

本文档介绍 btsmart 中 AI 翻译功能的完整实现链路,涵盖:

  • 翻译状态机(TranslateState)与状态流转
  • 逻辑中枢 TranslateViewModel 的操作码、依赖与回调
  • 设备端翻译能力封装(TranslationImpl、RecordOpImpl、TranslationMode、AudioData)
  • 云端 AI 翻译代理(AITranslationImpl 与豆包 doubao/translate 包:TranslateParam、TranslateAudioParam、TranslateTextParam、请求模型与鉴权)
  • 翻译记录与会话的本地持久化(TranslationRepository)
  • 时间/时长格式化与音频后缀等工具(TranslateUtil)

与翻译功能平级的其他设备功能(如录音、降噪、EQ 等)不在本文档范围内;蓝牙协议层 TranslationImpl 的底层指令细节亦只做概要说明,详见 SDK 层文档。UI 交互细节(TranslateFragment)仅作入口说明。

Overview

AI 翻译功能解决的核心问题是:在耳机/音箱等低算力设备上实现多语言实时对话翻译。设备本身不具备语音识别与机器翻译能力,因此采用"端-云协同"架构:

  1. 采集:设备麦克风录音(RecordOpImpl 触发设备录音,OP_DEVICE_RECORD);
  2. 传输:录音音频数据(AudioData)经蓝牙 RCSP 通道回传到手机;
  3. 云端翻译:AITranslationImpl 将音频/文本以 TranslateParam(音频流方式 WAY_AUDIO_STREAM 或文本方式 WAY_TEXT)封装,调用豆包翻译服务;
  4. 回放:译文文本/音频经蓝牙通道下发设备播放;
  5. 沉淀:翻译记录(TranslationRecord)与翻译会话(TranslationSession)写入 Room 数据库,支持历史回看。

翻译会话有明确的空闲(STATE_IDLE)/工作中(STATE_WORKING)/暂停(STATE_PAUSE)三种状态,由 TranslateState 枚举表示,TranslateViewModel 通过 MSG_COUNT_WORK_TIME 消息在 Handler 中累计工作时长。

关键概念

概念说明
TranslationModeSDK 层翻译模式(如单向/双向等),来自 com.jieli.bluetooth.bean.translation
AudioDataSDK 层音频数据封装,携带录音 PCM/OPUS 等编码数据
TranslationResultSDK 层翻译结果(译文文本等)
TranslateState应用层翻译状态机:STATE_IDLE / STATE_WORKING / STATE_PAUSE
AITranslationImpl应用层 AI 云翻译代理,负责调用豆包服务并桥接设备回调
TranslateParam云端翻译请求参数基类,派生 TranslateAudioParam(音频流)与 TranslateTextParam(文本)
RoleInfo角色信息(说话人/语言角色),参与云端请求与记录
TranslationRecord / TranslationSessionRoom 实体,分别表示单条翻译记录与一次翻译会话

Architecture

flowchart TD
    subgraph sg_UI["UI 层 (ui/translate)"]
        Fragment["TranslateFragment"]
        ViewModel["TranslateViewModel<br/>(extends BtBasicVM)"]
    end

    subgraph sg_Device["设备能力封装 (tool)"]
        AITranslation["AITranslationImpl<br/>AI 云翻译代理"]
        TranslationImpl["TranslationImpl<br/>(SDK RCSP 翻译)"]
        RecordOp["RecordOpImpl<br/>设备录音"]
        ConfigureKit["ConfigureKit<br/>配置管理"]
    end

    subgraph sg_Cloud["豆包云端 (tool/ai/doubao)"]
        TranslateParam["TranslateParam<br/>WAY_AUDIO_STREAM / WAY_TEXT"]
        AudioParam["TranslateAudioParam"]
        TextParam["TranslateTextParam"]
        Requests["Request 模型<br/>TranslateDataRequest /<br/>TranslateTextRequest /<br/>StopTranslateRequest"]
        Auth["SignSpeechTranslate<br/>签名鉴权"]
    end

    subgraph sg_Data["数据层"]
        Repository["TranslationRepository<br/>(Room)"]
        DB[("Room Database<br/>TranslationRecord / Session")]
        Util["TranslateUtil<br/>时间/时长/音频后缀"]
    end

    Fragment --> ViewModel
    ViewModel --> AITranslation
    ViewModel --> TranslationImpl
    ViewModel --> RecordOp
    ViewModel --> ConfigureKit
    ViewModel --> Repository
    AITranslation --> TranslateParam
    TranslateParam --> AudioParam
    TranslateParam --> TextParam
    AudioParam --> Requests
    TextParam --> Requests
    Requests --> Auth
    Repository --> DB
    ViewModel --> Util
    TranslationImpl -->|"Bluetooth RCSP"| Device["蓝牙设备<br/>录音/播放"]
    RecordOp -->|"录音指令"| Device

架构说明:TranslateViewModel 是应用层的逻辑中枢,持有 AITranslationImpl(云端)、TranslationImpl(设备端翻译能力)、RecordOpImpl(录音)、TranslationRepository(持久化)与 ConfigureKit(配置)五个依赖。云端请求参数以 TranslateParam 抽象类为基类,按翻译方式(音频流/文本)分化为 TranslateAudioParam 与 TranslateTextParam,最终经豆包请求模型与签名鉴权发往云端。TranslateUtil 为各层提供时间格式化与音频后缀等公共工具。

翻译状态机

翻译会话的运行时状态由 com.jieli.btsmart.tool.translate.TranslateState 枚举统一表达:

public enum TranslateState {
    STATE_IDLE(0),
    STATE_WORKING(1),
    STATE_PAUSE(2);

    private final int value;

    TranslateState(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Source: TranslateState.java

  • STATE_IDLE(0):空闲态,无翻译会话或会话已结束,可安全进入翻译模式;
  • STATE_WORKING(1):工作态,设备正在录音、音频正在传输或云端翻译进行中;
  • STATE_PAUSE(2):暂停态,会话保留但暂停采集/翻译,通常由用户手动暂停或设备录音中断触发。
stateDiagram-v2
    [*] --> STATE_IDLE
    STATE_IDLE --> STATE_WORKING: 进入翻译模式 (OP_ENTER_MODE) / 开始翻译 (OP_AI_TRANSLATION)
    STATE_WORKING --> STATE_PAUSE: 暂停翻译 (OP_AI_TRANSLATION)
    STATE_PAUSE --> STATE_WORKING: 继续翻译
    STATE_WORKING --> STATE_IDLE: 退出翻译模式 (OP_EXIT_MODE) / 会话结束
    STATE_PAUSE --> STATE_IDLE: 退出翻译模式 (OP_EXIT_MODE)

设计意图:引入独立状态枚举而非布尔标志,是为了让 UI、设备回调与云端回调三方对会话生命周期有一致的可观察视图,避免"正在录音但云端已完成"这类竞态误判;value 字段可序列化到设备端(如同步到协议层)以便双端状态对齐。

逻辑中枢:TranslateViewModel

TranslateViewModel(位于 ui/translate 包,继承 BtBasicVM)是整个 AI 翻译功能的编排者。它定义了与设备交互的操作码常量:

/** 进入翻译模式操作 */
public static final int OP_ENTER_MODE = 0x20;
/** 退出翻译模式操作 */
public static final int OP_EXIT_MODE = 0x21;
/** 调节音量 */
public static final int OP_ADJUST_VOLUME = 0x22;
/** 设备录音 */
public static final int OP_DEVICE_RECORD = 0x23;
/** AI翻译 */
public static final int OP_AI_TRANSLATION = 0x24;
/** 同步翻译模式 */
public static final int OP_SYNC_TRANSLATION_MODE = 0x25;

/** 工作时间计数消息 */
private static final int MSG_COUNT_WORK_TIME = 0x3211;

private static final int INIT_SESSION_ID = -1;

Source: TranslateViewModel.java

这些常量把"翻译功能"抽象为对设备的一组可下发操作:进入/退出翻译模式、调节音量、触发设备录音、启动/停止 AI 翻译、同步翻译模式。MSG_COUNT_WORK_TIME 通过 Handler 定时消息累计工作时长,INIT_SESSION_ID = -1 表示会话尚未建立。

ViewModel 持有的核心依赖(构造时注入):

/** 操作设备 */
@NonNull
private final BluetoothDevice mDevice;
/** AI云翻译代理实现 */
private final AITranslationImpl mAITranslation;
/** 翻译功能实现 */
private final TranslationImpl mTranslation;
/** 翻译数据库操作 */
private final TranslationRepository mRepository;
/** 配置管理工具 */
private final ConfigureKit mConfigureKit;
/** 录音 */
private RecordOpImpl mRecordOp;

Source: TranslateViewModel.java

对外暴露的 LiveData 回调

LiveData类型含义
initMLDMutableLiveData<Integer>初始化结果(错误码,0 为成功)
muteStateMLDMutableLiveData<Boolean>静音状态
modeChangeMLDMutableLiveData<TranslationMode>翻译模式切换
workTimeMLDMutableLiveData<Integer>本次翻译工作时长(秒)

UI(TranslateFragment)观察这些 LiveData 驱动界面刷新,而 ViewModel 通过 TranslationStateCallback、TranslationCallback、OnRecordStateCallback 等回调接收设备/云端事件。这种"LiveData 出、回调进"的模型保证所有状态变更都在主线程安全发布,天然适配 MVVM。

设备端能力:TranslationImpl 与录音

  • TranslationImpl(SDK com.jieli.bluetooth.impl.rcsp.translation):封装蓝牙 RCSP 协议层的翻译功能,负责下发翻译模式、接收设备返回的 AudioData(录音音频)与 TranslationResult(译文),并通过 TranslationCallback 上报。
  • RecordOpImpl(SDK com.jieli.bluetooth.impl.rcsp.record):负责设备录音控制,通过 OnRecordStateCallback 上报 RecordState,录音参数由 RecordParam 描述(采样率、编码等)。
  • ConfigureKit(应用层 tool.configure):管理设备配置项,用于在进入/退出翻译模式时保存与恢复设备状态(如音量、降噪等),避免翻译会话破坏原有设备配置。

翻译模式下数据流为设备 → 手机(录音上行)与手机 → 设备(译文/音频下行)双向交替:设备端采集的音频以 AudioData 回传,TranslateViewModel 将其交给 AITranslationImpl 送云端;云端译文回传后经 TranslationImpl 下发设备播放。

云端翻译:AITranslationImpl 与豆包请求模型

请求参数基类 TranslateParam

豆包翻译请求参数以抽象类 TranslateParam 为基类,按"翻译方式"区分两条路径:

/**
 * 翻译音频流方式
 */
public static final int WAY_AUDIO_STREAM = 1;
/**
 * 翻译文本方式
 */
public static final int WAY_TEXT = 2;

@NonNull
private final String mac;
@NonNull
private final RoleInfo roleInfo;
private final boolean isIdAutoInc;
private int recordId;
private TranslationRecord translationRecord;
private int saveRecordId = -1;

public TranslateParam(@NonNull String mac, @NonNull RoleInfo roleInfo, boolean isIdAutoInc, int recordId) {
    this.mac = mac;
    this.roleInfo = roleInfo;
    this.isIdAutoInc = isIdAutoInc;
    if (recordId < 0) {
        this.recordId = new Random().nextInt(256);
    } else {
        this.recordId = recordId;
    }
}

Source: TranslateParam.java

设计要点:

  • 双路径:WAY_AUDIO_STREAM(1)走音频流实时翻译,WAY_TEXT(2)走纯文本翻译,分别由 TranslateAudioParam 与 TranslateTextParam 实现,子类必须实现 getTranslationWay();
  • recordId 策略:调用方未指定记录 ID(recordId < 0)时随机生成 [0, 256) 的 ID,用于云端会话关联;isIdAutoInc 控制记录 ID 是否自增,saveRecordId 追踪已持久化的记录,避免重复入库;
  • 上下文绑定:每次请求都携带设备 mac 与 RoleInfo(角色/语言信息),使云端返回结果能与具体设备、具体说话角色正确对应。

豆包请求/响应模型

tool/ai/doubao/translate 包构成完整的云端接入面:

文件职责
model/request/TranslateConfigRequest翻译配置请求(语言对、采样率等)
model/request/TranslateDataRequest音频流数据请求(增量音频帧)
model/request/TranslateTextRequest文本翻译请求
model/request/StopTranslateRequest停止翻译请求
model/TranslateAudioParam音频流方式参数(继承 TranslateParam)
model/TranslateTextParam文本方式参数(继承 TranslateParam)
auth/SignSpeechTranslate云端签名鉴权,为请求生成合法凭证
OnTranslateResultCallback翻译结果回调接口(成功/失败/中间结果)

云端接入采用"配置 → 数据流 → 停止"的会话式协议:先以 TranslateConfigRequest 建立会话,再通过多个 TranslateDataRequest 流式上传音频/文本,最后以 StopTranslateRequest 结束会话。SignSpeechTranslate 保证请求经过签名校验,防止未授权调用。

数据模型与持久化

翻译会话与记录的实体位于 data/model/translation(TranslationRecord、TranslationSession、RoleInfo)与 SDK 层(AudioData、TranslationResult、TranslationMode),通过 TranslationRepository(tool/room/repository)访问 Room 数据库:

  • TranslationSession:一次翻译会话(开始时间、模式、时长、状态);
  • TranslationRecord:会话中的单条翻译记录(原文/译文、角色、时间戳、关联会话 ID);
  • RoleInfo:说话角色信息,随 TranslateParam 上行,用于区分说话人语言。
erDiagram
    TranslationSession ||--o{ TranslationRecord : "包含"
    TranslationSession {
        int sessionId PK "INIT_SESSION_ID = -1 表示未建立"
        string mode "TranslationMode"
        datetime startTime
        int duration "秒"
        int state "TranslateState"
    }
    TranslationRecord {
        int recordId PK "云端关联 ID"
        int sessionId FK
        string originalText
        string translatedText
        string role "RoleInfo"
        datetime createTime
    }
    TranslationRecord }o--|| RoleInfo : "说话角色"
    RoleInfo {
        string language
        string speaker
    }

TranslateViewModel 借助 saveRecordId 与 INIT_SESSION_ID 的配合,确保:会话未建立(ID 为 -1)时不写记录;同一条云端记录不因回调重入而重复入库。

核心流程:一次完整的 AI 翻译会话

从用户点击"开始翻译"到译文回放,完整时序如下:

sequenceDiagram
    participant U as 用户/TranslateFragment
    participant VM as TranslateViewModel
    participant R as RecordOpImpl
    participant D as 蓝牙设备
    participant T as TranslationImpl
    participant AI as AITranslationImpl
    participant Cloud as 豆包云端 (TranslateParam/签名)

    U->>VM: 进入翻译模式 (OP_ENTER_MODE)
    VM->>T: 下发翻译模式 TranslationMode
    T-->>VM: TranslationCallback 确认
    VM->>VM: 状态 -> STATE_WORKING<br/>启动 MSG_COUNT_WORK_TIME 计时
    VM->>R: 启动设备录音 (OP_DEVICE_RECORD)
    R->>D: 录音指令
    D-->>T: 回传 AudioData (音频流)
    T-->>VM: TranslationCallback(AudioData)
    VM->>AI: 请求云端翻译 (TranslateAudioParam)
    AI->>Cloud: TranslateConfigRequest + TranslateDataRequest<br/>(SignSpeechTranslate 鉴权)
    Cloud-->>AI: 译文结果
    AI-->>VM: OnTranslateResultCallback / TranslationResult
    VM->>Repository: 保存 TranslationRecord
    VM->>T: 下发译文 (文本/音频) 到设备
    T->>D: 设备播放译文
    U->>VM: 停止翻译 (OP_AI_TRANSLATION)
    VM->>Cloud: StopTranslateRequest
    VM->>VM: 状态 -> STATE_IDLE<br/>停止计时、保存会话

流程要点:

  1. 模式先行:必须先通过 OP_ENTER_MODE + TranslationImpl 让设备进入翻译模式,之后录音与音频回传才合法;
  2. 状态驱动计时:STATE_WORKING 期间 MSG_COUNT_WORK_TIME 每单位时间递增并发布到 workTimeMLD,暂停(STATE_PAUSE)时计时挂起,避免"暂停仍计费/计时"的体验问题;
  3. 音频即来即译:设备回传的 AudioData 不落盘,直接以 TranslateAudioParam(WAY_AUDIO_STREAM)流入云端,保证低延迟;
  4. 结果双向落地:译文既下发设备播放,也写入 TranslationRepository,兼顾实时性与可追溯性;
  5. 优雅收尾:停止时先发 StopTranslateRequest 结束云端会话,再退出翻译模式、持久化会话并复位状态。

使用示例

1. 状态枚举的使用

public enum TranslateState {
    STATE_IDLE(0),
    STATE_WORKING(1),
    STATE_PAUSE(2);

    private final int value;

    TranslateState(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Source: TranslateState.java

2. 时间格式化与音频后缀工具

TranslateUtil 集中了翻译功能的时间与文件命名约定:记录文件名使用 yyyyMMddHHmmss,会话展示使用 yyyy-MM-dd HH:mm,音频文件按 PCM / WAV / OPUS / JLA 后缀区分编码:

public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss", Locale.ENGLISH);
public static final SimpleDateFormat RECORD_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
public static final SimpleDateFormat YEAR_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
public static final SimpleDateFormat MONTH_DATE_FORMAT = new SimpleDateFormat("yyyy-MM", Locale.ENGLISH);

public static final String PCM_SUFFIX = ".pcm";
public static final String WAV_SUFFIX = ".wav";
public static final String OPUS_SUFFIX = ".opus";
public static final String JLA_SUFFIX = ".jla";

Source: TranslateUtil.java

时长展示工具 formatDuration(HH:mm:ss)与 formatDurationToHm(mm:ss)分别用于会话总时长与录音片段时长的 UI 展示;isSameDay / isSameMonth 用于把历史记录按天/月分组,getDayStartTime / getDayEndTime 支撑按日查询。

3. 构造云端翻译参数

public TranslateParam(@NonNull String mac, @NonNull RoleInfo roleInfo, boolean isIdAutoInc, int recordId) {
    this.mac = mac;
    this.roleInfo = roleInfo;
    this.isIdAutoInc = isIdAutoInc;
    if (recordId < 0) {
        this.recordId = new Random().nextInt(256);
    } else {
        this.recordId = recordId;
    }
}

Source: TranslateParam.java

实际使用时由 TranslateAudioParam 或 TranslateTextParam 提供具体的 getTranslationWay() 实现,AITranslationImpl 依据该方式选择音频流或文本请求通道。

4. ViewModel 操作码定义

public static final int OP_ENTER_MODE = 0x20;
public static final int OP_EXIT_MODE = 0x21;
public static final int OP_ADJUST_VOLUME = 0x22;
public static final int OP_DEVICE_RECORD = 0x23;
public static final int OP_AI_TRANSLATION = 0x24;
public static final int OP_SYNC_TRANSLATION_MODE = 0x25;

Source: TranslateViewModel.java

API Reference(核心接口)

TranslateState(枚举)

常量value语义
STATE_IDLE0空闲,无进行中的会话
STATE_WORKING1工作中,采集/翻译进行中
STATE_PAUSE2暂停,会话保留

方法:

  • getValue(): int — 返回状态值,用于序列化或与设备端同步。

TranslateParam(抽象类)

常量:

  • WAY_AUDIO_STREAM = 1 — 音频流翻译方式
  • WAY_TEXT = 2 — 文本翻译方式

构造器: TranslateParam(String mac, RoleInfo roleInfo, boolean isIdAutoInc, int recordId)

  • mac(必填):设备蓝牙地址,绑定云端会话与设备
  • roleInfo(必填):说话角色信息
  • isIdAutoInc:记录 ID 是否自增
  • recordId:指定记录 ID;小于 0 时随机生成 [0, 256)

方法:

  • getTranslationWay(): int(抽象)— 返回翻译方式
  • getMac(): String — 获取设备地址
  • getRoleInfo(): RoleInfo — 获取角色信息

TranslateViewModel(逻辑中枢)

操作码常量: OP_ENTER_MODE(0x20)、OP_EXIT_MODE(0x21)、OP_ADJUST_VOLUME(0x22)、OP_DEVICE_RECORD(0x23)、OP_AI_TRANSLATION(0x24)、OP_SYNC_TRANSLATION_MODE(0x25)。

对外 LiveData: initMLD: MutableLiveData<Integer>、muteStateMLD: MutableLiveData<Boolean>、modeChangeMLD: MutableLiveData<TranslationMode>、workTimeMLD: MutableLiveData<Integer>。

依赖(构造注入): BluetoothDevice mDevice、AITranslationImpl mAITranslation、TranslationImpl mTranslation、TranslationRepository mRepository、ConfigureKit mConfigureKit、RecordOpImpl mRecordOp。

回调接口(应用层 tool/translate): TranslationStateCallback — 翻译状态变化回调;SDK 层 TranslationCallback(音频/结果)、OnRecordStateCallback(录音状态)、OnRcspActionCallback(RCSP 操作结果)。

失败模式、边界情况与并发

蓝牙链路失败

  • 设备断开/未连接:TranslateViewModel 持有 BluetoothDevice,若会话中蓝牙断开,TranslationImpl 与 RecordOpImpl 的回调将中断。initMLD 以错误码(非 0)发布初始化失败,UI 据此提示并回到 STATE_IDLE。
  • 录音指令失败:OnRecordStateCallback 上报的 RecordState 非预期时(如设备忙),不应继续上行音频,需提示用户重试并保持会话可恢复。

云端失败与超时

  • 鉴权失败:SignSpeechTranslate 签名过期或非法时,豆包请求被拒绝;应重新生成签名后重试。
  • 会话中断:云端会话由 TranslateConfigRequest 建立、StopTranslateRequest 结束。若中途网络异常,云端会话可能悬挂,需要在重连后发送停止请求清理,否则新会话可能被旧会话干扰。
  • 重复回调:saveRecordId 机制防止同一条 TranslationRecord 因回调重入被多次写入;未保存(saveRecordId = -1)前才会写入数据库。

状态与并发

  • 状态竞态:STATE_IDLE / WORKING / PAUSE 由 ViewModel 主线程维护,所有回调(设备、云端、录音)都应在主线程转投 LiveData,避免多线程直接修改状态。MSG_COUNT_WORK_TIME 经主线程 Handler 派发,保证计时与状态切换有序。
  • recordId 冲突:recordId < 0 时随机生成 [0, 256),范围较小,极端情况下多设备/多会话可能碰撞;isIdAutoInc 为 true 时由调用方保证递增,规避冲突。
  • 会话未建立写库:INIT_SESSION_ID = -1 标记会话未建立,此时不落记录,避免"孤儿记录"污染历史列表。

边界情况

  • 翻译模式切换(OP_SYNC_TRANSLATION_MODE / modeChangeMLD)发生在会话中时,需先停止当前云端会话再切换 TranslationMode,否则新旧模式数据混流;
  • 暂停(STATE_PAUSE)期间设备可能仍在缓冲音频,恢复后需丢弃缓冲,保证译文顺序与真实语音一致;
  • 时长格式化边界:formatDuration 按 3600/60 取模,超长会话(>99 小时)仍可正确显示,但 UI 布局需预留宽度。

性能与运维考量

  • 低延迟优先:音频上行采用流式 TranslateDataRequest,边录边传,避免整段录音完成后再翻译带来的明显延迟;因此音频编码(OPUS/JLA 后缀暗示设备端支持压缩编码)直接影响带宽与延迟。
  • 计时开销:MSG_COUNT_WORK_TIME 为常驻 Handler 消息,仅在工作态运行;暂停/退出即移除消息,避免后台空转耗电。
  • 持久化策略:记录在翻译结果回调后立即写入 Room,会话在结束时写入;TranslationRepository 统一管理事务,批量回看(按天/月分组)依赖 TranslateUtil 的日期格式化方法生成索引键。
  • 依赖注入:AITranslationImpl、TranslationImpl、TranslationRepository、ConfigureKit 均通过构造注入到 ViewModel,便于单元测试替换为 mock 实现,也便于在 UI 层之外(如通知栏快捷入口)复用翻译会话。

扩展点

  • 新增云端服务商:AITranslationImpl 是 AI 翻译代理的抽象边界,豆包实现位于 tool/ai/doubao。接入新服务商可平行新增包(如 tool/ai/xxx/translate),实现同一组请求/回调约定即可,TranslateParam 的 WAY_AUDIO_STREAM / WAY_TEXT 双方式可复用。
  • 新增翻译方式:继承 TranslateParam 并实现 getTranslationWay(),同时在请求模型侧补充对应 Request 类即可扩展(如字幕式、离线词库式)。
  • 新增状态:在 TranslateState 枚举中追加状态值需同步更新 ViewModel 的状态迁移逻辑与 UI 状态展示,属于破坏性扩展。
  • 历史记录扩展:TranslationRecord / TranslationSession 为 Room 实体,可增加字段并通过 TranslationRepository 提供按角色、按语言过滤的新查询。

Related Links

  • TranslateState.java — 翻译状态枚举
  • TranslateViewModel.java — 翻译逻辑中枢
  • TranslateFragment.java — 翻译 UI 入口
  • TranslateParam.java — 云端翻译参数基类
  • TranslateUtil.java — 时间/时长/音频后缀工具
  • fragment_translate.xml — 翻译界面布局

相关平级功能页:录音、语音助手、设备配置(ConfigureKit)等请参见各自目录文档;蓝牙协议层 TranslationImpl / RecordOpImpl 的底层指令细节参见 SDK(com.jieli.bluetooth)文档。

Prev
彩屏仓控制