logo
当前页

展示字幕


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

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

前提条件

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

快速实现

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

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

flowchart TD Start([开始]) --> Init[实现onRecvExperimentalAPI回调并初始化字幕UI组件] Init --> ParseMessage[解析RTC房间自定义消息] ParseMessage --> |Cmd=3| ProcessASR[处理ASR文本] ParseMessage --> |Cmd=4| ProcessLLM[处理LLM文本] ProcessASR --> UpdateSubtitles1[更新用户字幕] ProcessLLM --> UpdateSubtitles2[更新智能体字幕] UpdateSubtitles1 --> HandleEndFlags[消息结束后清理消息缓存] UpdateSubtitles2 --> HandleEndFlags[消息结束后清理消息缓存] HandleEndFlags --> End([结束])

监听房间自定义消息

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

YourViewController.h
YourViewController.m
// 实现ZegoEventHandler协议
@interface YourService () <ZegoEventHandler>
@property (nonatomic, strong) YourViewController *youViewController;
@end

@implementation YourService

// 处理express onRecvExperimentalAPI接收到的消息
- (void)onRecvExperimentalAPI:(NSString *)content {
    // 转发给view解析消息内容
    [self.youViewController handleExpressExperimentalAPIContent:content];
}

@end // YourService implementation
1
Copied!
// 在头文件中实现ZegoEventHandler协议
@interface YourViewController () <ZegoEventHandler>

@end

@implementation YourViewController

// 解析自定义信令消息
- (void)handleExpressExperimentalAPIContent:(NSString *)content {
    // 解析JSON内容
    NSError *error;
    NSData *jsonData = [content dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *contentDict = [NSJSONSerialization JSONObjectWithData:jsonData 
                                                        options:NSJSONReadingMutableContainers 
                                                          error:&error];
    if (error || !contentDict) {
        NSLog(@"JSON解析失败: %@", error);
        return;
    }
    // 检查是否为房间消息
    NSString *method = contentDict[@"method"];
    if (![method isEqualToString:@"liveroom.room.on_recive_room_channel_message"]) {
        return;
    }
    // 获取消息参数
    NSDictionary *params = contentDict[@"params"];
    if (!params) {
        return;
    }
    NSString *msgContent = params[@"msg_content"];
    NSString *sendIdName = params[@"send_idname"];
    NSString *sendNickname = params[@"send_nickname"];
    NSString *roomId = params[@"roomid"];
    if (!msgContent || !sendIdName || !roomId) {
         NSLog(@"parseExperimentalAPIContent 参数不完整: msgContent=%@, sendIdName=%@, roomId=%@",
                msgContent, sendIdName, roomId);
        return;
    }
    
    // JSON 字符串示例:"{\"Timestamp\":1745224717,\"SeqId\":1467995418,\"Round\":2132219714,\"Cmd\":3,\"Data\":{\"MessageId\":\"2135894567\",\"Text\":\"你\",\"EndFlag\":false}}"
    // 解析消息内容
    [self handleMessageContent:msgContent userID:sendIdName userName:sendNickname ?: @""];
}

// 处理消息内容
- (void)handleMessageContent:(NSString *)command userID:(NSString *)userID userName:(NSString *)userName{
    NSDictionary* msgDict = [self dictFromJson:command];
    if (!msgDict) {
        return;
    }
  
    // 解析基本信息
    int cmd = [msgDict[@"Cmd"] intValue];
    int64_t seqId = [msgDict[@"SeqId"] longLongValue];
    int64_t round = [msgDict[@"Round"] longLongValue];
    int64_t timestamp = [msgDict[@"Timestamp"] longLongValue];
    NSDictionary *data = msgDict[@"Data"];
  
    // 根据命令类型处理消息
    switch (cmd) {
        case 3: // ASR文本
            [self handleAsrText:data seqId:seqId round:round timestamp:timestamp];
            break;
        case 4: // LLM文本
            [self handleLlmText:data seqId:seqId round:round timestamp:timestamp];
            break;
    }
}

@end // YourViewController implementation
1
Copied!

房间自定义消息协议

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

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

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

处理逻辑

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

使用字幕组件

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

注意事项

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

Previous

快速开始

Next

获取 AI Agent 服务状态