当前页

实现数字人实时播报

2026-07-27

本文档用于说明如何快速集成客户端 SDK(ZEGO Express SDK)实现数字人实时播报。
与数字人视频通话不同,数字人播报是单向观看场景——即用户不和数字人进行互动,只是拉数字人播报内容进行观看。
客户端只需要登录 RTC 房间拉流,不需要采集或推流用户的音视频流。创建播报实例后,服务端可以通过 TTS 接口主动让数字人播报指定文本。
适用于数字人直播、新闻播报、活动主持和固定话术播报等场景。

与数字人视频通话的区别

对比项数字人视频通话数字人实时播报
交互方式双向,用户说话后数字人回答单向,用户仅观看数字人播报内容
适用场景AI 互动、AI 客服、数字人老师数字人直播、新闻播报
客户端是否需要采集用户音频
数字人驱动机制收到用户音频后,LLM 输出回复,通过 TTS 驱动数字人播报内容完全由服务端控制,通过 TTS 驱动数字人
创建实例接口CreateDigitalHumanAgentInstanceCreateLiveDigitalHumanAgentInstance
是否需要 user_id、user_stream_id

前提条件

  • 已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 ServerSecret(用于服务端 API 签名与 RTC Token04 生成),详情请参考 控制台 - 项目信息
  • 已联系 ZEGO 技术支持开通数字人 PaaS 服务和相关接口的权限。
  • 已获取有效的 digital_human_id(测试时可使用公共 ID:c4b56d5c-db98-4d91-86d4-5a97b507da97)。
  • 已按 业务后台快速开始指引 集成播报数字人相关服务端 API。
  • 已联系 ZEGO 技术支持获取针对 AI Agent 优化的 ZEGO Express SDK,并集成到项目中。
注意

数字人播报不需要录音权限,也不会推送本地流。若同一个应用还包含语音通话或数字人视频通话入口,其他入口仍需要按对应文档申请录音权限。

示例代码

以下是接入实时互动 AI Agent API 的业务后台示例代码,您可以参考示例代码来实现自己的业务逻辑。

以下是客户端示例代码,您可以参考示例代码来实现自己的业务逻辑。

以下视频演示了如何跑通服务端和客户端(Web)示例代码并跟智能体进行语音互动。

整体业务流程

  1. 服务端,参考业务后台快速开始文档跑通业务后台示例代码,部署好业务后台
    • 接入实时互动 AI Agent API 管理智能体。
  1. 客户端,跑通示例代码
    • 通过业务后台创建和管理智能体。
    • 集成 ZEGO Express SDK 完成实时通信。

完成以上两个步骤后即可实现观看数字人播报。

核心能力实现

集成 ZEGO Express SDK

Web quickstart 使用 zego-express-engine-webrtc。播报入口不创建音频流、不调用 startPublishingStream,因此不需要麦克风权限:

npm install zego-express-engine-webrtc
import { ZegoExpressEngine } from "zego-express-engine-webrtc";

// appID: number,从 ZEGO 控制台项目信息获取
// server: 信令服务器地址,若使用 3.7.0 及以上版本 ZEGO Express SDK,可填写控制台获取的 Server 地址或者直接填空字符串
const zg = new ZegoExpressEngine(appID, "");

以下是 Web 端常用的变量声明/配置示例:

// 从 ZEGO 控制台获取
const APP_ID = 1234567890; // AppID,数字类型
const SERVER = ""; // 信令服务器地址,3.7.0+ 可填空字符串
// 从业务后台获取
const BASE_URL = "http://your-server-host:3000"; // 业务后台地址
const ROOM_ID = "room_xxx"; // RTC 房间 ID
const USER_ID = "user_xxx"; // 用户 ID
const DIGITAL_HUMAN_ID = "c4b56d5c-db98-4d91-86d4-5a97b507da97"; // 数字人 ID
const CONFIG_ID = "web"; // Web 端使用 web

// 模块级变量,供 roomStreamUpdate / remoteCameraStatusUpdate / 退出使用
let agentStreamId = "";
let agentInstanceId = "";
const loginResult = await zg.loginRoom(roomID, token, {
    userID,
    userName,
});

if (!loginResult) {
  throw new Error("登录 RTC 房间失败");
}

当前 quickstart 的公共初始化逻辑仍会调用 checkSystemRequirements 检查 WebRTC 和麦克风能力,以兼容语音通话入口;如果您的 Web 应用只实现数字人播报,可以移除麦克风检查。

通知业务后台创建播报数字人实例

客户端调用业务后台的 POST /api/start-live-digital-human。业务后台收到请求后,会调用 ZEGO 的 CreateLiveDigitalHumanAgentInstance 接口创建播报数字人实例,接口详细参数请参考创建数字人播报实例。RTC 模式下请求体至少包含 room_iddigital_human_idconfig_id,不需要传 user_iduser_stream_id

{
  "room_id": "room_xxxxxxxx",
  "digital_human_id": "digital_human_xxxxxxxx",
  "config_id": "mobile"
}

digital_human_id 对应服务端 DigitalHuman 结构,其核心字段如下:

字段说明
digital_human_id数字人 ID,用于指定数字人形象。
encode_code编码类型,仅支持 mobile(Android/iOS)和 web(Web)。Android 与 iOS 使用 mobile,Web 使用 web

其中 Android 和 iOS 的 config_id 使用 mobile,Web 使用 webDigitalHumanConfig.EncodeCode 合法取值仅 mobileweb

业务后台在调用 ZEGO API 时,需要将 digital_human_idconfig_id 构造为 DigitalHuman 对象:

{
    "DigitalHumanId": "c4b56d5c-db98-4d91-86d4-5a97b507da97",
    "ConfigId": "mobile",
    "EncodeCode": "H264"
}

服务端成功响应中需要将以下信息返回给客户端:

字段用途
agent_instance_id调用主动 TTS 和停止实例接口
agent_stream_idRTC 房间内数字人流的 ID
agent_user_id数字人在 RTC 房间内的用户 ID
digital_human_config初始化 Android/iOS 数字人 SDK 的配置

Web 使用 fetch 直接请求业务后台。示例只传 RTC 房间 ID,因此不会传本地用户或本地流信息:

async function startLiveDigitalHuman(roomId: string) {
  const response = await fetch(`${baseURL}/api/start-live-digital-human`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
    digital_human_id: config.digitalHuman.id,
    config_id: config.digitalHuman.configId,
    room_id: roomId,
    }),
  });
  const result = await response.json();
  if (result.code !== 0) throw new Error(result.message);
  return result;
}

用户进入房间(不推流)

播报数字人只需要登录 RTC 房间并接收数字人流,客户端不需要创建本地流或调用 startPublishingStream

Web 直接登录房间,播报场景不创建音频流或推送本地流:

// 1. 从业务后台获取 Token
const tokenRes = await fetch(`${BASE_URL}/api/zego-token?userId=${USER_ID}&roomId=${ROOM_ID}`);
const { token } = await tokenRes.json();

// 2. 登录 RTC 房间
await zg.loginRoom(ROOM_ID, token, { userID: USER_ID, userName: USER_ID });

// 3. 创建播报数字人实例
const result = await startLiveDigitalHuman(ROOM_ID);
// 4. 提取并保存 agent_stream_id 和 agent_instance_id,供后续拉流、TTS 和退出使用
agentStreamId = result.agent_stream_id;
agentInstanceId = result.agent_instance_id;

初始化数字人 SDK 和自定义渲染

Android 和 iOS 需要将 ZEGO Express SDK 收到的原始视频帧与 SEI 数据传递给数字人 SDK,再由数字人 SDK 渲染数字人画面。必须在调用 startPlayingStream 之前开启自定义视频渲染。

Web 端不集成数字人 SDK,无需自定义渲染配置,直接使用 ZEGO Express SDK 播放数字人视频流。

拉取数字人流

创建实例后,客户端使用服务端返回的 agent_stream_id 拉取数字人流。不同平台 quickstart 的拉流时机略有不同:Android 在创建实例接口成功后直接拉流;iOS 和 Web 通过房间流更新回调,匹配目标流后再拉流。

监听 roomStreamUpdate,匹配服务端返回的 agentStreamId 后创建远程流视图。agentStreamId 来自创建实例接口返回的 agent_stream_id,已在登录房间后从响应中提取:

let remoteView: any = null;

zg.on(
  "roomStreamUpdate",
  async (
    roomID: string,
    updateType: "DELETE" | "ADD",
    streamList: ZegoStreamList[],
  ) => {
    if (updateType === "ADD" && streamList.length > 0) {
      for (const stream of streamList) {
        // 仅拉取数字人流,过滤房间内其他流
        if (stream.streamID !== agentStreamId) continue;
        const mediaStream = await zg.startPlayingStream(stream.streamID);
        remoteView = await zg.createRemoteStreamView(mediaStream);
        remoteView?.playAudio();
        break;
      }
    }
  },
);

// 数字人视频流由服务端推送,相机状态变为 OPEN 表示视频流已就绪,此时再播放画面
zg.on(
  "remoteCameraStatusUpdate",
  (streamID: string, status: "OPEN" | "MUTE") => {
    if (streamID === agentStreamId && status === "OPEN") {
      remoteView?.playVideo("remoteStreamView");
    }
  }
);
CDN 模式拉流

以上为 RTC 模式拉流方式。若使用 CDN 模式,客户端无需登录 RTC 房间,也不需要按上述流程拉取 RTC 流,而是直接通过通用播放器(如 HLS / FLV 播放器)拉取业务后台返回的 cdn_url 即可观看数字人播报。CDN 模式不需要集成数字人 SDK。

主动让数字人播报文本

数字人实例创建成功后,客户端调用业务后台 POST /api/send-agent-instance-tts,传入实例 ID 和文本:

{
  "agent_instance_id": "2075416950128779264",
  "text": "尊敬的开发者你好,欢迎使用 ZEGO AI Agent。"
}

text 最大长度不超过 300 个字符。还可以按业务需要传入 add_historyprioritysame_priority_option 等参数。详细说明请参考主动调用 TTS

实例生命周期

播报数字人实例在空闲(无播报任务)超过 900 秒后会自动销毁,业务侧可通过 MaxIdleTime 调整该空闲超时时间。如需长时间保活,请定期调用主动 TTS 或调大 MaxIdleTime

const response = await fetch(`${baseURL}/api/send-agent-instance-tts`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    agent_instance_id: agentInstanceId,
    text,
  }),
});
const result = await response.json();
if (result.code !== 0) throw new Error(result.message);

Web quickstart 会在播报模式下显示 TTS 输入框,并将服务端返回的 agent_instance_id 保存到页面状态。

退出房间结束播报

退出时需要停止 Agent 实例、停止拉流、退出 RTC 房间并销毁客户端 SDK。无论停止接口是否成功,都应释放 RTC 资源,避免房间和引擎残留。

async function logoutRoom() {
  await fetch(`${baseURL}/api/stop`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ agent_instance_id: agentInstanceId }),
  });
  zg.stopPlayingStream(agentStreamId);
  zg.logoutRoom(roomID);
  agentInstanceId = "";
}

播报场景没有本地音频流,不需要销毁音频采集流。

RTC 和 CDN 模式

本文以 RTC 模式为例:客户端登录房间并拉取 agent_stream_id。如果需要大规模直播,可以使用 CDN 模式:

模式创建实例参数客户端播放方式适用场景
RTCroom_idZEGO Express SDK 拉取 RTC 流低延迟、小范围互动
CDNcdn_url使用播放器拉取 CDN 流大规模直播

RTC 和 CDN 模式都使用 agent_instance_id 调用主动 TTS 和停止实例接口。CDN 模式不需要客户端登录 RTC 房间,也不需要集成数字人 SDK。CDN 拉流方式:可以用任何支持 CDN 播放的方式进行拉流,不做特殊说明。

数字人支持 RTC、CDN 拉流,如若需要让大规模的用户观看数字人播报内容,例如电商直播、直播课堂等场景,可以使用 CDN 直播模式。CDN 模式下 Web 端无需集成 ZEGO Express SDK,使用任意支持 HLS/FLV 的 Web 播放器(如 hls.js、video.js)拉取 cdn_url 即可。

监听回调

请监听 ZEGO Express SDK 的房间登录、拉流状态和错误回调,并在业务后台记录 agent_instance_idagent_stream_idrequest_id 和错误信息,便于定位创建实例、拉流或 TTS 失败原因。其中 request_id 由 ZEGO 服务端返回,是排查服务端链路问题的关键标识,请务必在出现异常时连同上述信息一起反馈给 ZEGO 技术支持。

接入测试过程中,强烈建议监听业务后台接收回调(Event 为 Exception 的事件),通过 Data.CodeData.Message 快速定位 LLM/TTS 等参数配置问题。回调与错误码详情请参考接收回调异常事件错误码

注意

如果数字人画面停留在静态图,请重点检查:数字人配置是否有效、agent_stream_id 是否正确、是否在 startPlayingStream 前开启了自定义视频渲染,以及是否将视频帧和 SEI 数据传给了数字人 SDK。

排查清单

接入过程中如遇异常,可对照以下清单逐项排查。

Web 排查清单

现象排查方向
登录房间失败检查 Token 是否有效、AppID 是否匹配;3.7.0 及以上版本 server 可填空字符串。
创建实例返回失败确认 digital_human_idconfig_id(Web 为 web)、room_id 是否正确,业务后台签名是否有效。
无画面 / 无声音roomStreamUpdate 中按 agentStreamId 过滤后再 startPlayingStream;等待 remoteCameraStatusUpdateOPEN 后再 playVideo
视频容器不显示确认 playVideo 传入的容器 ID 为 remoteStreamView(注意拼写)。
TTS 不播报确认 agent_instance_id 正确、text ≤ 300 字符、实例未因 900 秒空闲被销毁。

更多错误码请参考异常事件错误码,回调监听请参考接收回调

2026-07-27

上一篇

实现数字人视频通话

下一篇

展示字幕