广告位招商中 欢迎洽谈

开发者如何集成 D-ID Streaming API 构建实时交互式对话虚拟人

365Finds Editorial
已收录 11,430 篇 Wiki 文章

让你的 AI 用上 365 Wiki

复制这段快捷提示词,粘贴到你正在使用的 AI 对话中,然后继续提问。AI 会搜索 365 Wiki,帮你查资料、比较方案并给出建议。

下载完整 Skill

偶尔使用,快捷提示词就够了。经常使用,安装 365Wiki Skill:无需每次复制,还能更完整地研究问题、比较选择并规划下一步。没有常用工具?Gemini、Microsoft Copilot 等网页版 AI 也能使用。

365Wiki Skill

构建实时对话式视觉 AI 需要解决一个核心工程瓶颈:延迟。传统的合成视频生成管线多以异步批处理模式运行,渲染、编码并交付一个 MP4 视频文件通常需要数秒到数分钟不等。对于交互式应用场景——例如 AI 销售代表、虚拟医疗助手、客服数字人以及交互式数字化导师——数秒的延迟会彻底破坏对话流畅度并降低用户参与度。

D-ID 通过其实时流式传输基础设施解决了这一挑战,该架构将低延迟视频生成算法与 WebRTC 及 LiveKit 数据传输技术相结合。D-ID 的流式传输引擎无需在磁盘上生成完整的视频文件,而是实时渲染唇形同步的数字人视频帧,并以亚秒级延迟直接流式传输到客户端浏览器。虽然早期的实现依赖于旧版 Talks 和 Clips 流式接口(/talks/streams),但 D-ID 当前的现代架构主要围绕 D-ID Agents 框架和官方 @d-id/client-sdk 构建。

本指南将深入解析将 D-ID Streaming API 与大型语言模型(LLM)集成的完整架构管线,涵盖后端智能体配置、WebRTC 会话协商、前端媒体流绑定、对话交互模式、延迟优化策略以及额度生命周期管理。


架构概览:对话式数字人管线

实时交互式数字人应用作为一个协同循环运行,涵盖用户输入、语言推理、语音合成、面部动画以及点对点媒体传输:

+-------------+      Audio / Text      +-------------------+
|             | ---------------------> | Application Logic |
| User Client |                        | (STT / LLM / RAG) |
|  (Browser)  | <--------------------- +-------------------+
|             |     WebRTC Video / Audio         |
|             | <---------------------------+    | Text / Audio Chunks
+-------------+                             |    v
                                       +-------------------+
                                       | D-ID Streaming    |
                                       | Engine & Agents   |
                                       +-------------------+

开发者通常根据自身的基础设施需求选择以下两种集成范式之一:

  1. 托管式 D-ID Agent 工作流:D-ID 在内部统一管理 LLM 系统提示词、外部知识库(检索增强生成 / RAG)以及文本转语音(TTS)语音提供商。客户端应用使用 @d-id/client-sdk 直接连接到智能体,并通过 agentManager.chat() 发送用户提示词。
  2. 自定义后端编排工作流:开发者的后端完全掌控对话状态、用户鉴权、专有工具、向量数据库以及 LLM 调用(如 OpenAI GPT-4o、Anthropic Claude 或自托管模型)。随后后端通过 agentManager.speak() 或 REST 流式接口将生成的文本或合成音频流式传输给 D-ID,以驱动数字人动画。

步骤 1:通过 REST API 配置与预配 Agent

在建立实时流之前,开发者需要配置数字人角色形象、语音特征以及智能层。尽管可以通过 D-ID Studio 界面创建智能体,但生产环境应用通常通过 REST API 自动化这一预配过程。

创建 Agent

向 https://api.d-id.com/agents 发送 POST 请求,并附带 D-ID API 密钥进行身份验证:

curl -X POST "https://api.d-id.com/agents" \
  -H "Authorization: Basic <YOUR_BASE64_ENCODED_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "presenter": {
      "type": "clip",
      "presenter_id": "v2_public_Amber@0zSz8kflCN",
      "voice": {
        "type": "microsoft",
        "voice_id": "en-US-JennyMultilingualV2Neural"
      }
    },
    "llm": {
      "type": "openai",
      "provider": "openai",
      "model": "gpt-4o",
      "instructions": "You are an AI customer success specialist for an enterprise SaaS platform. Keep responses under two sentences, maintain an empathetic and professional tone, and guide users to relevant product features."
    }
  }'

关键配置参数

配置对象参数说明
presentertype数字人渲染类型:talk(基于照片的 V2)、clip(预渲染演播室主播 V3)或 expressive(基于 LiveKit 的 V4 数字人)。
presenterpresenter_id 或 source_urlD-ID 预置主播的标识符,或用于自定义照片数字人的公开可访问 HTTPS 图片 URL。
presenter.voicetype语音提供商引擎,常见为 microsoft(Azure Neural)或 elevenlabs。
presenter.voicevoice_id匹配提供商目录的具体语音模型标识符(例如 en-US-JennyMultilingualV2Neural)。
llmtype 与 provider原生托管补全使用 openai,外部后端路由使用 custom。
llminstructions设定数字人角色设定、行为约束和对话边界的系统指令。

API 会返回一个包含唯一 agentId 的 JSON 响应。请将该标识符保存在应用程序数据库中。

保护客户端凭据

生产环境的 Web 和移动应用切勿在客户端代码中暴露主要的 D-ID API 密钥。应当通过后端生成受限范围的 Client Key:

curl -X POST "https://api.d-id.com/agents/<AGENT_ID>/client-key" \
  -H "Authorization: Basic <YOUR_BASE64_ENCODED_API_KEY>" \
  -H "Content-Type: application/json"

在 D-ID Studio 控制面板中,通过 Allowed Domains 设置将此客户端密钥限制在生产域名内,以防止未经授权的调用。


步骤 2:建立低延迟 WebRTC 流

实时交互需要在客户端浏览器与 D-ID 渲染集群之间建立 WebRTC 对等连接。D-ID 提供了两种集成路径:自动化的 @d-id/client-sdk(强烈推荐)以及基于 REST 的直接 WebRTC 信令交互。

方式 A:通过 @d-id/client-sdk 进行客户端集成(推荐)

官方 @d-id/client-sdk 将会话协商、会话描述协议(SDP)提议/应答交换以及交互式连通建立(ICE)候选收集封装为简洁的 JavaScript 接口。

1. 安装 SDK

npm install @d-id/client-sdk

2. 初始化 AgentManager 并绑定媒体轨道

import * as did from "@d-id/client-sdk";

// DOM 元素
const videoElement = document.getElementById("avatar-video");
const statusElement = document.getElementById("connection-status");
const chatInputElement = document.getElementById("chat-input");
const sendButton = document.getElementById("send-btn");

let agentManager = null;

async function initializeAvatar() {
  const agentId = "agt_xxxxxxxxxxxxxxxx";
  const clientKey = "YOUR_CLIENT_KEY";

  agentManager = await did.createAgentManager(agentId, {
    auth: {
      type: "key",
      clientKey: clientKey
    },
    callbacks: {
      // 接收来自 D-ID WebRTC Peer 的已附加媒体流
      onSrcObjectReady(mediaStream) {
        videoElement.srcObject = mediaStream;
        videoElement.play().catch((err) => console.error("Video autoplay error:", err));
      },
      // 监听连接状态变化:connecting、connected、disconnected、closed
      onConnectionStateChange(state) {
        statusElement.textContent = `Status: ${state}`;
        console.log("WebRTC Connection State:", state);
      },
      // 处理收到的对话轮次
      onNewMessage(messages) {
        const latest = messages[messages.length - 1];
        console.log(`[${latest.role}]: ${latest.content}`);
      },
      // 监控数字人说话生命周期状态
      onVideoStatusChange(status) {
        console.log("Avatar Video Status:", status); // 例如 "playing", "idle"
      },
      onError(error, errorData) {
        console.error("D-ID Agent Error:", error, errorData);
      }
    }
  });

  // 连接 WebRTC 会话
  await agentManager.connect();
}

initializeAvatar().catch(console.error);

方式 B:底层手动 WebRTC 信令握手

对于无头环境、非浏览器客户端(如原生移动应用或嵌入式设备)或旧版系统,开发者可以直接调用 D-ID 的 REST 接口执行 WebRTC 握手:

  1. 初始化流会话: 向 https://api.d-id.com/agents/{agentId}/streams(或旧版 /talks/streams)发送 POST 请求。D-ID 返回:

    • id:唯一的流会话 ID。
    • session_id:会话跟踪标识符。
    • offer:由 D-ID 的 WebRTC 媒体服务器生成的 SDP offer。
    • ice_servers:用于 NAT 穿透的 STUN 和 TURN 服务器凭据列表。
  2. 初始化本地 RTCPeerConnection: 客户端创建一个配置了 D-ID ice_servers 的 RTCPeerConnection 实例:

    const pc = new RTCPeerConnection({ iceServers: response.ice_servers });
    
  3. 设置远程描述并创建本地应答:

    await pc.setRemoteDescription(new RTCSessionDescription(response.offer));
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    
    // 将 SDP Answer 提交回 D-ID
    await fetch(`https://api.d-id.com/agents/${agentId}/streams/${response.id}/sdp`, {
      method: "POST",
      headers: {
        "Authorization": `Basic ${API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        answer: answer,
        session_id: response.session_id
      })
    });
    
  4. 交换 ICE 候选: 监听客户端对等连接上的 onicecandidate 事件,并将每个候选转发至 D-ID 的 ICE 接口:

    pc.onicecandidate = (event) => {
      if (event.candidate) {
        fetch(`https://api.d-id.com/agents/${agentId}/streams/${response.id}/ice`, {
          method: "POST",
          headers: {
            "Authorization": `Basic ${API_KEY}`,
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            candidate: event.candidate.candidate,
            sdpMid: event.candidate.sdpMid,
            sdpMLineIndex: event.candidate.sdpMLineIndex,
            session_id: response.session_id
          })
        });
      }
    };
    
  5. 接收媒体轨道: 当媒体轨道到达时,将远程流绑定到 DOM:

    pc.ontrack = (event) => {
      videoElement.srcObject = event.streams[0];
    };
    

步骤 3:对话交互:chat() 与 speak()

一旦 WebRTC 会话处于活跃状态,开发者可以使用 SDK 提供的两种核心方法触发数字人动画。

模式 1:自主对话轮次(chat)

如果智能体配置了内置 LLM 逻辑,可直接向智能体的对话线程发送文本消息:

// 用户通过 UI 提交提示词
async function handleUserSubmit(userText) {
  if (!agentManager) return;

  // 将用户消息发送给智能体;智能体查询 LLM、生成语音并流式传输视频
  await agentManager.chat(userText);
}

D-ID 智能体会自动处理用户轮次跟踪、LLM 推理、TTS 生成和视频合成,并在解析 token 和消息时触发 onNewMessage 回调。

模式 2:自定义后端编排(speak)

当应用逻辑需要专有工作流时——例如针对企业数据库的多轮 RAG 查询、带工具调用的 LangChain 智能体或自定义 LLM 接口——开发者可以使用 speak() 方法。这允许后端独立生成响应,并指示数字人朗读特定内容。

发送文本输入

// 指示数字人使用智能体配置的 TTS 语音朗读任意文本
await agentManager.speak({
  type: "text",
  input: "Welcome back, Sarah. I have pulled your quarterly analytics report."
});

发送预合成音频

对于使用专用语音引擎(如自定义克隆声音或定制语音模型)的应用,开发者可以直接传入公开可访问的 HTTPS 音频 URL:

// 数字人嘴型和面部表情与所提供的音频同步运动
await agentManager.speak({
  type: "audio",
  audio_url: "https://storage.yourdomain.com/audio/response_chunk_01.mp3"
});

生产环境延迟优化与性能策略

在交互式对话 AI 中,人类对延迟的容忍度极低;超过 1,000 到 1,500 毫秒的对话停顿就会显得不自然。实现流畅的对话需要优化管线的每个阶段。

1. 连接预热

WebRTC 连接建立过程(SDP 交换、STUN/TURN 候选发现以及 ICE 连通性检查)通常需要 800 毫秒到 2,500 毫秒不等,具体取决于网络环境。

2. 针对长 LLM 响应的分块流式传输

在调用 speak() 之前等待 LLM 生成完整的多句段落会引入显著的延迟(首字时间 Time-to-First-Token 加上完整生成时间)。

为了减少感知延迟:

3. 打断与插话处理

自然的对话需要允许用户在数字人说话中途进行打断。在 D-ID 的现代流式架构中,通过流畅的流式控制原生支持打断能力:

// 检测到数字人正在说话时用户开口发声
function onUserSpeechDetected() {
  if (agentManager) {
    // 中断当前的语音播放并将数字人重置为空闲聆听状态
    agentManager.interrupt();
  }
}

当触发打断事件时,D-ID 会截断服务端活跃的语音队列并停止视频传输,确保数字人不会继续覆盖用户的声音。

4. 基于 LiveKit 的表达型数字人(V4)

对于高度重视自然临场感的应用,D-ID 的 V4 Expressive Avatars 使用 LiveKit 传输替代了标准的点对点 WebRTC。表达型数字人在对话轮次之间保持持续的空闲动作(微妙的眨眼、头部微动和呼吸起伏),消除了早期数字人引擎中常见的画面定格感。


资源生命周期管理与计费成本控制

在大规模部署实时视频数字人时,必须严格遵守会话销毁规则和额度核算要求。

1. 优雅关闭会话

未正常关闭的 WebRTC 会话会持续消耗服务器资源,并可能导致额度意外耗尽。请务必在组件卸载和窗口关闭事件中实现显式断开逻辑:

// 窗口关闭时清理会话
window.addEventListener("beforeunload", () => {
  if (agentManager) {
    agentManager.disconnect().catch(console.error);
  }
});

// 在单页面应用中清理(React / Vue / Svelte 卸载阶段)
function cleanupAvatarSession() {
  if (agentManager) {
    agentManager.disconnect();
    agentManager = null;
  }
}

对于 REST 实现,请在会话终止时向 https://api.d-id.com/agents/{agentId}/streams/{streamId} 发送 DELETE 请求。

2. 额度消耗与 15 秒取整规则

D-ID 会直接从账户的统一定额分钟数(在 Creative Reality™ Studio 和 API 之间共享)中扣除视频生成用量。

3. 空闲超时与非活动保护

为了防范用户保持浏览器标签页打开而造成的孤立会话,建议实现非活动计时器。若 90 至 120 秒内未发生用户交互,可提示用户或使用 agentManager.disconnect() 自动断开 WebRTC 连接。


集成清单汇总

阶段核心操作推荐工具 / 端点
预配配置创建具有语音、角色设定和 LLM 指令的智能体POST /agents
安全防护签发带域名白名单限制的受限客户端凭据POST /agents/{agentId}/client-key
连接建立建立 WebRTC 对等会话并绑定 <video> 流@d-id/client-sdk(agentManager.connect())
交互通信发送对话提示词或外部 LLM 文本分块agentManager.chat() 或 agentManager.speak()
体验优化支持用户插话打断与后台连接预热麦克风活动时调用 agentManager.interrupt()
生命周期在页面退出或空闲超时后关闭 WebRTC 流agentManager.disconnect() / DELETE /streams/{id}

通过将 D-ID 的实时流式传输引擎与结构化的 LLM 提示词编排及客户端 WebRTC 生命周期管理相结合,开发团队能够构建并在 Web 与移动平台上交付具备企业级性能、反应敏捷且表达自然的对话式 AI 数字人。