You need to enable JavaScript to run this app.
实时音视频

实时音视频

复制全文
进阶功能
获取智能体状态
复制全文
获取智能体状态

支持通过回调机制来实时获取智能体状态,如聆听中、思考中、说话中、被中断或发生错误。您可以将这些状态信息在客户端实时展示,或在服务端进行持久化存储与分析。

接收方式

支持通过客户端或服务端两种方式接收智能体状态信息,它们的适用场景有所不同:

  • 客户端接收(推荐):延迟更低,可靠性更高,适用于需要在终端(App、Web)实时展示智能体状态的场景。
  • 服务端接收:适用于需要将状态持久化存储、进行二次分析,或客户端不便处理实时二进制消息的场景。

通过客户端接收

实现方式

  1. 调用 StartVoiceChat 接口时,将 AgentConfig.EnableConversationStateCallback 设置为 true
  2. 在客户端监听 RTC SDK 回调 onRoomBinaryMessageReceived
  • 不同端回调名称可能有差异,具体请参见客户端 API 参考
  • 其中,C 语言端接口名称为 on_message_received

当智能体状态发生变化时,您将通过上述回调收到一个二进制的 message。您需要对其进行解析,以获取具体的状态信息。

消息解析示例

message 格式,具体请参见二进制消息格式。您可以参考以下示例,解析 message

import VERTC from '@volcengine/rtc';

/**
 * @brief TLV 数据格式转换成字符串
 * @note TLV 数据格式
 * | magic number | length(big-endian) | value |
 * @param {ArrayBufferLike} tlvBuffer
 * @returns 
 */
function tlv2String(tlvBuffer: ArrayBufferLike) {
  const typeBuffer = new Uint8Array(tlvBuffer, 0, 4);
  const lengthBuffer = new Uint8Array(tlvBuffer, 4, 4);
  const valueBuffer = new Uint8Array(tlvBuffer, 8);

  let type = '';
  for (let i = 0; i < typeBuffer.length; i++) {
    type += String.fromCharCode(typeBuffer[i]);
  }

  const length =
    (lengthBuffer[0] << 24) | (lengthBuffer[1] << 16) | (lengthBuffer[2] << 8) | lengthBuffer[3];

  const value = new TextDecoder().decode(valueBuffer.subarray(0, length));

  return { type, value };
};

/**
 * @brief Room Message Handler
 */
function handleRoomBinaryMessageReceived(
  event: {
    userId: string;
    message: ArrayBuffer;
  },
) {
  const { message } = event;
  const { type, value } = tlv2String(message);
  const data = JSON.parse(value);
  const { EventTime, RoundID, Stage, TaskId, UserID, ErrorInfo } = data || {};
  const { Code, Description } = Stage || {};
  // 对 type、data 进行业务处理
  console.log(type, EventTime, RoundID, TaskId, UserID, Code, Description);
  if (ErrorInfo) {
    const { ErrorCode, Reason } = ErrorInfo;
    console.log('Error Occurred:', ErrorCode, Reason);
  }
  // ...
}

/**
 * @brief 监听房间内二进制消息
 */
this.engine.on(VERTC.events.onRoomBinaryMessageReceived, handleRoomBinaryMessageReceived);

通过服务端接收

实现方式

  1. 调用 StartVoiceChat 接口时,通过以下参数配置回调服务器:

    "AgentConfig": {
        "EnableConversationStateCallback": true,  //必须设置为 true
        
        // 1. 您的回调服务地址。系统会将状态消息 POST 到这里。需满足以下要求:
        // - 必须为公网可访问的域名地址。若使用 HTTPS,请确保 SSL 证书合法且完整。
        // - 若同时配置了智能体状态回调(ServerMessageURLForRTS),两者必须使用相同的 URL 地址。
        // - 请确保该 URL 指向的服务端能够正常处理无 Content-Type 的 POST 请求。
        "ServerMessageURLForRTS": "https://your-server.com/example_domain/vertc/cstage",
        
        // 2. 认证密钥。由您自定义,平台只是在回调中原样返回,供你在服务端做合法性校验。
        "ServerMessageSignatureForRTS": "your_custom_secure_signature" 
    }
    
  2. 接收、校验并解析回调消息。
    当智能体状态发生变化时,您配置的 URL 将会收到一个 HTTP POST 请求,请求体格式如下:

    {
      "message": "Y29udgAAAKV7Cg...=",
      "binary": true,
      "signature": "your_custom_secure_signature"
    }
    
    • message:Base64 编码的二进制消息内容。具体格式参看二进制消息格式
    • signature:平台原样回传的签名字符串,即您在 StartVoiceChat 中配置 AgentConfig.ServerMessageSignatureForRTS
      接收到回调消息后,你还需要完成以下事情:
    • 接收消息:获取 messagesignature 字段及其值。
    • 校验 signature:将 signature 的值与 AgentConfig.ServerMessageSignatureForRTS 进行比对。
    • 解析 message:仅在签名校验通过后,才继续解码和解析 message 的内容。

以下是一个完整的 Go 服务示例,实现了上述流程。

你可以在本地快速验证该示例。具体操作,请参见本地验证

package main

import (
   "encoding/base64"
   "encoding/binary"
   "encoding/json"
   "fmt"
   "github.com/gin-gonic/gin"
)
// --- 1. 需要您修改的配置 ---
const (
   conversationStageHeader = "conv"
   exampleSignature        = "your_custom_secure_signature"   // 替换为您在 StartVoiceChat 中配置的真实密钥
)

type RtsMessage struct {
   Message   string `json:"message"`
   Signature string `json:"signature"`
}

type Conv struct {
   TaskID    string    `json:"TaskId"`
   UserID    string    `json:"UserID"`
   RoundID   int64     `json:"RoundID"`   
   EventTime int64     `json:"EventTime"`
   Stage     StageInfo `json:"Stage"`
}

type StageInfo struct {
   Code        stageCode `json:"Code"`
   Description string    `json:"Description"`
}
type stageCode int

const (
   _ stageCode = iota
   listening
   thinking
   answering
   interrupted
   answerFinish
)

var (
   stageListening    = StageInfo{Code: listening, Description: "listening"}
   stageThinking     = StageInfo{Code: thinking, Description: "thinking"}
   stageAnswering    = StageInfo{Code: answering, Description: "answering"}
   stageInterrupted  = StageInfo{Code: interrupted, Description: "interrupted"}
   stageAnswerFinish = StageInfo{Code: answerFinish, Description: "answerFinish"}
)

func HandleConversationStageMsg(c *gin.Context) {
   msg := &RtsMessage{}
   if err := c.BindJSON(&msg); err != nil {
      fmt.Printf("BindJson failed,err:%v\n", err)
      return
   }
   if msg.Signature != exampleSignature {
      fmt.Printf("Signature not match\n")
      return
   }

   conv, err := Unpack(msg.Message)
   if err != nil {
      fmt.Printf("Unpack failed,err:%v\n", err)
      return
   }

   fmt.Println(conv)

   //业务逻辑

   c.String(200, "ok")
}

func Unpack(msg string) (*Conv, error) {
   data, err := base64.StdEncoding.DecodeString(msg)
   if err != nil {
      return nil, fmt.Errorf("DecodeString failed,err:%v", err)
   }
   if len(data) < 8 {
      return nil, fmt.Errorf("Data invalid")
   }
   dataHeader := string(data[:4])
   if dataHeader != conversationStageHeader {
      return nil, fmt.Errorf("Header not match")
   }
   dataSize := binary.BigEndian.Uint32(data[4:8])
   if dataSize+8 != uint32(len(data)) {
      return nil, fmt.Errorf("Size not match")
   }

   subData := data[8:]
   conv := &Conv{}
   err = json.Unmarshal(subData, conv)
   if err != nil {
      return nil, fmt.Errorf("Unmarshal failed,err:%v\n", err)
   }
   return conv, nil
}

func main() {

   r := gin.Default()
   // --- 2. 需要您修改的配置 ---
   // 回调路径:这里的路径 ("/example_domain/vertc/cstage") 必须与您在 StartVoiceChat 中配置的 ServerMessageURLForRTS 的路径部分完全一致。
   // 例如,如果您的回调 URL 是 "https://my-service.com/api/rtc/status",
   // 那么这里的路径就必须是 "/api/rtc/status"。
   r.POST("/example_domain/vertc/cstage", HandleConversationStageMsg)
   r.Run()
}

预期解析结果示例:

&{ChatTask01 Huoshan01 16 1765787330849 {1 listening}}

本地验证

  1. 创建一个 main.go 文件,复制上述示例代码,并按照注释修改代码中的 exampleSignature 的值和 r.POST 中的路径。

  2. 安装 Gin 框架:

    go get github.com/gin-gonic/gin
    
  3. 启动服务:

    go run main.go
    

    您将看到服务在 8080 端口启动的提示。

  4. 打开新终端,使用 curl 模拟一次真实的回调请求。
    注意:signature 的值需与 main.go 代码中的 exampleSignature 的值完全一致。

    curl -X POST 'http://127.0.0.1:8080/example_domain/vertc/cstage' \
      -H 'Content-Type: application/json' \
      -d '{
        "message":"Y29udgAAAKV7CgkiRXZlbnRUaW1lIiA6IDE3NjU3Njk1MDI4NDcsCgkiUm91bmRJRCIgOiAzLAoJIlN0YWdlIiA6IAoJewoJCSJDb2RlIiA6IDUsCgkJIkRlc2NyaXB0aW9uIiA6ICJhbnN3ZXJGaW5pc2giCgl9LAoJIlRhc2tJZCIgOiAiQ2hhdFRhc2swMSIsCgkiVXNlcklEIiA6ICJIdW9zaGFuMDEiCn0=",
        "signature":"your_custom_secure_signature"
      }'
    

    预期结果:

    • curl 输出 ok。
    • 在运行 Go 服务的终端中,您将看到成功解析的日志:
    &{ChatTask01 Huoshan01 3 1765769502847 {5 answerFinish}}
    

附录

二进制消息格式

Image

参数名

类型

描述

magic number

binary

消息格式,固定为 conv

length

binary

消息长度,单位为 bytes。存放方式为大端序。

conversation_status_message

binary

消息详细信息。具体参看conversation_status_message

conversation_status_message

参数名

类型

描述

TaskId

String

智能体任务 ID。

UserID

String

说话人 UserId。

RoundID

Int64

对话轮次。从 0 开始计数。

EventTime

Int64

该事件在 RTC 服务器上发生的 Unix 时间戳 (ms)。

Stage

Stage

任务状态详细描述。

ErrorInfo

ErrorInfo

任务错误详细信息。仅当 Stage.Code0 时,会返回该字段。

Stage

参数名

类型

描述

Code

Int

状态码。

  • 0:智能体任务发生错误。
  • 1:智能体聆听中。
  • 2:智能体思考中。
  • 3:智能体说话中。
  • 4:智能体被打断。
  • 5:智能体说话完成。

Description

String

任务状态描述。

ErrorInfo

参数名

类型

描述

Code

Int

错误状态码。详细定义,请参见错误码

Reason

String

错误详细原因。

最近更新时间:2025.12.15 20:03:59
这个页面对您有帮助吗?
有用
有用
无用
无用