一、認知顛覆:撕下大模型與傳統數位人的「串流假象」
隨著 DeepSeek、Qwen 等國產大模型以極高的推理能力風靡全球,我們正在見證 AI 認知能力的巔峰。然而一個尷尬的現實無法迴避:大模型的能力被死死困在了「純文字」的對話框裡。 在傳統的 ChatBot 互動範式下,大模型是一個「看得見摸不著的幕後智者」。面對冷冰冰的吐字,使用者感受到的是極具距離感的「機器感」。沒有眼神的交流,沒有情緒的共鳴,沒有肢體的表達。
為了解決這個問題,市場上出現了很多將「大模型 + TTS 語音 + 數位人影片串流」拼接的方案。但這種拼湊型方案在底層邏輯、技術弊端及使用者感受上面臨著巨大的限制:
傳統數位人雖具備基礎互動能力,但受雲端影片串流架構制約,互動體驗生硬、回應延遲高,難以勝任下一代人機互動場景。要打破這種困局,大模型必須擁有真正的 AI 具身智慧體表現層。

如何讓數位人真正具備即時互動的「具身」能力?魔珐星雲給出了硬核的解法。作為具身智慧數位人開放平台,魔珐科技自研的立體 3D 多模態大模型搭配自研參數流架構,突破了傳統雲端影片串流渲染高算力、高延遲的產業瓶頸。
魔珐星雲的核心技術優勢在於其獨創的自研參數流架構搭配 AI 端渲和解算

想像一個傳統的智慧文旅、飯店大廳或景區導覽場景:現在的智慧大螢幕大多只是掛著一個類似「網頁版說明書」的輸入框,冷清且無人問津。
當我們引入魔珐星雲的 AI 具身智慧數位人 方案,傳統的顯示大螢幕將完成一次顛覆性的「具身智慧」升級:
螢幕上出現的是一個充滿熱情、擁有細膩微表情、眼神能與你即時對視的 3D 專屬導遊。當你疲憊地走到大螢幕前詢問:「附近有什麼好玩好吃的呀?」,大模型在飛速思考的同時,導遊就已經帶著親切的微笑、配合著自然的肢體動作,如同老朋友般流利地為你解說起來。
接下來,我們將不借助任何繁瑣的後端伺服器,僅透過純前端一個 HTML 檔案,快速跑通這個具有劃時代意義的具身智慧互動 Demo。
為了降低開發門檻,我們捨棄了複雜的 FastAPI 或 Node.js 後端中轉架構,直接在前端使用標準的 Server-Sent Events (SSE) 串流解析大模型文字,並透過魔珐官方最新的 XmovAvatar SDK 驅動 3D 軀殼。
先準備好大模型和魔珐星雲 3D 應用的設定:這裡我是用 deepseek 作為大模型底座,這個自己去 deepseek 的平台建立 API 取得 key 就 OK 了,這裡就不贅述了。
接下來進入[魔珐星雲平台](全球領先的具身智慧 3D 數位人開放平台 - 魔珐星雲),建立一個具身智慧應用,選擇形象、場景、音色、表演等等細節

之後取得 1. App ID:應用的唯一識別碼(用於 SDK appId 欄位) 2. App Secret:應用密鑰(用於 SDK appSecret 欄位)

在本機目錄新建一個 index.html 檔案,將以下完整程式碼貼上去(記得更換你的魔珐星雲 ID 和 Secret,以及大模型的 API key):
HTML 体验AI代码助手 代码解读复制代码
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DeepSeek × 魔珐星雲 3D 具身智慧導遊</title>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://media.xingyun3d.com/xingyun3d/general/litesdk/[email protected]"></script>
<style>
background: linear-gradient(135deg, #1e293b, #0f172a);
}
</style>
</head>
<body class="bg-slate-900 text-slate-100 min-h-screen flex flex-col items-center justify-center p-4 md:p-8">
<div class="w-full max-w-4xl bg-slate-800 rounded-2xl shadow-2xl border border-slate-700 overflow-hidden flex flex-col md:flex-row h-[750px]">
<div class="w-full md:w-1/2 relative flex flex-col" id="avatar-container">
<div id="sdk_canvas" class="w-full h-full"></div>
<div id="loading-tips" class="absolute inset-0 flex flex-col items-center justify-center bg-slate-950/80 p-4 text-center">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mb-4"></div>
<p class="text-sm text-slate-300">3D 智慧體正在降臨現實軀殼...</p>
<p class="text-xs text-slate-500 mt-2">首次載入需下載 3D 材質,請耐心等待</p>
</div>
<div class="absolute top-4 left-4 bg-slate-900/60 backdrop-blur-sm px-3 py-1 rounded-full text-xs flex items-center gap-2 border border-slate-700">
<span class="h-2 w-2 rounded-full bg-emerald-500 animate-pulse"></span>
<span id="status-text">3D 軀殼未就緒</span>
</div>
</div>
<div class="w-full md:w-1/2 flex flex-col p-6 bg-slate-850 border-t md:border-t-0 md:border-l border-slate-700">
<div class="mb-4">
<h1 class="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-emerald-400">
DeepSeek × 魔珐星雲
</h1>
<p class="text-xs text-slate-400">具身智慧 3D 互動流動 Demo</p>
</div>
<div id="chat-output" class="flex-1 overflow-y-auto bg-slate-950 rounded-xl p-4 border border-slate-800 space-y-4 mb-4 text-sm scrollbar-thin">
<div class="text-slate-400 italic text-center text-xs py-2">
提示:請確認程式碼設定區已填寫您的完整憑證
</div>
</div>
<div class="space-y-2">
<div class="flex gap-2">
<input type="text" id="user-input" placeholder="輸入你想問本地導遊的問題..."
class="flex-1 bg-slate-950 border border-slate-700 rounded-xl px-4 py-3 text-sm focus:outline-none focus:border-blue-500 transition-colors">
<button id="send-btn" class="bg-blue-600 hover:bg-blue-500 px-5 py-3 rounded-xl text-sm font-medium transition-all shadow-lg active:scale-95">
送出
</button>
</div>
<button id="stop-btn" class="w-full bg-slate-700 hover:bg-rose-900 text-slate-300 hover:text-white py-2 rounded-xl text-xs font-medium transition-all border border-slate-600 hover:border-rose-700">
🛑 緊急打斷數位人發言
</button>
</div>
</div>
</div>
<script>
// ==========================================
// 1. 核心帳號設定區
// ==========================================
const CONFIG = {
mofa: {
appId: "從魔珐星雲應用取得",
appSecret: "從魔珐星雲應用取得",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa/session"
},
deepseek: {
apiKey: "這裡寫大模型API key",
apiUrl: "https://api.deepseek.com/v1/chat/completions",
systemPrompt: "你是一個名叫做‘小溫’的生動溫暖的數位人導遊。你的語言風格親切、溫暖,就像鄰家大姊姊一樣,富有畫面感和感染力。回答控制在80字以內,極其適合口語表達,絕對不要使用長篇大論、機械的分點列表或程式碼區塊。"
}
};
let mofaSdk = null;
let isFirstSentence = true;
let textBuffer = "";
const punctReg = /[。!?;;!?]/;
// ==========================================
// 2. 初始化 XmovAvatar 數位人
// ==========================================
function initMofaAvatar() {
// 安全守衛:校驗全域 XmovAvatar 類是否存在
if (typeof XmovAvatar === 'undefined') {
console.error("SDK 腳本未成功載入,請檢查網路連結。");
return;
}
// 實例化官方核心類
mofaSdk = new XmovAvatar({
containerId: '#sdk_canvas',
appId: CONFIG.mofa.appId,
appSecret: CONFIG.mofa.appSecret,
gatewayServer: CONFIG.mofa.gatewayServer,
onMessage: function(msg) {
console.log("SDK 收到通知:", msg);
}
});
// 執行官方標準的初始化方法
mofaSdk.init({
onDownloadProgress: (progress) => {
console.log("資源下載進度:", progress + "%");
document.getElementById('status-text').innerText = 正在下載材質: ${progress}%;
}
}).then(() => {
// 初始化 Promise 成功回應後隱藏載入層
console.log("3D 渲染就緒!");
document.getElementById('loading-tips').style.display = 'none';
const statusEl = document.getElementById('status-text');
statusEl.innerText = "3D 具身軀殼已就緒";
statusEl.classList.replace('text-slate-400', 'text-emerald-400');
}).catch((err) => {
console.error("3D 初始化失敗:", err);
document.getElementById('status-text').innerText = "3D 初始化異常";
});
}
// 確保頁面資源完全載入完後再實例化
window.addEventListener('load', initMofaAvatar);
// ==========================================
// 3. 串流斷句驅動
// ==========================================
function processStreamText(textChunk, isFinal = false) {
textBuffer += textChunk;
let match;
while ((match = punctReg.exec(textBuffer)) !== null) {
const breakIndex = match.index + 1;
const sentence = textBuffer.substring(0, breakIndex).trim();
textBuffer = textBuffer.substring(breakIndex);
if (sentence.length > 0) {
driveAvatarSpeak(sentence, false);
}
}
if (isFinal && textBuffer.trim().length > 0) {
driveAvatarSpeak(textBuffer.trim(), true);
textBuffer = "";
}
}
function driveAvatarSpeak(text, isEnd) {
if (!mofaSdk) return;
console.log([驅動聲音] isStart=${isFirstSentence}, isEnd=${isEnd}, 文本: ${text});
mofaSdk.speak(text, isFirstSentence, isEnd);
if (isFirstSentence) {
isFirstSentence = false;
}
}
// ==========================================
// 4. 大模型 SSE 串流互動
// ==========================================
async function handleSendMessage() {
const inputEl = document.getElementById('user-input');
const outputEl = document.getElementById('chat-output');
const query = inputEl.value.trim();
if (!query) return;
inputEl.value = "";
textBuffer = "";
isFirstSentence = true;
outputEl.innerHTML += <div class="text-right"><span class="bg-blue-600 text-white inline-block px-3 py-2 rounded-xl rounded-tr-none max-w-[85%] text-left"><b>你:</b>${query}</span></div>;
const aiBubbleContainer = document.createElement('div');
aiBubbleContainer.className = "text-left";
const aiBubble = document.createElement('span');
aiBubble.className = "bg-slate-800 border border-slate-700 text-slate-100 inline-block px-3 py-2 rounded-xl rounded-tl-none max-w-[85%]";
aiBubble.innerHTML = <b>小溫:</b>;
aiBubbleContainer.appendChild(aiBubble);
outputEl.appendChild(aiBubbleContainer);
outputEl.scrollTop = outputEl.scrollHeight;
try {
const response = await fetch(CONFIG.deepseek.apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${CONFIG.deepseek.apiKey}
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [
{ role: "system", content: CONFIG.deepseek.systemPrompt },
{ role: "user", content: query }
],
stream: true
})
});
if (!response.ok) throw new Error(HTTP 異常: ${response.status});
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
while (true) {
const { done, value } = await reader.read();
if (done) {
processStreamText("", true);
break;
}
const chunkStr = decoder.decode(value, { stream: true });
const lines = chunkStr.split('\n');
for (let line of lines) {
line = line.trim();
if (!line || line === 'data: [DONE]') continue;
if (line.startsWith('data:')) {
try {
const jsonStr = line.replace('data:', '').trim();
const parsed = JSON.parse(jsonStr);
const token = parsed.choices[0]?.delta?.content || "";
if (token) {
aiBubble.innerHTML += token;
outputEl.scrollTop = outputEl.scrollHeight;
processStreamText(token, false);
}
} catch (err) {}
}
}
}
} catch (error) {
console.error(error);
aiBubble.innerHTML += <span class="text-rose-400"><br>[資料連線異常]</span>;
}
}
// ==========================================
// 5. 控制綁定
// ==========================================
document.getElementById('send-btn').addEventListener('click', handleSendMessage);
document.getElementById('user-input').addEventListener('keydown', (e) => {
if (e.key === 'Enter') handleSendMessage();
});
document.getElementById('stop-btn').addEventListener('click', () => {
if (mofaSdk) {
mofaSdk.interactiveIdle();
textBuffer = "";
isFirstSentence = true;
document.getElementById('chat-output').innerHTML += <div class="text-center italic text-amber-500 text-xs py-1">⚠️ 3D 智慧體已被打斷</div>;
}
});
</script>
</body>
</html>
等待片刻即可載入成功

來看看我們的成果吧

這樣的美女導遊誰看了不迷糊呢

### 4.2 官方 SDK 功能詳解與段落程式碼深度分析
透過 AI Coding 工具加速完成核心邏輯後,我們來逐個剖析魔珐星雲官方最新輕量級 SDK 運作的底層密碼。
#### A. 3D 容器實例化與雲端解算握手
大模型的感知訊號想要接入 3D 軀殼,首先需要建立一個安全的雙向握手。
Plain 体验AI代码助手 代码解读复制代码// 核心片段:類的實例化與設定
mofaSdk = new XmovAvatar({
containerId: '#sdk_canvas', // 傳入承載數位人的盒子選擇器appId: CONFIG.mofa.appid, // 權限驗證憑證appSecret: CONFIG.mofa.appSecret,
gatewayServer: CONFIG.mofa.gatewayServer, // 雲端解算服務路徑onMessage: (message) => { console.log(message); }
});
> ⚙️ **技術拆解:**
>
> 我們在初始化設定時傳入的 `containerId` 具有決定性作用。SDK 內部會讀取對應的 DOM 元素,自動計算其寬高比並自適應拉起一個高畫質的 WebGL 畫布。魔珐的串流傳輸閘道 `gatewayServer` 必須使用 `ttsa` 服務路徑,這是魔珐星雲特有的 Text-to-Speech + Animation 端到端參數解算協議,只有這樣雲端才會吐出控制 3D 數位人骨架與嘴型的輕量化參數,而不是笨重高延遲的影片畫面流。
#### B. 非同步串流文字的即時並行驅動
為了解決「大模型全部生成完才開口說話」的數秒尷尬空白期,我們開發了專門的並行管道。當大模型剛開始吐字,正規表示式捕捉到第一個結束標點(如「!」或「。」)時,這一小段完整的語義文字將立刻被送入發音佇列:
Plain 体验AI代码助手 代码解读复制代码function driveAvatarSpeak(text, isEnd) {
if (!mofaSdk) return;
// 嚴格呼叫官方底層控制方法:speak(ssml, is_start, is_end)
mofaSdk.speak(text, isFirstSentence, isEnd);
if (isFirstSentence) {
isFirstSentence = false; // 首句完成打通後,後續追加流的 start 標誌置為假
}
}
> ⚙️ **技術拆解:**
>
> 對齊官方文件 `speak` 方法內部有極其精密的參數邊界控制:
>
> - **啟動句** (`is_start=true, is_end=false`):通知雲端數位人進入發音過渡,並無縫切入第一句動作。
> - **串流追加句** (`is_start=false, is_end=false`):在第一句還在端側播放的期間,後面的聲音流參數在背景源源不斷地靜默串流堆疊。
> - **結束尾句** (`is_start=false, is_end=true`):標誌整段大模型意圖表述完畢,虛擬人平穩回到待機互動迴圈。
#### C. 「有機互打斷」狀態機的優雅實現
在具身人機互動場景中,「隨叫隨停」是檢驗智慧體真實互動性的硬指標。如果虛擬人正在長篇大論,使用者強行打字插話,若沒有中斷機制,多層聲音在雲端層疊會導致音軌崩潰。

Plain 体验AI代码助手 代码解读复制代码// 綁定按鈕:觸發緊急打斷
mofaSdk.interactiveIdle();
> ⚙️ **技術拆解:**
>
> 魔珐星雲 SDK 絕非簡單的影片播放容器,它在本地維護著一個精密的狀態機。呼叫官方標準的 `interactiveIdle()` 方法,能夠直接命令端側及雲端渲染管線**瞬間清空未播放完的參數流快取**,並讓數位人強制從播放說話狀態無縫過渡,優雅切回 `interactive_idle`(有機待機互動)狀態,完美避開音軌重疊,實現了極其自然的雙向即時交談。
五、運轉與避坑指南
----------
1. **不要直接雙擊執行**:由於程式碼直接引入了魔珐的線上 WebGL 渲染腳本及請求了外部大模型服務,如果直接雙擊開啟 `index.html` 可能會因瀏覽器的本地安全策略(`file://` 協議)導致載入崩潰。請在專案目錄下使用 VS Code 的 **Live Server** 外掛點擊右下角 `Go Live` 執行,或者使用本機命令快速啟動本機微型伺服器:

1.
Plain 体验AI代码助手 代码解读复制代码python -m http.server 8000
1. 然後用瀏覽器訪問 `http://localhost:8000` 即可完美運作。
2. **生產環境跨域(CORS)與密鑰防護提示**:本篇教學由於是極簡的技術徵文評測展示,所以將大模型的 `apiKey` 直接硬編碼在前端 JS 中。在實際商業專案落地(例如真實的飯店大螢幕)時,**強烈建議把大模型的 Fetch 請求以及魔珐星雲的身分驗簽移到企業後端**進行中轉,以防前端程式碼被反編譯導致企業憑證外洩。
結語
--
大模型的技術迭代,其終極形態不應僅停留在文字層面的吞吐,更應該走向擁有真實情感、敏捷互動的**具身智慧時代**。魔珐星雲用強大的自研端側渲染與參數流處理技術,成功打破了傳統 3D 渲染的頻寬與延遲枷鎖。
透過今天這個僅用單前端檔案跑通的輕量級 Demo,我們真切感受到了國產大模型「高智商大腦」與魔珐星雲「高保真 3D 軀殼」融合後散發出的迷人魅力。一個真正有溫度、能對視、回應快於 500ms 的 AI 具身智慧體時代,大幕已啟。
👉\[魔珐星雲平台\]([全球領先的具身智慧 3D 數位人開放平台 - 魔珐星雲](https://link.juejin.cn?target=https%3A%2F%2Fxingyun3d.com%2F%3Futm_campaign%3Ddaily%26utm_source%3DjixinghuiKoc155%26utm_medium%3D%26utm_term%3D%26utm_content%3D))
---
原文出處:https://juejin.cn/post/7649738148373823529