Files
story/docs/volc-native-subtitle-callback.md
T
Codex Local 0c2151ace9
ci / verify (push) Canceled after 0s
chore: checkpoint 第一版
2026-09-06 17:04:11 +08:00

7.0 KiB
Raw Blame History

火山字幕回调与重启记忆修复(2026-09-06)

设备实测更新(北京时间 10:20)

  • 已烧录并启动:COM6,ESP32-S3 MAC b4:3a:45:16:34:a8。最终固件 app 0x2ccf40,日志 build/native-subtitle-stable-{build,flash,device}.log,烧录哈希校验成功。NVS/Wi-Fi/绑定均保留;设备已联网待机。
  • 实际用户测试会话 157f866d-c364-4ae8-b169-50ca07024e5a:设备保存 3 条文字(其中 1 条为前置播放测试),双方实际对话保存成功,状态 COMPLETED,2 条 READY 摘要。设备约每 15 秒续期成功。之后创建的新会话已携带非空历史上下文;实际断电后口头回忆仍需用户反馈。
  • 真实火山回调已收到,但不能据此宣称按会话入库完成。 当前 low_load 回调只有 message/signature;解码后包含 productKey、deviceName、type、data,说话者 userId 为 input/output,没有 job_id、session_id 或 conversation_id。
  • 平台确实下发了带 conversation_id 的 URL 和 43 字符会话签名。固件 session.update 使用官方 AgentConfig.ServerMessageURLForRTS/ServerMessageSignatureForRTS 字段,但实测仍回调控制台静态 URL 和静态签名。额外测试 ServerMessageUrl/ServerMessageSignature 别名也未改变结果,该实验已从最终固件移除。
  • 不允许通过“设备最新会话”归属回调,否则旧会话延迟字幕可能写入重启后的新会话。保持 VOLC_SUBTITLE_PRIMARY=false。设备 turns:batch 仍为唯一正式记录来源。
  • callbacks 服务已更新为 0.78.3-rc.subtitle-memory3(api/worker 仍为 memory1),静态回调校验签名、设备身份及格式后返回 200,仅记无正文的验证日志,不存第二份文字。支持 Base64 JSON 和 subv 二进制封装。错误签名返回 401。公网验证前后 conversation_turn 行数不变,服务 ready。
  • 两个控制台配置值不变。其静态配置已能将字幕发送到平台,尚未完成独立的、可靠的会话归档。独立入库前必须解决会话身份传递,并按实测 input/output 更新和验证说话者映射;不能直接开启 primary。
  • 下一步供应商核对事项:低负载 session.update 是否支持动态回调 URL/签名?支持时需要的准确字段/生效时机是什么?不支持时能否在字幕中返回与 session.created.job_id 相同的编号?必要时评估平台管理每设备独立智能体及启动前冻结配置,但尚未创建、修改或批量克隆任何火山智能体。

以下为上一轮部署时的设计和验证记录;与本节冲突的“未烧录/未实测”描述已由本节更新取代。

已上线

  • 后端:0.78.3-rc.subtitle-memory1,服务器 /opt/data-terminal-cloud/current 指向同名 release。
  • POST /callbacks/v1/volcengine/subtitles 支持没有 Content-Type 的火山原生请求:外层 message/signature,message 解码后为 subv + 四字节大端长度 + subtitle JSON。
  • 当前 VOLC_SUBTITLE_PRIMARY=false:回调仅验证,不存第二份文字;设备原有 turns:batch 仍是正式记录来源。
  • 有效摘要现在包含已失败的会话,仍限定租户、用户、授权及 READY 状态。硬件结束、失败、超时按实际最大 turn sequence 安排摘要提取。
  • 无数据库迁移;未发布工作区其他改动。上一个 release 可用于回退。

火山控制台填写

  • ServerMessageUrl:https://121.41.46.238/callbacks/v1/volcengine/subtitles
  • ServerMessageSignature:使用本机被 Git 忽略的 .deploy-artifacts/volc-subtitle-console-settings.txt 中同名值。此文档不复制密钥。

这两项是基础配置,不能单靠基础 URL 推断归属会话。新固件上报 native_subtitle_callback=true 后,平台每次创建会话返回 session_config.subtitle_callback_url(带 conversation_id)和 subtitle_callback_signature(绑定该会话的 HMAC 值)。固件在 session.update 的 agent_config 中设置 ServerMessageURLForRTS 和 ServerMessageSignatureForRTS,同时设置 config.SubtitleConfig.SubtitleMode=1。火山按普通自定义 signature 原样回传它,平台进行比较。

已冻结的会话各自保留记录来源和说话者映射,不能用“设备当前最新会话”归档延迟回调。完成的分句全部保留,不能只保留 paragraph=true;稳定键按 userId、roundId、sequence 去重。没有供应商时间戳的回调只记录接收时间,不声称等于实际说话时间。网络乱序的分句按入库顺序分配平台序号。

尚未完成的设备验证

  • COM6 尚未出现,COM3 的 VID:PID 为 1D6B:011E,是另一台设备;COM4/5 为蓝牙。没有烧录新固件。
  • 最新编译:firmware/echoear-platform-agent/build/native-subtitle-build.log,app 大小 0x2ccf40;保留此前连续播放和眼睛动画修复,新增心跳续期及字幕配置。
  • 不能把平台发出的合成 HTTP 检查当成真实火山回调。当前 low_load 模式是否发送原生服务端字幕还需用设备验证;服务端状态回调仍关闭。
  • 先烧录 app 分区,保留 NVS/Wi-Fi/绑定。确认真实用户和助手字幕均能到达,并核对实际 userId 与冻结映射。未知或有歧义的说话者禁止入库。未验证前不得启用 primary。
  • primary 只作用于新会话;固件收到 subtitle_source=provider 后停止设备文字上传,平台也拒绝该会话的设备补传,防止双份记录。切换后还需验证重连、断电回忆、分句完整性及播放连续性。

验证结果

  • 单元测试:协议截断/错误长度、缺字段、错误签名、跨会话签名、无 Content-Type、说话者歧义等通过。
  • 独立临时 PostgreSQL(不是生产数据库):完成/失败/活跃会话的摘要选择、隔离其他用户、末尾提取版本与去重、字幕 probe 不入库、primary 入库与重复处理、未知说话者、冲突、撤回授权测试通过。日志 .deploy-artifacts/subtitle-db-test.log。
  • 公网 HTTPS(正常证书校验)协议检查:错误签名 401,正确签名 probe 200;原会话记录数测试前后均为 5,无测试聊天写入。
  • API、callbacks、worker 的 /health/ready 均 ready,线上版本接口返回新版本。

运维命令

当前上线额外使用 deploy/server/compose.subtitle.yaml 固定三个后端服务镜像和回调环境变量。后续重启这版必须保留该文件:

cd /opt/data-terminal-cloud/current
docker compose -p data-terminal-cloud --env-file deploy/server/.env \
  -f compose.yaml -f deploy/server/compose.override.yaml \
  -f deploy/server/compose.subtitle.yaml up -d --no-deps api callbacks worker

首次启动曾因 Windows 编译文件无 Linux 执行位被拒,已自动回退并修正为打包前 chmod 0755,随后成功上线。部署源码在本机 .deploy-artifacts/subtitle-release,包含明确文件清单;保留服务器基线的其他源码。

官方格式依据:实时字幕(对话记录),查阅于 2026-09-06。