「原味厨房(The Culinary Lab)」——全语音 3D AI 具身交互智能私人主厨与沉浸式烹饪陪伴交互舱
「原味厨房(The Culinary Lab)」——全语音 3D AI 具身交互智能私人主厨与沉浸式烹饪陪伴交互舱
7-4原味厨房数字人-视频演示
一、项目背景与痛点
对于绝大多数家庭烹饪者而言,真正的难点往往不在“看菜谱”,而在“手上沾着面粉、锅里正冒着油时”的那一刻——你既腾不出手翻手机,也没法停下手里的活去逐字核对步骤。传统的解决方案存在明显断层:
-
静态图文菜谱:信息密度低、无法实时纠偏,火候过了才发现步骤看错。
-
普通语音助手:本质是“问答式”而非“对话式”,你问一句它答一句,炒菜中途想插话追问“现在该不该转小火”会被打断重来,节奏割裂。
-
录播类烹饪视频:无法交互,更无法根据你手边食材临场给建议。
为了还原“炉边有一位米其林主厨随时陪你做菜”的体验,本文将分享一个多模态互动数字人系统的开发实践。系统以魔珐星云(XmovAvatar)SDK 驱动一位 3D 具身交互智能数字人私人主厨 Leo(雷奥),支持全双工实时语音对话——你可以一边翻炒一边开口追问,主厨随时插话回应;配合流式字幕、背景菜品宫格氛围与火候/计时联动,构成一套沉浸式烹饪陪伴交互舱。
作为一名代码基础较弱的开发者,本次开发全程通过 AI Coding 工具辅助,结合魔珐星云 SDK 的 API,几乎由 AI 辅助完成了全部核心链路。本文将从技术架构、全双工状态机与回声规避、核心交互逻辑三个维度,分享整个开发流程与踩坑经验。
二、核心技术亮点与架构
本系统在前端和交互控流层主要实现了以下技术要点:
-
多状态机管理:系统维护了包括入驻中(boot)、待机(ready)、倾听(listening)、思考(thinking)、说话(speaking)等在内的核心交互状态,并额外引入“回声守卫”时序窗口。通过状态机的平滑切换,保障视觉资产与音频流的丝滑同步。
-
低延迟全双工打断 + 回声规避:结合前端 VAD(语音活动检测)与 SDK 的打断接口(如
interactiveIdle),实现毫秒级打断响应。真正的难点在于数字人自己的外放声会被本端麦克风采集成“回声”导致自我打断——本文给出以onVoiceStateChange("end")为真正说完信号、播报期关麦、余音窗口后再恢复采集的完整工程方案。 -
大模型流式控流:大模型(火山方舟 Response API)通过 SSE 逐 token 返回,前端实现双端流式字幕——用户回答用打字机逐字呈现,主厨回复随增量 token 实时填充气泡,降低首字响应延迟(RTTC),并借
previous_response_id实现原生多轮连续对话。 -
背景动态氛围引擎:采用 GSAP 移植的 GridMotion 菜品宫格,数字人入驻后四行图片以左右交替方向错峰滑入填充背景,并随鼠标手势视差滑动;同时联动火候指示条与厨房计时器,让“陪伴感”可视化。
三、核心功能与交互效果展示
1. 核心交互体验:随时打断
主厨正在播报做法时,用户可随时开口说话。系统通过 ASR/VAD 实时监测用户语音,一旦检测到插话,立即执行以下链路:
停止当前播报 -> 自动切换至倾听状态 -> 捕获新提问 -> 思考并流式回答 -> 播报结束后再度恢复监听,进入循环。

2. 双端流式字幕
-
用户回答:识别完成后以打字机效果逐字流出,呈现“正在聆听并复述”的自然感。
-
主厨回复:大模型 SSE 每推送一个增量 token,气泡文本即时追加,字幕与唇形/语音同步生长,而非整段突兀出现。

3. 背景菜品宫格与氛围联动
-
滑入揭示:未启动数字人时背景完全留空;主厨入驻并完全加载后,
#dish-grid整体淡入,四行菜品图各自从屏幕外(第 1、3 行从右、第 2、4 行从左)以power3.out缓动错峰滑入填满背景,末行到位后无缝接管鼠标视差滑动,两端始终超出屏幕“看不到边”。 -
视觉氛围反馈:待机/倾听态下底部呈现动态音频波形与火候指示条;提到“计时 5 分钟”时右下角计时器自动启动并倒数。

四、全双工打断与回声规避的底层控制流实现
全双工交互的核心难点在于状态流转的时序控制,而本项目最关键的踩坑是“数字人自己打断自己”——根因是 LiteSDK.speak() 的 Promise 往往在音频真正播放完之前就已 resolve,若此刻立刻重启麦克风,后半句外放声会被采集成用户回答,进而触发新一轮 speak 把当前播报打断。
解决方案:以 SDK 的 onVoiceStateChange("end")(音频真正播完)作为恢复采集的唯一信号,而非以 Promise 为准。完整控流逻辑如下:
// 核心逻辑伪代码:全双工打断 + 回声规避
function handleUserInterrupt() {
// 1. VAD 检测到用户语音活动,且当前数字人正在播报/思考
if (avatarState === 'speak' || avatarState === 'think') {
// 2. 调用 SDK 打断接口,中止当前语音 token 输出
if (LiteSDK && typeof LiteSDK.interactiveIdle === 'function') {
LiteSDK.interactiveIdle();
}
// 3. 终止在途推理、作废当前播报令牌,强制切至 'listen'
thinkingAbort.abort();
turnToken++; speakToken++;
updateAvatarState('listen');
}
}
async function speakToAvatar(text) {
isSpeaking = true;
stopRecognition(); // 播报期间关麦,避免采集到自己的声音
await LiteSDK.speak(text, true, true);
// 注意:speak 的 Promise 常提前 resolve,此处【不立即恢复麦克风】
}
// 以音频真正播放结束为准,而非 speak Promise
onVoiceStateChange = (s) => {
if (s === 'end') {
voicePlaying = false;
onAvatarVoiceEnd(); // 进入回声守卫窗口
}
};
function onAvatarVoiceEnd() {
isSpeaking = false;
echoGuardUntil = Date.now() + 1500; // 余音窗口:1.5s 内忽略任何识别结果
setTimeout(() => {
lastSpokenText = ""; // 守卫结束再清空台词,供 isEcho 比对
if (!isSpeaking && !voicePlaying) startRecognition(); // 此时才恢复聆听
}, 1500);
}
完整交互生命周期流程:
-
用户开口 -> VAD 触发打断函数(播报中则
interactiveIdle+ 关麦)。 -
状态切换 -> 状态机切至
listen,捕获用户完整表达。 -
识别完成 -> 状态机切至
think,将文本投递给大模型(带previous_response_id多轮锚点)。 -
流式返回 -> 主厨气泡随 SSE token 实时生长,状态机切至
speak,驱动唇形同步与播报(期间麦克风关闭)。 -
音频真正结束 ->
onVoiceStateChange("end")-> 回声守卫 1.5s -> 恢复监听,进入下一轮循环。
五、开发踩坑记录与解决方案
1. 编程小白如何利用 AI 工具攻克复杂 SDK?
在不熟悉复杂多媒体前端开发的情况下,利用 Cursor / Copilot 等 AI 助手是快速落地的关键。
- 技巧:不要把整个 SDK 文档直接丢给 AI。应该将魔珐星云 SDK 提供的官方
Demo 代码和核心 API 说明(如状态机字典、speak 方法入参、onVoiceStateChange 事件)提取成 Context 喂给 AI,让其定向生成状态切换与打断逻辑代码。本项目中的入驻、播报、打断、音频状态回调均由此方式完成。
2. 数字人“自己打断自己” + 回声问题
-
现象:主厨刚开口播报,后半句还没说完就被“自己”打断,循环重启麦克风又把外放声当成用户回答。
-
根因:
speak()的 Promise 在音频真正结束前就 resolve;若以此为准立即startRecognition(),余音窗口内本端 ASR 会把数字人自己的声音转写成“用户回答”,进而触发新一轮speak。 -
解决:
-
播报前
stopRecognition()关麦,onend自愈重启加!isSpeaking && !voicePlaying守卫; -
以
onVoiceStateChange("end")作为真正说完信号,而非 Promise; -
播完设 1.5s
echoGuardUntil余音窗口,窗口内handleFinalTranscript直接丢弃结果,窗口结束再恢复采集; -
守卫期内保留
lastSpokenText,用isEcho()文本比对做二次兜底。
-
3. 背景宫格被 Flex 布局压缩
-
现象:菜品图宽度被压成“高高的扁扁的”,滑动时两侧露出大片空白。
-
根因:
.gm-container是display:flex父容器的子项,未设flex-shrink:0,flex 默认把它从设定的440vw压到父级(#stage)宽度,导致整行与每张图都被横向压缩。 -
解决:给
.gm-container加flex-shrink: 0,使其保留真实440vw宽度,图片恢复原始比例,滑动时两端始终超出屏幕。
六、总结与后续演进方向
通过本次技术原型的搭建,可以看出“低门槛工具辅助 + 模块化数字人 SDK(魔珐星云)”已经可以让非资深研发快速搭建出具备多模态交互能力的应用。系统的状态机与回声规避设计灵活,极易扩展到其他垂直领域(导购、讲解、陪练等)。
下一步的优化迭代方向:
-
RAG 菜谱知识库挂载:接入私有垂直菜谱/食材库,提升主厨回答的专业度与准确率,支持“我家有 XX 食材能做什么”。
-
AEC 回声消除升级:当前以“播报期关麦”规避回声,代价是播报中无法抢话打断;后续可引入 WebRTC
MediaStreamTrack+echoCancellation,在保留插话能力的同时彻底消除回声。 -
多语种与情感识别:结合 Web Audio API 分析用户语气振幅,调整主厨回应情感,并拓展中英文切换陪伴能力。
-
移动端与离线适配:将氛围引擎与流式链路向移动端 H5 收敛,适配弱网与触屏交互。
数字人SDK部分参考官方文档——https://xingyun3d.com/?utm_campaign=daily&utm_source=juzhen
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)