实时字幕
更新时间不可用
本文介绍如何在你的 App 中实现实时字幕功能。
与对话式智能体进行实时互动时,你可能需要实时字幕来显示你与智能体的对话内容。本文介绍如何在你的 App 中实现实时字幕功能。
技术原理
声网提供一套灵活可扩展、标准化的对话式 AI 引擎客户端组件(以下简称组件)。该组件支持 iOS、Android、Web 平台,封装了多个场景化 API,你只需要调用这些 API 即可结合声网实时互动 (RTC) SDK 和实时消息 (RTM) SDK 的能力实现以下功能:
组件通过 onTranscriptUpdated 回调接收字幕转录内容,支持监听不同类型的字幕转录信息:
- 智能体字幕:智能体的语音转录内容,包括实时更新和最终结果。
- 用户字幕:用户的语音转录内容,支持实时显示和状态管理。
- 字幕转录状态:支持进行中、完成、中断等不同状态的处理。
以下为使用组件实现实时字幕功能的工作流程图:
前提条件
开始前,请确保完成以下准备工作:
实现方法
集成组件
Maven (Maven)
在 Android 项目的 build.gradle 文件中添加如下依赖:
implementation 'io.agora.agents:agora-agent-client-toolkit:2.10.0'Swift Package Manager (Swift Package Manager)
在 Xcode 中添加如下 Package URL,并将版本指定为 tag 2.10.0:
https://github.com/AgoraIO/agent-client-toolkit-swift.git源码集成 (源码集成)
将 ConversationalAIAPI 文件夹拷贝到你的项目中,并在后续调用组件 API 前引入组件。你可以前往组件结构了解各个文件作用。
Package Manager (Package Manager)
根据你的项目类型安装组件依赖。
-
Vanilla JS / TypeScript:
Bash pnpm add agora-agent-client-toolkit@2.10.0 -
React:
Bash pnpm add agora-agent-client-toolkit@2.10.0 agora-agent-client-toolkit-react@2.10.0
源码集成 (源码集成)
将 conversational-ai-api 文件拷贝到你的项目中,并在后续调用组件 API 前引入组件。你可以前往组件结构了解各个文件作用。
初始化组件
为 RTC 和 RTM 实例创建配置对象,并设置转录字幕渲染模式,之后创建组件实例:
// 为 RTC 和 RTM 实例创建配置对象
val config = ConversationalAIAPIConfig(
rtcEngine = rtcEngineInstance,
rtmClient = rtmClientInstance,
/**
* 设置转录字幕渲染模式,可选值:
* - `TranscriptRenderMode.Word`:逐字渲染模式,即回调接收的字幕内容将逐字渲染到 UI 上。
* - `TranscriptRenderMode.Text`:逐句渲染模式,即回调接收的字幕内容将全量渲染到 UI 上。
*/
renderMode = TranscriptRenderMode.Word,
enableLog = true
)
// 创建组件实例
val api = ConversationalAIAPIImpl(config)/// 为 RTC 和 RTM 实例创建配置对象
let config = ConversationalAIAPIConfig(
rtcEngine: rtcEngine,
rtmEngine: rtmEngine,
/**
* 设置转录字幕渲染模式,可选值:
* - `.words`:逐字渲染模式,即回调接收的字幕内容将逐字渲染到 UI 上。
* - `.text`:逐句渲染模式,即回调接收的字幕内容将全量渲染到 UI 上。
*/
renderMode: .words,
enableLog: true
)
/// 创建组件实例
convoAIAPI = ConversationalAIAPIImpl(config: config)// 初始化组件
ConversationalAIAPI.init({
rtcEngine,
rtmEngine,
/**
* 设置转录字幕渲染模式,可选值:
* - `ESubtitleHelperMode.WORD`:逐字渲染模式,即回调接收的字幕内容将逐字渲染到 UI 上。
* - `ESubtitleHelperMode.TEXT`:逐句渲染模式,即回调接收的字幕内容将全量渲染到 UI 上。
*
* 不指定则自动根据消息判断模式,或手动指定模式
*/
renderMode: ESubtitleHelperMode.WORD,
})
// 获取 API 实例(单例)
const conversationalAIAPI = ConversationalAIAPI.getInstance()信息
逐字渲染模式 (ESubtitleHelperMode.WORD) 下需要接收来自 RTC 的音频时间戳信息才能实现字幕和语音同步输出。为此,在创建客户端对象前,请确保完成以下设置:
// 设置传递音频时间戳信息
AgoraRTC.setParameter("ENABLE_AUDIO_PTS_METADATA", true);
// 创建客户端对象并指定频道场景和浏览器编码方式
const client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });注册字幕回调
调用 addHandler 方法,注册并实现字幕转录回调:
api.addHandler(covEventHandler)convoAIAPI.addHandler(handler: self)// 监听转录内容更新,用于实时显示字幕转录内容
conversationalAIAPI.on(EConversationalAIAPIEvents.TRANSCRIPT_UPDATED, onTextChanged)实现字幕数据回调接口
你需要自行实现字幕处理逻辑,根据转录内容更新 UI 显示。
将你实现的字幕 UI 模块继承自 IConversationalAIAPIEventHandler 接口,并实现 onTranscriptUpdated 方法,在该方法内处理字幕渲染至 UI 的逻辑。
private val covEventHandler = object : IConversationalAIAPIEventHandler {
override fun onTranscriptUpdated(agentUserId: String, transcript: Transcript) {
// 在此处接收字幕更新 UI
}
}将你实现的字幕 UI 模块实现 ConversationalAIAPIEventHandler 协议,并实现 onTranscriptUpdated 方法,在该方法内处理字幕渲染至 UI 的逻辑:
extension ChatViewController: ConversationalAIAPIEventHandler {
public func onTranscriptUpdated(agentUserId: String, transcript: Transcript) {
//可以在此处接收字幕更新 UI
}
}将你实现的字幕 UI 模块接收客户端组件的字幕数据回调,并实现一个简单的 React JS 组件来展示这些消息:
信息
- 所有
TRANSCRIPT_UPDATED事件回调均返回完整聊天对话列表。每次均有可能更新最近的几条对话字幕,请根据完整的列表渲染 UI。 - 推荐使用状态管理库如
zustand、redux等来代替React.useState管理状态,以便在组件间共享状态。
import * as React from "react"
import {
type IUserTranscript,
type IAgentTranscript,
type ISubtitleHelperItem,
EConversationalAIAPIEvents,
} from "@/conversational-ai-api/type"
import { ConversationalAIAPI } from "@/conversational-ai-api"
// 监听转录内容更新,用于实时显示字幕转录内容
export const ChatHistory = () => {
const [chatHistory, setChatHistory] = React.useState<
ISubtitleHelperItem<Partial<IUserTranscript | IAgentTranscript>>[]
>([])
const conversationalAIAPI = ConversationalAIAPI.getInstance()
conversationalAIAPI.on(
EConversationalAIAPIEvents.TRANSCRIPT_UPDATED,
setChatHistory
)
return (
<>
{chatHistory.map((message) => (
<div key={`${message.uid}-${message.turn_id}`}>
{message.uid}: {message.text}
</div>
))}
</>
)
}订阅频道消息
字幕转录内容通过 RTM 频道消息传递,你需要在开始智能体会话前订阅频道消息,以接收字幕数据。
在开始智能体会话前调用 subscribeMessage 订阅频道消息:
api.subscribeMessage("channelName") { error ->
if (error != null) {
// 处理错误
}
}在开始智能体会话前调用 subscribeMessage 订阅频道消息:
convoAIAPI.subscribeMessage(channelName: channelName) { error in
if let error = error {
print("订阅失败: \(error.message)")
} else {
print("订阅成功")
}
}conversationalAIAPI.subscribeMessage(channel_name)智能体加入频道
你可以通过 RESTful API 或 Agents SDK 创建并启动智能体;本文后续步骤聚焦客户端组件侧的事件订阅和消息处理。
调用 POST 创建对话式智能体接口,或在 Agents SDK 的会话配置中完成以下参数设置:
advanced_features.enable_rtm: true—— (必选)启动 RTM 服务parameters.data_channel: "rtm"—— (必选)开启 RTM 数据传输通道parameters.enable_metrics: true—— (按需开启)接收智能体性能数据parameters.enable_error_message: true—— (按需开启)接收智能体错误事件
调用成功后,智能体会加入指定 RTC 频道,用户可以开始与智能体互动。
取消订阅频道消息
每次智能体会话结束后,你需要取消订阅频道消息,以释放字幕相关资源。
api.unsubscribeMessage("channelName") { error ->
if (error != null) {
// 处理错误
}
}/// 取消订阅频道消息
convoAIAPI.unsubscribeMessage(channelName: channelName) { error in
if let error = error {
print("取消订阅失败: \(error.message)")
} else {
print("取消订阅成功")
}
}conversationalAIAPI.unsubscribeMessage(channel_name)销毁组件实例
结束 AI 对话场景后或关闭 App 前,你需要销毁组件实例,以释放组件的所有资源。
api.destroy()convoAIAPI.destroy()conversationalAIAPI.destroy()参考信息
示例项目
声网提供了开源的实时字幕示例项目供你参考,你可以前往下载或查看其中的源代码。
组件结构
客户端组件文件夹的结构和各文件作用如下:
信息
以下文件和文件夹即为集成客户端组件所需全部内容,无需拷贝其他文件。
IConversationalAIAPI.kt— API 接口及相关数据结构和枚举ConversationalAIAPIImpl.kt— ConversationalAI API 主要实现逻辑ConversationalAIUtils.kt— 工具函数与事件回调管理subRender/v3/— 字幕部分模块TranscriptionController.kt— 字幕控制器MessageParser.kt— 消息解析器
ConversationalAIAPI.swift— API 接口ConversationalAIAPIImpl.swift— ConversationalAI API 主要实现逻辑MessageModels.swift— 消息模型和相关枚举MessagePayloadBuilder.swift— RTM 消息载荷构造器Transcription/TranscriptionController.swift— 字幕控制器
index.ts— API 类type.ts— API 接口及相关数据结构和枚举utils/index.ts— API 工具函数utils/events.ts— 事件管理类,可以拓展该类以轻松实现事件监听和播报utils/sub-render.ts— 字幕部分模块