在调实时字幕的排版和上屏节奏时,我们很快碰到了一个棘手的问题:很多改动单凭肉眼“看一会儿”,根本说不清到底变好了没有。
比如,让模型把刚识别出的半截词尽早推上屏幕,延迟确实低了,但紧接着一秒内它可能连续改写三次前文,读起来眼睛一直在跳;反过来,如果我们人为把每次更新压住 500 毫秒再显示,画面稳了不少,跟听时又会觉得字幕慢半拍。再比如,当模型悄悄改掉了前面一个词,我们应该用浅黄色闪一下提醒读者,还是什么都不提示直接替换?
想严肃回答这些问题,没法靠对着麦克风念两遍稿子来试。就算同一个人照着同一份讲稿念,两次的语速、停顿位置,以及服务端切分音频的时机都会有细微出入。唯一公平的做法,是把某一次真实识别过程中服务端发来的所有更新事件原封不动录下来,再把完全相同的一条字幕流放在不同显示设置下重放给不同的人看。
Echoo 里的录制导出与回放分析页,最早就是为了解决这个需求写出来的。
导出拿到的三个文件
在本地视频字幕或悬浮字幕页面结束一次会话后,页面上会出现“导出会话”按钮。点击之后,所有文件都由浏览器直接在本地拼接并写出,不会上传到服务器:
echoo-<时间>.events.jsonl(事件日志):第一行固定记录这次会话的环境信息,包括目标语言、声音来源、音频参数,以及录制当下生效的呈现设置。从第二行开始,每一行对应服务端推过来的一次字幕更新,原样保留收到该事件时的相对毫秒数(atMs)、那时尚已送出的音频长度(audioMs)、句子编号(segmentId)、是否为中间结果(partial),以及当时的原文(text)和译文(translation)。echoo-<时间>.segments.csv(按句汇总表):如果你不打算重放,只是想用 Excel、R 或 Python 算一下延迟和改写率,直接看这张表就够了。它把事件日志按句子归并成一行一条记录,算好了每一句首次上屏的时间、初稿长什么样、定稿长什么样、中间更新和改写了多少次、译文比原文晚到多久,以及从首字出现到最终定稿花了多长时间。echoo-<时间>.audio.wav(原始音频):实际送进识别模型的那路 16 kHz 单声道 PCM 录音(单次最长保留 30 分钟)。
因为当时的显示设置直接写进了 .events.jsonl 的第一行,哪怕几个月后再翻出实验数据,也不会搞混那次录音是在什么条件下跑出来的。
在回放页里做对照实验
打开“回放与分析”页面,把导出的 .events.jsonl 拖进去,页面上会先画出整场会话的逐句时间线:每一句在哪个时间点冒出第一个词、中途被模型改写了几次、什么时候彻底定稿,一眼就能看清。如果同时把对应的 .audio.wav 也加载进来,回放时钟就会严格锁定在音频进度上。
重放区域的字幕并不是另外写的模拟动画,而是直接复用了实时字幕页面里的同一个渲染组件。这意味着你可以在“字幕设置 → 呈现策略”里调整四个核心变量,并立刻看到它们作用在同一段录音上的真实效果:
- 显示时机:是边识别边上屏,还是等整句定稿后再一次性显示。
- 人为延迟(0–3000 毫秒):在每次更新真正渲染前额外等待一段时间,用来测试延迟与稳定性的交换边界。
- 新词上屏方式:新增的词是平滑淡入,还是直接跳出。
- 修正提示:模型推翻前文时,被改动的部分是短暂高亮一下,还是静默替换。
做阅读理解或眼动实验时,你可以先录好一段十分钟的英文讲座,然后拿同一份 .events.jsonl 和 .audio.wav 给四组受试者回放——只切换“修正提示”和“显示时机”,其余从语音到每一次模型改写的中间态都分毫不差。
如果你的问题不是“怎么显示”,而是“换一个识别或翻译模型会差多少”,可以改用引擎对照页面:它会把同一路麦克风或系统音频同时喂给两个引擎,左右并排实时对比延迟和译文,结束时同样可以把两边的记录一起导出来。