返回博客

一条 WebSocket 拿到说话人和时间戳:用 LecSync 实时 API 做会议客户端

LecSync Team

会议记录好不好用,看每一句话能不能回答两个问题:谁说的,在录音的哪个位置。说话人分割和对齐音频的时间戳,决定了实时字幕能不能变成一份可以搜、可以回放、可以引用的记录。这篇文章讲怎么用 LecSync 实时 API 在一条 WebSocket 上同时拿到这两样,消息长什么样,以及同样的需求放到 AssemblyAI、Deepgram 和 OpenAI 上分别要怎么做。

文中其他厂商的信息全部来自各家公开文档和定价页,核对日期为 2026 年 10 月 6 日。LecSync 的信息以开发者页面和 API 文档为准。

做会议客户端,实时语音 API 要给到什么?

会议客户端需要每一条落定的文字都带三个字段:说话人、开始时间、结束时间,而且时间要和录音用同一个时钟。有了这三样,应用才能按人区分颜色、点任意一句跳到对应位置播放、把纪要里的要点链回当时的原话。

预览文字只服务于实时显示,随时会被替换。产品最终保存和展示的记录来自落定段落,所以说话人和时间必须挂在落定段落上。

LecSync 在一条连接上返回什么

在连接请求里打开说话人:

{
  "transcribe": { "languages": ["auto"], "speakers": true },
  "translate": { "languages": ["en", "zh"] },
  "digest": true,
  "store": true
}

之后每个落定段落都是一条 transcript.final,说话人和时间在同一条消息里:

{
  "type": "transcript.final",
  "segmentId": "gw_8f3a_2",
  "speaker": "speaker_0",
  "text": "So the quantization step near zero is about eight.",
  "startMs": 118400,
  "endMs": 122900
}

还有三类消息通过同一个 segmentId 挂到这一行上:

  • translation.final 是译文,自带 startMs 和 endMs,原文和译文天然落在同一行。
  • 打开 aiEnhance 后,精修过的译文会用同一个 segmentId 再推一次,带 enhanced: true。直接覆盖这一行即可,别追加成新行。
  • digest.update 按话题推送实时纪要,每段带 startMs、endMs 和生成它的 segmentIds。文档特别说明,这些时间是根据转写段落算出来的,不由模型生成。

预览消息 transcript.partial 不带说话人。LecSync 要等段落落定才判定是谁说的,所以预览文字可以先用中性样式显示,收到 final 再上颜色。

以上全部按每音频分钟 $0.006 计费。开发者页面列出的包含项里有说话人分割、对齐音频的时间戳、实时翻译、实时结构化纪要和 30 天录音存储,并写明关闭功能不会降价。

断线以后,时间轴怎么不乱

一场长会里会遇到两种重连,处理方式不一样。

你看不到的上游重连

识别引擎报的时间是相对它自己那条连接的。会话中途这条连接一旦重建,引擎的时钟归零,点播放就会往回跳。LecSync 时间戳文档说明,它用你发送音频的字节数来计时,所以上游重连时 startMs 照样单调递增。开了 store: true,这个值就是可下载录音里的位置。

文档也写明了一个边界情况:识别器没给出 token 级时间时,少数段落可能不带时间戳。客户端要能接受没有 startMs 的 final,这一行不可跳播就是了。

你自己的连接断了

客户端的 socket 一关,这条流就结束了。断线文档写得很清楚:没有续传,重新调用 connect 就是一条新流,segmentId 编号和 startMs 都从头开始,术语表要重新传。开了 store: true 的话,每条连接各自生成一个录音文件。

客户端多存一点状态就能解决:

  1. 记下每条流发出的字节数。16 kHz、16 位、单声道 PCM,每秒音频是 32,000 字节。
  2. 一条流结束时,把它的时长累加到 meetingOffsetMs。
  3. 新流的每个段落按 meetingOffsetMs + startMs 入库,段落 ID 前面加上流序号。
  4. 录音文件按创建时间排好,回放时按会议时间找到对应的文件。

说话人标签也按单条流来理解。文档没有承诺新连接里的 speaker_0 还是同一个人,重连之后最好让主持人确认一下名字。

四家 API 做带说话人的实时转写,差在哪

以下内容于 2026 年 10 月 6 日对照各家公开文档和定价页核对。

LecSync Realtime STTAssemblyAI 流式Deepgram 流式(Nova-3)OpenAI gpt-live-transcribe
怎么开说话人transcribe.speakers: truespeaker_labels: truediarize_model=latest(或 v1)不支持
标签挂在哪每个落定段落(speaker_0…)每个 Turn(A、B…)和每个 final 词每个词(从 0 开始的整数)—
时间戳final 原文和译文都带 startMs/endMs,毫秒词级 start/end,毫秒,从流开始算词级 start/end,秒,从流开始算不返回词级时间戳
事后修正标签文档未提及会话结束时发 SpeakerRevision,也可设为会中定期发文档未提及流式修正—
同一连接出译文支持,按 segmentId 配对翻译附加项仅限录音文件定价页没有流式翻译项需另开 gpt-realtime-translate 会话
同一连接出纪要支持,digest.update 带时间范围未列流式纪要附加项,纪要走 LLM Gateway摘要在 Audio Intelligence 下按 token 计费—
说话人附加费已含在单价里每小时 +$0.12,按会话时长计每分钟 $0.0020—

出处:AssemblyAI 流式说话人分割、AssemblyAI 定价、Deepgram 说话人分割、Deepgram 定价、OpenAI 实时转写指南、OpenAI 定价。

别家做得更细的地方

只论说话人分割本身,AssemblyAI 做得更深。每个 final 词都有自己的说话人和 speaker_confidence 分数,一句话里有人插嘴也能标出来。SpeakerRevision 会在模型听到更多内容后回头修正前面的标签;会中修正的间隔最短 120 秒,文档建议设 5 分钟。不到约 1 秒的短句会标成 PENDING,界面上要给这种状态留位置。

Deepgram 同样是词级标注,想在别人插话的地方把一段拆开,会更方便。

LecSync 按整段标注。转录文档说明,默认的 sentence 显示模式会按标点、说话人切换和停顿来分段,所以换人说话通常就是新的一行。如果产品确实需要词级归属或置信度,AssemblyAI 和 Deepgram 更合适。

OpenAI 的指南写明,gpt-live-transcribe 不返回词级时间戳、说话人标签和置信度,需要的话建议改用文件转写模型或在应用层自己兜底。拿它做带说话人的实时会议界面,不太合适。

带说话人转写一小时,各家多少钱

按上面的按量付费公开价计算,有翻译的只算一种目标语言:

方案每小时包含什么
LecSync60 × $0.006 = $0.36说话人、时间戳、翻译、实时纪要,可选存储
AssemblyAI Universal-Streaming + 说话人$0.15 + $0.12 = 每会话小时 $0.27说话人和时间戳,无流式翻译
AssemblyAI Universal-3.6 Pro Realtime + 说话人$0.45 + $0.12 = 每会话小时 $0.57同上,换成高端模型
Deepgram Nova-3 Monolingual + 说话人($0.0048 + $0.0020) × 60 = 促销价 $0.408,原价 $0.582说话人和时间戳
Deepgram Nova-3 Multilingual + 说话人($0.0058 + $0.0020) × 60 = 促销价 $0.468,原价 $0.672说话人和时间戳
OpenAI gpt-live-transcribe60 × $0.017 = $1.02只有文字,没有说话人和词级时间戳

有两处计费规则会让实际账单偏离这张表。AssemblyAI 的流式按 WebSocket 打开的时长计费,空闲时间也算,说话人附加费同样覆盖整个会话。LecSync 按有效音频时长计费,没有有效音频不收费,不过定价文档也写了被接收的静音照样计费。Deepgram 的流式低价标注为限时促销。

如果只要说话人和时间戳,AssemblyAI Universal-Streaming 每小时更便宜。同一场会还要实时翻译和随会纪要时,LecSync 的 $0.36 已经把这两样包进去,不用再接第二家服务。放大到 1,000 小时的算法,可以看这篇实时语音识别 API 价格对比。

客户端怎么搭:六步

  1. 连接。POST https://api.lecsync.com/v1/realtime/connect,带上 speakers: true、语言对、digest: true;要做点句跳播就加 store: true。
  2. 推流。收到 session.ready 后发裸 pcm_s16le,16 kHz 单声道,每帧不超过 64 KB,不需要序号和偏移量。
  3. 按 ID 存 final。以 segmentId 为主键,transcript.final 填 text、speaker、startMs、endMs,translation.final 挂到同一行。
  4. 给说话人起名。先显示 speaker_0、speaker_1 占位,让主持人改成真名。映射关系存在应用里,按流区分。
  5. 跳播。点击某行,从 startMs 播放已存的录音。GET /v1/recordings/{sessionId} 在 30 天内返回音频和转写的签名链接。
  6. 用纪要导航。每个 digest.update 段落当作一个章节,segmentIds 和时间范围告诉你该高亮哪几行、跳到哪里。

最小的消息处理:

ws.onmessage = (e) => {
  const m = JSON.parse(e.data);
  if (m.type === "transcript.final") {
    rows.set(m.segmentId, {
      speaker: m.speaker ?? null,
      text: m.text,
      startMs: m.startMs != null ? meetingOffsetMs + m.startMs : null,
      endMs: m.endMs != null ? meetingOffsetMs + m.endMs : null,
    });
  } else if (m.type === "translation.final") {
    const row = rows.get(m.segmentId);
    if (row) row.translation = m.text; // enhanced: true 时直接覆盖
  } else if (m.type === "digest.update") {
    chapters = m.sections; // 每次推送都是完整快照,整体替换
  }
};

网络抖动时实时字幕会不会越拖越远,可以看 LecSync 如何把积压卡在 2 秒。

什么样的会议产品选哪家

  • 只要字幕加说话人、单一语言、账单最低:AssemblyAI Universal-Streaming 加说话人分割。
  • 做质检工具,需要词级说话人和置信度:AssemblyAI,Deepgram 也是词级。
  • 一条连接里要带说话人的转写、实时翻译和随会纪要,一个单价:LecSync。
  • 要的是会说话的助手或语音代理:去看 OpenAI 的实时模型;单靠 gpt-live-transcribe 拿不到说话人。

更全面的横向对比见 LecSync 对比 AssemblyAI、OpenAI 和 LecSync 对比 Deepgram。

常见问题

LecSync 实时 API 支持说话人分割吗?

支持。在连接请求里把 transcribe.speakers 设为 true,之后每条落定的 transcript.final 都会带 speaker 字段(如 speaker_0),和 startMs、endMs 在同一条消息里。预览结果没有说话人,因为要等段落落定才判定。说话人分割包含在每音频分钟 $0.006 里。

LecSync 的时间戳和录音对得上吗?

对得上。原文和译文的 final 都带 startMs、endMs,单位毫秒,从你发出的第一个字节算起。时间来自字节计数,上游识别器重连时也保持递增。开了 store: true,这些值可以直接对应到下载的录音文件。

我这边 WebSocket 断了,时间戳会怎样?

socket 关闭就代表这条流结束,没有续传。下一次 connect 是新流,segmentId 和 startMs 从零开始,录音也是新文件。客户端记下每条已结束流的时长,作为偏移量加上去,就能拼回一条连续的会议时间轴。

说话人分割要另外收费吗?

LecSync 不另收,它在 $0.006 每音频分钟的包含项里。截至 2026 年 10 月 6 日,AssemblyAI 流式说话人分割在模型单价之外每小时加 $0.12;Deepgram 按量付费的流式说话人分割是每分钟 $0.0020。

OpenAI 的实时转写能分说话人吗?

gpt-live-transcribe 不能。OpenAI 实时转写指南写明,这个模型不返回词级时间戳、说话人标签和置信度;确实需要时,建议用文件转写模型或在应用层兜底。

能把说话人显示成真名吗?

API 返回的是 speaker_0、speaker_1 这样的标签,换成真名要在应用里做,比如让主持人逐个改名。映射按流保存,因为文档没有说标签会延续到新连接。

一句话总结

做会议客户端,难点在于一小时甚至更久的会议里,说话人、原文、译文和时间始终挂在同一行。LecSync 用同一个 segmentId 把四样一起返回,上游重连时时钟不倒退,还附带有时间范围的实时纪要,统一按每音频分钟 $0.006 计费。只要带说话人的字幕,AssemblyAI 更便宜,也标得更细。接入可以从 LecSync Realtime STT 开发者页面和说话人文档开始。