構建即時對話式視覺 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)整合的完整架構流程,涵蓋後端 Agent 配置、WebRTC 工作階段協商、前端媒體串流繫結、對話互動模式、延遲最佳化策略以及額度生命週期管理。
架構概觀:對話式數位人流程
即時互動式數位人應用程式作為一個協同迴圈運作,涵蓋使用者輸入、語言推理、語音合成、面部動畫以及點對點媒體傳輸:
+-------------+ Audio / Text +-------------------+
| | ---------------------> | Application Logic |
| User Client | | (STT / LLM / RAG) |
| (Browser) | <--------------------- +-------------------+
| | WebRTC Video / Audio |
| | <---------------------------+ | Text / Audio Chunks
+-------------+ | v
+-------------------+
| D-ID Streaming |
| Engine & Agents |
+-------------------+
開發者通常根據自身的基礎架構需求選擇以下兩種整合範式之一:
- 代管型 D-ID Agent 工作流程:D-ID 在內部統一管理 LLM 系統提示詞、外部知識庫(檢索增強生成 / RAG)以及文字轉語音(TTS)語音提供商。用戶端應用程式使用
@d-id/client-sdk直接連線至 Agent,並透過agentManager.chat()發送使用者提示詞。 - 自訂後端協調工作流程:開發者的後端完全掌握對話狀態、使用者驗證、專有工具、向量資料庫以及 LLM 呼叫(例如 OpenAI GPT-4o、Anthropic Claude 或自託管模型)。隨後後端透過
agentManager.speak()或 REST 串流端點將生成的文字或合成音訊串流傳輸至 D-ID,以驅動數位人動畫。
步驟 1:透過 REST API 佈建與設定 Agent
在建立即時串流之前,開發者需要配置數位人角色形象、語音特徵與智慧層。儘管可以透過 D-ID Studio 介面建立 Agent,但正式環境應用程式通常透過 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."
}
}'
關鍵配置參數
| 設定物件 | 參數 | 說明 |
|---|---|---|
presenter | type | 數位人渲染類型:talk(基於相片的 V2)、clip(預渲染攝影棚主持人 V3)或 expressive(基於 LiveKit 的 V4 數位人)。 |
presenter | presenter_id 或 source_url | D-ID 預設主持人的識別碼,或用於自訂相片數位人的公開可存取 HTTPS 圖片 URL。 |
presenter.voice | type | 語音提供商引擎,常見為 microsoft(Azure Neural)或 elevenlabs。 |
presenter.voice | voice_id | 符合提供商目錄的特定語音模型識別碼(例如 en-US-JennyMultilingualV2Neural)。 |
llm | type 與 provider | 原生託管完成使用 openai,外部後端路由使用 custom。 |
llm | instructions | 設定數位人角色設定、行為限制與對話邊界的系統指令。 |
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 設定將此 Client Key 限制在正式網域內,以防止未經授權的使用。
步驟 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 端點的已連結媒體串流
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 握手:
-
初始化串流工作階段: 向
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 伺服器憑證清單。
-
初始化本地
RTCPeerConnection: 用戶端建立配置了 D-IDice_servers的RTCPeerConnection實例:const pc = new RTCPeerConnection({ iceServers: response.ice_servers }); -
設定遠端描述並建立本機應答:
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 }) }); -
交換 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 }) }); } }; -
接收媒體軌道: 當媒體軌道到達時,將遠端串流繫結至 DOM:
pc.ontrack = (event) => { videoElement.srcObject = event.streams[0]; };
步驟 3:對話互動:chat() 與 speak()
一旦 WebRTC 工作階段處於啟動狀態,開發者可以使用 SDK 提供的兩種核心方法觸發數位人動畫。
模式 1:自主對話輪次(chat)
若 Agent 配置了內建 LLM 邏輯,可直接向 Agent 的對話執行緒發送文字訊息:
// 使用者透過 UI 提交提示詞
async function handleUserSubmit(userText) {
if (!agentManager) return;
// 將使用者訊息發送給 Agent;Agent 查詢 LLM、生成語音並串流傳輸視訊
await agentManager.chat(userText);
}
D-ID Agent 會自動處理使用者輪次追蹤、LLM 推理、TTS 生成與視訊合成,並在解析 token 與訊息時觸發 onNewMessage 回呼。
模式 2:自訂後端協調(speak)
當應用程式邏輯需要專有工作流程時——例如針對企業資料庫的多輪 RAG 查詢、具備工具呼叫的 LangChain Agent 或自訂 LLM 端點——開發者可以使用 speak() 方法。這允許後端獨立生成回應,並指示數位人說出特定內容。
發送文字輸入
// 指示數位人使用 Agent 配置的 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 毫秒不等,具體取決於網路環境。
- 反模式:僅在使用者提交第一個查詢後才觸發
agentManager.connect()。 - 最佳實踐:在使用者開啟應用程式畫面、聚焦聊天輸入框或完成身分驗證時,立即在背景預熱 WebRTC 連線。當使用者發送第一則訊息時,數位人已處於連線狀態並可立即渲染回應。
2. 針對長 LLM 回應的分塊串流傳輸
在呼叫 speak() 之前等待 LLM 生成完整的多句段落會引入顯著的延遲(首字時間 Time-to-First-Token 加上完整生成時間)。
為了減少體感延遲:
- 在後端對 LLM 的 Server-Sent Events(SSE)token 串流進行緩衝。
- 在自然句子邊界處(例如
.、?、!,或全形標點。、?、!)切分接收到的文字。 - 立即將第一句分發至 D-ID,同時 LLM 繼續生成後續句子。
- 排隊發送後續句子以保持連續不間斷的語音輸出。
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 之間共用)中扣除視訊生成用量。
- 15 秒進位區間:透過 Streaming API 生成的視訊時長按每次請求無條件進位至最接近的 15 秒倍數。例如,生成一段 4 秒的語音回應將消耗 15 秒的 API 視訊額度。
- 最佳化建議:為了最大化成本效益,應避免將極短的單字確認(例如「Yes」、「好的」、「收到」)作為獨立的
speak()請求發送。可將簡短的肯定短語與後續指示結合,或依賴文字 UI 指示器呈現微確認。
3. 閒置逾時與非活動保護
為了防範使用者保持瀏覽器分頁開啟而產生的孤立工作階段,建議實作非活動計時器。若 90 至 120 秒內未發生使用者互動,可提示使用者或使用 agentManager.disconnect() 自動中斷 WebRTC 連線。
整合檢核表摘要
| 階段 | 核心操作 | 建議工具 / 端點 |
|---|---|---|
| 佈建配置 | 建立具備語音、角色設定與 LLM 指令的 Agent | POST /agents |
| 安全防護 | 核發具備網域白名單限制的受限 Client Key | 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 數位人。