手动控制说话开始和结束

更新时间不可用

了解如何快速接入对话式 AI 引擎,完成环境准备、参数配置、示例运行和核心流程验证。

当你的业务场景不适合依赖服务端自动判定用户何时开始说话或结束说话时,可以使用手动 SoS/EoS 能力,由客户端显式声明用户回合边界。该能力适用于 AI 面试、互动答题、对讲机模式等需要“按下开始、点击提交”的交互。本文介绍如何通过创建智能体配置和客户端组件接口,实现手动控制用户说话边界。

集成流程

手动轮次控制需要同时配置智能体启动参数和客户端组件:

Text
启动 Agent 时配置 manual 模式
→ 客户端初始化 toolkit 并订阅 RTM 消息
→ 注册手动 SoS/EoS 结果回调
→ 用户点击开始/提交时调用 manualSOS/manualEOS

选择控制模式

start_of_speech.mode 和 end_of_speech.mode 是两个独立配置。先根据交互选择需要手动控制的边界:

业务场景start_of_speech.modeend_of_speech.mode客户端调用
用户可自由开始说话,但需要点击“提交答案”vadmanual只调用 manualEOS
用户点击或按下后开始说话,结束由服务端自动判停manualvad只调用 manualSOS
按住说话、松开发送、对讲机模式manualmanual先调用 manualSOS,再调用 manualEOS
表格内容超出当前宽度,可横向滚动查看更多列。

如果只把 end_of_speech.mode 设为 manual,则服务端仍会通过 VAD 自动识别用户开始说话;业务只需要在用户点击提交时调用 manualEOS。

如果只把 start_of_speech.mode 设为 manual,则服务端只会在客户端调用 manualSOS 后开始接收本轮用户音频;结束说话仍由 VAD 自动识别,业务不需要调用 manualEOS。

如果同时把 start_of_speech.mode 和 end_of_speech.mode 设为 manual,则服务端只会在客户端调用 manualSOS 后开始接收本轮用户音频,并在客户端调用 manualEOS 后提交本轮发言。

前提条件

开始前,请确保完成以下准备工作:

  • 已集成 RTC SDK v4.5.1 及以上版本,且已在 App 中实现基本的实时音视频功能并获取相关设备权限。请参考实现音视频互动。
  • 已在控制台为项目启用 RTM 服务,并在 App 中实现基本的实时消息功能。请参考实现收发消息。
  • 已参考实现对话式智能体实现与智能体对话的基本逻辑。
  • 确保 RTC 可用、RTM 已登录,且 RTC 和 RTM 实例的生命周期大于组件的生命周期。组件内部不负责维护 RTC,RTM 的初始化、生命周期以及鉴权/登录状态的逻辑。

实现手动控制用户说话开始和结束

创建智能体时开启手动轮次控制

调用 POST 创建对话式智能体 接口时,开启 RTM,并根据业务场景将需要手动控制的一侧设为 manual。

如果你只需要手动控制结束说话,可以保留自动 SoS,仅将 end_of_speech.mode 设为 manual。

JSON
{
  "name": "manual-eos-agent",
  "properties": {
    "channel": "channel_name",
    "token": "token",
    "agent_rtc_uid": "0",
    "remote_rtc_uids": ["123"],
    "advanced_features": {
      "enable_rtm": true
    },
    "turn_detection": {
      "mode": "default",
      "config": {
        "start_of_speech": {
          "mode": "vad",
          "vad_config": {
            "interrupt_duration_ms": 160,
            "speaking_interrupt_duration_ms": 320,
            "prefix_padding_ms": 800
          }
        },
        "end_of_speech": {
          "mode": "manual"
        }
      }
    },
    "parameters": {
      "data_channel": "rtm"
    }
  }
}

如果你只需要手动控制开始说话,可以将 start_of_speech.mode 设为 manual,并保留自动 EoS。

JSON
{
  "name": "manual-sos-agent",
  "properties": {
    "channel": "channel_name",
    "token": "token",
    "agent_rtc_uid": "0",
    "remote_rtc_uids": ["123"],
    "advanced_features": {
      "enable_rtm": true
    },
    "turn_detection": {
      "mode": "default",
      "config": {
        "start_of_speech": {
          "mode": "manual"
        },
        "end_of_speech": {
          "mode": "vad",
          "vad_config": {
            "silence_duration_ms": 480
          }
        }
      }
    },
    "parameters": {
      "data_channel": "rtm"
    }
  }
}

如果你需要完整的对讲机模式,则同时将 start_of_speech.mode 和 end_of_speech.mode 设为 manual。

JSON
{
  "name": "manual-sos-eos-agent",
  "properties": {
    "channel": "channel_name",
    "token": "token",
    "agent_rtc_uid": "0",
    "remote_rtc_uids": ["123"],
    "advanced_features": {
      "enable_rtm": true
    },
    "turn_detection": {
      "mode": "default",
      "config": {
        "start_of_speech": {
          "mode": "manual"
        },
        "end_of_speech": {
          "mode": "manual"
        }
      }
    },
    "parameters": {
      "data_channel": "rtm"
    }
  }
}

集成并初始化客户端组件

先完成组件集成:

Maven (Maven)

在 Android 项目的 build.gradle 文件中添加如下依赖:

groovy
implementation 'io.agora.agents:agora-agent-client-toolkit:2.10.0'

源码集成 (源码集成)

将 convoaiApi 文件夹拷贝到你的项目中,并在后续调用组件 API 前引入组件。

CocoaPods (CocoaPods)

在 Podfile 中添加如下依赖:

Ruby
pod 'agent-client-toolkit-swift', '2.10.0'

Swift Package Manager (Swift Package Manager)

在 Xcode 中添加如下 Package URL,并将版本指定为 tag 2.10.0:

Text
https://github.com/AgoraIO/agent-client-toolkit-swift.git

源码集成 (源码集成)

将 ConversationalAIAPI 文件夹拷贝到你的项目中,并在后续调用组件 API 前引入组件。

Package Manager (Package Manager)

根据你的项目类型安装组件依赖。

  • Vanilla JS / TypeScript:

    Shell
    pnpm add agora-agent-client-toolkit@2.10.0
  • React:

    Shell
    pnpm add agora-agent-client-toolkit@2.10.0 agora-agent-client-toolkit-react@2.10.0

源码集成 (源码集成)

将 conversational-ai-api 文件夹拷贝到你的项目中,并在后续调用组件 API 前引入组件。

信息

如果在 Android 或 iOS 项目中同时集成多个声网 SDK 时出现库冲突,请参考多 SDK 库冲突处理。

然后使用已有的 RTC 和 RTM 实例初始化客户端组件。

Kotlin
val config = ConversationalAIAPIConfig(
    rtcEngine = rtcEngine,
    rtmClient = rtmClient,
    renderMode = TranscriptRenderMode.Word,
    enableLog = true,
    enableRenderModeFallback = true
)

val api = ConversationalAIAPIImpl(config)

注册消息回调并订阅频道消息

手动 SoS/EoS 的处理结果通过专用回调或事件返回,你需要先注册这些回调或事件,再订阅智能体所在频道的消息:

Kotlin
api.addHandler(object : IConversationalAIAPIEventHandler {
    override fun onUserManualSosEvent(agentUserId: String, event: UserManualSosEvent) {
        // 处理手动 SOS 结果。event.payload.success 表示服务端是否接受。
    }

    override fun onUserManualEosEvent(agentUserId: String, event: UserManualEosEvent) {
        // 处理手动 EOS 结果。
    }

    override fun onAgentManualEosEvent(agentUserId: String, event: AgentManualEosEvent) {
        // 处理服务端因超限等原因触发的自动 EOS 通知。
    }
})

api.subscribeMessage("channelName") { error ->
    if (error != null) {
        // 处理订阅失败
    }
}

信息

这些回调用于接收服务端对手动 SoS/EoS 请求的处理结果。你可以根据回调中的 event、requestId 和错误信息实现自己的业务逻辑。如需查看相关接口和事件说明,请参考客户端组件 API。

让智能体加入频道

创建智能体后,让智能体加入与你的用户相同的 RTC 频道:

调用 POST 创建对话式智能体接口,并完成以下参数设置:

  • advanced_features.enable_rtm: true —— (必选)启动 RTM 服务
  • parameters.data_channel: "rtm" —— (必选)开启 RTM 数据传输通道
  • parameters.enable_metrics: true —— (按需开启)接收智能体性能数据
  • parameters.enable_error_message: true —— (按需开启)接收智能体错误事件

调用成功后,智能体会加入指定 RTC 频道,用户可以开始与智能体互动。

在用户开始说话时发送手动 SoS

仅当 start_of_speech.mode = "manual" 时需要调用 manualSOS。如果你使用 VAD 自动 SoS,可以跳过这一步。

Kotlin
api.manualSOS(agentUserId = "agentUserId") { requestId, error ->
    if (error != null) {
        Log.e("ManualSOS", "发送失败: ${error.errorMessage}, requestId=$requestId")
    } else {
        Log.i("ManualSOS", "已发送 SOS, requestId=$requestId")
    }
}

手动 SoS 生效后,服务端开始把后续音频计入本轮用户发言。在此之前到达的音频不会计入本轮。

在用户结束说话时发送手动 EoS

仅当 end_of_speech.mode = "manual" 时需要调用 manualEOS。如果你使用 VAD 自动 EoS,可以跳过这一步。

Kotlin
api.manualEOS(agentUserId = "agentUserId") { requestId, error ->
    if (error != null) {
        Log.e("ManualEOS", "发送失败: ${error.errorMessage}, requestId=$requestId")
    } else {
        Log.i("ManualEOS", "已发送 EOS, requestId=$requestId")
    }
}

手动 EoS 生效后,服务端会按现有链路提交 ASR、触发 LLM 推理,并在后续生成回复。该信号只表示“用户当前发言段结束”,不等同于整个 turn 立即结束。

销毁组件实例

结束 AI 对话场景后或关闭 App 前,你需要销毁组件实例,以释放组件的所有资源。

Kotlin
api.destroy()

API 参考

客户端组件 API