logo
当前页

展示字幕


本文介绍如何展示用户在与智能体进行语音通话的过程中的字幕。如下:

  • 用户说话内容:流式展示用户正在说的话(语音识别(ASR)的实时结果)
  • 智能体说话内容:流式展示智能体输出的内容(大语言模型(LLM)实时的输出结果)
subtitle.png

前提条件

已按照 快速开始 文档集成 ZEGO Express SDK 和 AI Agent 并实现基本的语音通话功能。

快速实现

用户与智能体进行语音对话期间,AI Agent 服务端通过 RTC 房间自定义消息下发 ASR 识别文本和 LLM 回答的文本。客户端可以监听房间自定义消息,解析对应的状态事件来渲染 UI 。

RTC 房间自定义消息的处理流程如下:

监听房间自定义消息

客户端可通过监听 onRecvExperimentalAPI 回调获取 methodliveroom.room.on_recive_room_channel_message 的房间自定义消息。以下是监听回调的示例代码:

Untitled
// 注意!!!:通过房间自定义消息收到的数据可能会乱序,需要根据 SeqId 字段进行排序。
ZegoExpressEngine.getEngine().setEventHandler(new IZegoEventHandler() {
    @Override
    public void onRecvExperimentalAPI(String content) {
        super.onRecvExperimentalAPI(content);
        try {
            // 第一步:将 content 解析为 JSONObject
            JSONObject json = new JSONObject(content);

            // 第二步:检查 method 字段的值
            if (json.has("method") && json.getString("method")
                .equals("liveroom.room.on_recive_room_channel_message")) {
                // 第三步:获取 params 并解析
                JSONObject paramsObject = json.getJSONObject("params");
                String msgContent = paramsObject.getString("msg_content");

                // JSON 字符串示例:"{\"Timestamp\":1745224717,\"SeqId\":1467995418,\"Round\":2132219714,\"Cmd\":3,\"Data\":{\"MessageId\":\"2135894567\",\"Text\":\"你\",\"EndFlag\":false}}"
                // 将 JSON 字符串解析为 AudioChatMessage 对象
                AudioChatMessage chatMessage = gson.fromJson(msgContent, AudioChatMessage.class);
                if (chatMessage.cmd == 3) {
                    updateASRChatMessage(chatMessage);
                } else if (chatMessage.cmd == 4) {
                    addOrUpdateLLMChatMessage(chatMessage);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
});

/**
 * 语音聊天界面,接收到的后台服务器发过来的 房间内的聊天消息的结构体
 */
  public static class AudioChatMessage {

        @SerializedName(value = "Timestamp", alternate = "timestamp")
        public long timestamp;
        @SerializedName(value = "SeqId", alternate = "seq_id")
        public long seqId;
        @SerializedName(value = "Round", alternate = "round")
        public long round;
        @SerializedName(value = "Cmd", alternate = "cmd")
        public int cmd;
        @SerializedName(value = "Data", alternate = "data")
        public Data data;

        public static class Data {

            @SerializedName(value = "SpeakStatus", alternate = "speak_status")
            public int speakStatus;
            @SerializedName(value = "Text", alternate = "text")
            public String text;
            @SerializedName(value = "MessageId", alternate = "message_id")
            public String messageId;
            @SerializedName(value = "EndFlag", alternate = "end_flag")
            public boolean endFlag;
            @SerializedName(value = "UserId", alternate = "user_id")
            public String userId;
        }
    }
1
Copied!

房间自定义消息协议

房间自定义消息的各字段说明如下:

字段类型描述
TimestampNumber时间戳,秒级别
SeqIdNumber包序列号,可能乱序,请根据序列号对消息进行排序。极端情况下 Id 可能不连续。
RoundNumber对话轮次,每次用户主动说话轮次增加
CmdNumber3: 语音识别(ASR)的文本
4: LLM 文本
DataObject具体内容,各Cmd对应不同Data

Cmd 不同对应的 Data 也不同,具体如下:

处理逻辑

根据 Cmd 字段判断消息类型,并根据 Data 字段获取消息内容。

使用字幕组件

您还可以直接下载字幕处理类源码到您的项目中直接使用。

注意事项

  • 消息排序处理:通过房间自定义消息收到的数据可能会乱序,需要根据 SeqId 字段进行排序。
  • 流式文本处理:
  • ASR 文本每次下发的是全量文本,同一个 MessageId 的消息需要完全替换之前的内容。
  • LLM 文本每次下发的是增量文本,同一个 MessageId 的消息需要在排序后累加显示。
  • 内存管理:请及时清理已完成的消息缓存,特别是当用户进行长时间对话时。

Previous

实现数字人视频通话