魔珐星云实战:从零打造一个会说话的 3D 数字人应用

魔珐星云体验链接:https://xingyun3d.com?utm_campaign=daily&utm_source=jixinghuiKoc10

作为一名开发者,我最近体验了魔珐科技推出的魔珐星云具身智能平台。这个平台的核心理念很有意思:让 AI 不再只是冷冰冰的文字输出,而是拥有"身体"——能表达、会互动的 3D 数字人。魔珐星云正是通过其六大核心能力,以及“文生 3D 多模态动作大模型”“AI 端渲与结算”等创新技术,一举打破了 3D 数字人生成的“质量、成本、延时不可能三角”,为具身智能的大规模商业应用奠定了基础。在实际上手后,我发现这套 SDK 确实做到了"开箱即用",整个开发过程比预想中顺畅很多。

平台初体验:配置比写代码还简单

第一步:创建具身驱动应用

打开魔珐星云平台,注册登录后进入应用中心。整个平台的 UI 设计简洁明了,没有冗余的选项。点击"创建应用",创建一个应用。

接下来是配置环节。平台提供了三个核心配置项:

  1. 选择角色

平台内置了多个高质量的 3D 数字人角色,每个角色的建模质量都很高。我选择了一个看起来专业亲和的女性角色。值得一提的是,这些角色不是简单的 3D 模型,而是经过精心调优的,表情和动作都很自然。

  1. 选择音色

音色库也挺丰富,涵盖了不同年龄、性别、风格的声音。每个音色都可以试听,我选了一个温和专业的女声。试听后发现,这不是机械的 TTS 合成音,而是带有情感起伏的自然语音。

  1. 选择表演风格

这是个很细节的功能——你可以设定数字人的"表演风格",比如专业、亲和、活泼等。这会影响数字人说话时的肢体语言和表情幅度。我选择了"专业亲和"风格。

配置完成后,系统会生成两个关键凭证:App IDApp Secret。这就像是你的应用钥匙,后续 SDK 开发都要用到。整个配置过程不到 5 分钟,比我想象中简单太多。

重要提醒:这三项配置缺一不可。我一开始只选了角色和音色,忘了选表演风格,结果初始化时一直报"不支持的配置"错误。确保三项都选上,并且保存成功后再进行下一步。

SDK 开发:真正的"十分钟上手"

准备工作

拿到 App ID 和 App Secret 后,就可以开始写代码了。魔珐星云提供的是纯前端 SDK,只需要一个 HTML 文件就能跑起来。这对快速原型开发非常友好。

首先创建项目目录,引入 SDK:

<script src="https://media.xingyun3d.com/xingyun3d/general/litesdk/xmovAvatar@latest.js"></script>

这个 SDK 文件大约几百 KB,加载速度很快。不需要安装任何依赖,也不需要复杂的构建工具,就是这么直接。

核心代码实现

整个应用的核心代码非常精简。我创建了一个基础 Demo,包含数字人展示区、控制面板和日志输出三个部分。

初始化 SDK
const LiteSDK = new XmovAvatar({
    containerId: '#sdk',           // 数字人渲染容器
    appId: 'your_app_id',          // 从平台获取
    appSecret: 'your_app_secret',  // 从平台获取
    gatewayServer: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa/session',

    // 状态变化回调
    onStateChange(state) {
        console.log('当前状态:', state);
    },

    // 语音状态回调
    onVoiceStateChange(status) {
        if (status === 'voice_start') {
            console.log('开始说话');
        } else if (status === 'voice_end') {
            console.log('说话结束');
        }
    },

    enableLogger: true
});

// 初始化连接
await LiteSDK.init({
    onDownloadProgress(progress) {
        console.log(资源加载: ${progress}%);
    },
    onError(error) {
        console.error('初始化错误:', error);
    }
});

初始化过程中,SDK 会下载数字人的 3D 模型、表情数据、动作资源等。这里我特别关注了加载速度:

  • 首次加载大约需要 3-5 秒(取决于网络)
  • 资源会被缓存,第二次加载几乎秒开
  • 有详细的进度回调,可以做个好看的加载动画

驱动数字人说话

这是最核心的功能。API 设计很简洁:

// 让数字人说一句话
LiteSDK.speak("你好,欢迎体验魔珐星云数字人!", true, true);

三个参数:

  • 第一个是要说的文本
  • 第二个 is_start 表示是否开始一段对话
  • 第三个 is_end 表示是否结束这段对话

如果要对接大模型做流式输出,可以这样:

// 第一句
LiteSDK.speak("今天天气", true, false);
// 中间的句子
LiteSDK.speak("真不错", false, false);
// 最后一句
LiteSDK.speak("适合出门散步", false, true);

这种设计对大模型流式对话非常友好。

状态控制

数字人不是只能说话,还有多种状态可以切换:

// 待机状态
LiteSDK.idle();

// 倾听状态(模拟在听用户说话)
LiteSDK.listen();

// 思考状态(模拟在思考)
LiteSDK.think();

// 互动待机(可以打断当前动作)
LiteSDK.interactiveidle();

这些状态切换让交互更自然。比如用户说话时,调用 listen() 让数字人呈现倾听状态;大模型思考时,调用 think() 展现思考动作。

在线/离线模式

这是个很贴心的功能:

// 离线模式(不消耗积分)
LiteSDK.offlineMode();

// 在线模式(正常使用)
LiteSDK.onlineMode();

在调试阶段,可以切换到离线模式节省积分。离线模式下数字人仍然会保持动画循环,只是不会驱动新的内容。

开发中遇到的坑和解决方案

坑 1:“不支持的配置” 错误

前面提到过,这是我遇到的第一个问题。错误信息:

ttsa request error: 不支持的配置

startSession请求失败

原因:在平台创建应用时,角色、音色、表演风格三项没有全部配置。

解决:回到平台检查应用配置,确保三项都已选择并保存。重新复制 App ID 和 App Secret。

坑 2:按钮启用逻辑问题

初始化后控制按钮没有自动启用。这个是我代码逻辑的问题:

// 错误写法
onError(error) {
    isInitialized = false;  // 这会导致后续检查失败
}

// 正确写法
onError(error) {
    console.error('SDK 错误:', error);
    // 不要直接设置 isInitialized,让主流程控制
}

SDK 的 onError 回调会在遇到非致命错误时触发,但这不意味着初始化失败。正确做法是记录错误,但不影响初始化流程。

实际体验:延迟低到让人惊讶

性能测试

我做了几组简单测试:

响应延迟

  • 从调用 speak() 到数字人开始说话:100-300****ms
  • 语音和口型同步精度:几乎完美
  • 表情和动作切换:流畅无卡顿

资源占用

  • 浏览器内存占用:约 200MB
  • CPU 占用:5-10%(Chrome 浏览器)
  • 3D 渲染帧率:稳定 60fps

这个延迟水平已经可以做实时对话了。如果对接到 GPT-4 或文心一言这类大模型,完全可以做成一个流畅的语音助手。

多端适配能力

官方资料提到能在 RK3566 这样的嵌入式芯片上运行。虽然我没有实际硬件测试,但从 SDK 的设计来看:

  1. 纯 WebGL 渲染:不依赖特定硬件,只要支持 WebGL 就能跑
  2. 资源按需加载:3D 模型、表情、动作数据分片下载
  3. 多级质量配置:可以根据设备性能调整清晰度

文档里提到 RK3588 建议 1080P,RK3566 建议 720P。这个适配策略很合理。

应用场景:想象空间很大

基于这套 SDK,我能想到很多有趣的应用:

虚拟客服

传统客服是文字聊天框,体验冰冷。用数字人做客服,配上自然的表情和声音,用户体验会好很多。关键是开发成本不高——只需要对接现有的客服系统和知识库。

教育陪伴

给孩子做个 AI 学习伙伴,用数字人讲故事、教知识。相比纯语音,有形象的数字人更能吸引孩子注意力。而且可以根据学习内容切换不同的表演风格。

车载助手

想象一下,车载中控屏上有个 3D 数字人助手,用自然的语言和动作与你交互。导航时提醒你,播放音乐时推荐歌曲,比传统的语音助手有温度得多。

桌面宠物

做一个桌面小助手,平时在屏幕角落待机,有消息时跳出来提醒,帮你总结邮件、安排日程。这种应用很有市场潜力。

SDK 易用性评价

技术内核:打破不可能三角

魔珐星云的核心优势,在于其通过技术创新,解决了行业长期存在的“质量、成本、延时”的权衡难题。

  • 高质量 + 低成本(AI 端渲): 传统高保真 3D 渲染严重依赖云端高性能 GPU(高成本),而魔珐星云采用AI 端渲技术,将渲染计算卸载到低功耗的终端设备上。这使得您的应用可以在 RK3566 这样的嵌入式芯片上运行(如您所测,无需 GPU 也能稳定 60fps),极大降低了边际成本和部署门槛
  • 高质量 + 低延时(文生 3D 动作大模型): 数字人的自然互动依赖于海量、高精度的动作和表情数据。魔珐星云利用文生 3D 多模态动作大模型,实现了动作的实时生成和高效压缩。结合优化的传输和结算机制,将响应延迟控制在了惊人的 100-300****ms 级别,真正实现了类人级的实时交互

优点

  1. 上手快

从零到看到数字人说话,真的只需要十几分钟。这是我体验过的最友好的 3D 人像 SDK 之一。

  1. 文档清晰

官方文档写得很详细,每个 API 都有说明和示例。错误码也整理成表格,出了问题能快速定位。

  1. **无需 **GPU

这是个大杀器。传统 3D 渲染应用对硬件要求高,但星云用纯 WebGL 实现,连 RK3566 这种低功耗芯片都能跑。这让数字人应用的部署门槛大大降低。

  1. 延迟控制好

100-300ms 的响应延迟,对实时交互来说完全够用。我之前担心网络传输会成为瓶颈,实测下来体验很流畅。

有待改进的地方

  1. 角色定制

目前只能用平台提供的角色,不支持上传自定义模型。如果能开放定制接口,让企业上传自己的 IP 形象,应用范围会更广。

  1. 动作库扩展

虽然表演风格可选,但具体的动作库还是有限。希望未来能开放更多肢体动作,甚至支持自定义动作序列。

  1. SSML 标签文档

SDK 支持 SSML(语音合成标记语言)来控制语调、停顿、动作,但这部分文档不够详细。需要更多示例来说明如何精细控制数字人表现。


我准备了一个可以让大家快速复现使用的代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>魔珐星云具身驱动SDK - 十分钟上手体验</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        
        .header h1 {
            font-size: 28px;
            margin-bottom: 10px;
        }
        
        .content {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            padding: 30px;
        }
        
        .avatar-container {
            background: #f5f5f5;
            border-radius: 15px;
            padding: 20px;
            min-height: 600px;
        }
        
        #sdk {
            width: 100%;
            height: 600px;
            min-width: 400px;
            min-height: 600px;
            background: #000;
            border-radius: 10px;
            overflow: hidden;
            position: relative;
        }
        
        /* 添加加载提示 */
        #sdk::before {
            content: '等待初始化数字人...';
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            color: #fff;
            font-size: 16px;
            z-index: 1;
            pointer-events: none;
        }
        
        #sdk.initialized::before {
            display: none;
        }
        
        .control-panel {
            background: #f9f9f9;
            border-radius: 15px;
            padding: 20px;
        }
        
        .control-group {
            margin-bottom: 20px;
        }
        
        .control-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #333;
        }
        
        .control-group input,
        .control-group textarea {
            width: 100%;
            padding: 10px;
            border: 2px solid #ddd;
            border-radius: 8px;
            font-size: 14px;
            transition: border-color 0.3s;
        }
        
        .control-group input:focus,
        .control-group textarea:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .control-group textarea {
            min-height: 100px;
            resize: vertical;
        }
        
        .btn {
            width: 100%;
            padding: 12px;
            margin: 5px 0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        
        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }
        
        .btn-secondary {
            background: #6c757d;
            color: white;
        }
        
        .btn-secondary:hover {
            background: #5a6268;
        }
        
        .btn-success {
            background: #28a745;
            color: white;
        }
        
        .btn-success:hover {
            background: #218838;
        }
        
        .btn-danger {
            background: #dc3545;
            color: white;
        }
        
        .btn-danger:hover {
            background: #c82333;
        }
        
        .status {
            margin-top: 20px;
            padding: 15px;
            background: #e9ecef;
            border-radius: 8px;
            font-size: 14px;
        }
        
        .status-item {
            margin: 5px 0;
            padding: 5px;
            background: white;
            border-radius: 5px;
        }
        
        .log {
            max-height: 200px;
            overflow-y: auto;
            background: #1e1e1e;
            color: #00ff00;
            padding: 10px;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            margin-top: 10px;
        }
        
        .log-item {
            margin: 3px 0;
        }
        
        @media (max-width: 768px) {
            .content {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🌟 魔珐星云具身驱动SDK</h1>
            <p>让 AI 从会思考,走向能表达、会交流 - 十分钟上手体验</p>
        </div>
        
        <div class="content">
            <div class="avatar-container">
                <h3 style="margin-bottom: 15px; color: #333;">数字人展示区域</h3>
                <div id="sdk"></div>
            </div>
            
            <div class="control-panel">
                <h3 style="margin-bottom: 20px; color: #333;">控制面板</h3>
                
                <div class="control-group">
                    <label>App ID:</label>
                    <input type="text" id="appId" placeholder="请输入您的App ID">
                </div>
                
                <div class="control-group">
                    <label>App Secret:</label>
                    <input type="text" id="appSecret" placeholder="请输入您的App Secret">
                </div>
                
                <div class="control-group">
                    <label>说话内容 (支持SSML):</label>
                    <textarea id="speakText" placeholder="请输入要说的内容,支持SSML格式">欢迎来到星云具身3D数字人平台,这里有超多精彩内容等你发现~</textarea>
                </div>
                
                <button class="btn btn-primary" onclick="initSDK()">初始化SDK</button>
                <button class="btn btn-primary" onclick="speak()">让数字人说话</button>
                <button class="btn btn-secondary" onclick="idle()">待机状态</button>
                <button class="btn btn-secondary" onclick="listen()">聆听状态</button>
                <button class="btn btn-secondary" onclick="think()">思考状态</button>
                <button class="btn btn-secondary" onclick="interactiveIdle()">互动待机</button>
                <button class="btn btn-success" onclick="onlineMode()">在线模式</button>
                <button class="btn btn-secondary" onclick="offlineMode()">离线模式</button>
                <button class="btn btn-danger" onclick="destroySDK()">销毁SDK</button>
                
                <div class="control-group" style="margin-top: 15px;">
                    <label>资源加载进度:</label>
                    <div style="background: #e9ecef; border-radius: 8px; height: 20px; position: relative; overflow: hidden;">
                        <div id="progressBar" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); height: 100%; width: 0%; transition: width 0.3s;"></div>
                        <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold;">
                            <span id="progressText">0%</span>
                        </div>
                    </div>
                </div>
                
                <div class="status">
                    <h4>状态信息:</h4>
                    <div class="status-item" id="status">未初始化</div>
                    <div class="status-item" id="voiceStatus">音频状态: 未开始</div>
                </div>
                
                <div class="log" id="log">
                    <div class="log-item">等待初始化...</div>
                </div>
            </div>
        </div>
    </div>
    
    <!-- 引入星云具身驱动SDK -->
    <script src="https://media.xingyun3d.com/xingyun3d/general/litesdk/xmovAvatar@latest.js"></script>
    
    <script>
        // 检查SDK是否加载成功
        window.addEventListener('load', () => {
            if (typeof XmovAvatar === 'undefined') {
                console.error('SDK加载失败,请检查网络连接');
                document.getElementById('log').innerHTML = 
                    '<div class="log-item" style="color: #ff0000;">[错误] SDK加载失败,请检查网络连接或刷新页面</div>';
            } else {
                console.log('SDK加载成功');
            }
        });
        let liteSDK = null;
        let isInitialized = false;
        
        // 日志输出函数
        function addLog(message, type = 'info') {
            const logDiv = document.getElementById('log');
            const timestamp = new Date().toLocaleTimeString();
            const colors = {
                'info': '#00ff00',
                'error': '#ff0000',
                'warning': '#ffff00'
            };
            const logItem = document.createElement('div');
            logItem.className = 'log-item';
            logItem.style.color = colors[type] || colors.info;
            logItem.textContent = `[${timestamp}] ${message}`;
            logDiv.appendChild(logItem);
            logDiv.scrollTop = logDiv.scrollHeight;
        }
        
        // 更新进度条
        function updateProgress(progress) {
            const progressBar = document.getElementById('progressBar');
            const progressText = document.getElementById('progressText');
            progressBar.style.width = progress + '%';
            progressText.textContent = progress + '%';
        }
        
        // 初始化SDK
        async function initSDK() {
            const appId = document.getElementById('appId').value;
            const appSecret = document.getElementById('appSecret').value;
            
            if (!appId || !appSecret) {
                alert('请先输入App ID和App Secret');
                addLog('初始化失败: 缺少App ID或App Secret', 'error');
                return;
            }
            
            try {
                // 如果已存在实例,先销毁
                if (liteSDK) {
                    liteSDK.destroy();
                    liteSDK = null;
                    isInitialized = false;
                }
                
                addLog('正在创建SDK实例...', 'info');
                
                // 检查SDK是否已加载
                if (typeof XmovAvatar === 'undefined') {
                    throw new Error('SDK未加载,请刷新页面重试');
                }
                
                addLog('SDK类已加载,开始创建实例...', 'info');
                
                liteSDK = new XmovAvatar({
                    containerId: '#sdk',
                    appId: appId,
                    appSecret: appSecret,
                    gatewayServer: 'https://nebula-agent.xingyun3d.com/user/v1/ttsa/session',
                    
                    // Widget事件回调
                    onWidgetEvent(data) {
                        addLog(`Widget事件: ${JSON.stringify(data)}`);
                        console.log('Widget事件:', data);
                    },
                    
                    // 代理Widget事件(可选)
                    proxyWidget: {
                        "widget_slideshow": (data) => {
                            addLog(`轮播图事件: ${JSON.stringify(data)}`);
                        },
                        "widget_video": (data) => {
                            addLog(`视频事件: ${JSON.stringify(data)}`);
                        },
                    },
                    
                    // 网络信息回调
                    onNetworkInfo(networkInfo) {
                        addLog(`网络信息: ${JSON.stringify(networkInfo)}`);
                        console.log('networkInfo:', networkInfo);
                    },
                    
                    // SDK消息回调
                    onMessage(message) {
                        addLog(`SDK消息: ${message}`);
                        console.log('SDK message:', message);
                    },
                    
                    // 状态变化回调
                    onStateChange(state) {
                        document.getElementById('status').textContent = `当前状态: ${state}`;
                        addLog(`状态变化: ${state}`);
                        console.log('当前状态:', state);
                        
                        // 当状态变为已连接时,移除加载提示
                        if (state === 'connected' || state === 'ready') {
                            const sdkContainer = document.getElementById('sdk');
                            if (sdkContainer) {
                                sdkContainer.classList.add('initialized');
                            }
                        }
                    },
                    
                    // 状态变化回调(带状态信息)
                    onStatusChange(status) {
                        addLog(`状态详情: ${JSON.stringify(status)}`);
                        console.log('SDK Status Change:', status);
                    },
                    
                    // 状态渲染变化回调
                    onStateRenderChange(state, duration) {
                        addLog(`状态渲染: ${state}, 持续时间: ${duration}ms`);
                        console.log('SDK State Change Render:', state, duration);
                    },
                    
                    // 音频状态变化回调(根据文章,状态是voice_start和voice_end)
                    onVoiceStateChange(status) {
                        const statusMap = {
                            'voice_start': '开始说话',
                            'voice_end': '说话结束',
                            'start': '开始播放',
                            'end': '播放结束'
                        };
                        document.getElementById('voiceStatus').textContent = 
                            `音频状态: ${statusMap[status] || status}`;
                        addLog(`音频状态: ${status}`);
                        console.log("sdk voice status", status);
                    },
                    
                    // 是否显示日志(SDK内部日志)
                    enableLogger: true
                });
                
                addLog('SDK实例创建成功,开始连接...', 'info');
                document.getElementById('status').textContent = '正在连接...';
                
                // 检查容器是否存在
                const container = document.querySelector('#sdk');
                if (!container) {
                    throw new Error('容器元素 #sdk 不存在');
                }
                
                // 检查容器尺寸
                const rect = container.getBoundingClientRect();
                if (rect.width === 0 || rect.height === 0) {
                    addLog('警告: 容器尺寸为0,可能影响渲染', 'warning');
                }
                
                addLog(`容器尺寸: ${rect.width}x${rect.height}`, 'info');
                
                // 根据官方文档,使用connect方法连接
                if (typeof liteSDK.connect === 'function') {
                    liteSDK.connect();
                    addLog('已调用connect()方法', 'info');
                } else if (typeof liteSDK.init === 'function') {
                    // 如果connect不存在,尝试使用init方法
                    addLog('未找到connect方法,尝试使用init方法', 'warning');
                    await liteSDK.init({
                        onDownloadProgress(progress) {
                            updateProgress(progress);
                            addLog(`资源加载: ${progress}%`);
                        },
                        onError(error) {
                            addLog(`初始化错误: ${error}`, 'error');
                        }
                    });
                } else {
                    addLog('警告: 未找到connect或init方法,SDK可能已自动初始化', 'warning');
                }
                
                // 等待一小段时间让连接建立
                await new Promise(resolve => setTimeout(resolve, 1000));
                
                isInitialized = true;
                addLog('SDK连接成功!', 'info');
                document.getElementById('status').textContent = '连接成功,可以使用';
                updateProgress(100);
                
                // 移除加载提示
                const sdkContainer = document.getElementById('sdk');
                if (sdkContainer) {
                    sdkContainer.classList.add('initialized');
                }
                
            } catch (error) {
                addLog(`初始化失败: ${error.message}`, 'error');
                console.error('SDK初始化错误:', error);
                console.error('错误详情:', error);
                
                // 显示详细错误信息
                let errorMsg = '初始化失败: ' + error.message;
                if (error.stack) {
                    console.error('错误堆栈:', error.stack);
                }
                
                // 检查是否是SDK未加载
                if (typeof XmovAvatar === 'undefined') {
                    errorMsg = 'SDK未加载,请检查网络连接或SDK地址是否正确';
                    addLog('SDK未加载,请刷新页面重试', 'error');
                }
                
                alert(errorMsg);
                isInitialized = false;
                document.getElementById('status').textContent = '初始化失败';
            }
        }
        
        // 让数字人说话(根据文章,参数是text, is_start, is_end)
        function speak() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                addLog('说话失败: SDK未初始化', 'error');
                return;
            }
            
            const text = document.getElementById('speakText').value;
            if (!text) {
                alert('请输入要说的内容');
                return;
            }
            
            try {
                // 根据文章,speak方法的参数是 (text, is_start, is_end)
                // 单次说话:is_start=true, is_end=true
                liteSDK.speak(text, true, true);
                
                addLog(`数字人开始说话: ${text}`, 'info');
            } catch (error) {
                addLog(`说话失败: ${error.message}`, 'error');
                console.error('说话错误:', error);
            }
        }
        
        // 流式说话示例(用于对接大模型)
        function speakStreaming() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            // 第一句
            liteSDK.speak("今天天气", true, false);
            // 中间的句子
            setTimeout(() => liteSDK.speak("真不错", false, false), 1000);
            // 最后一句
            setTimeout(() => liteSDK.speak("适合出门散步", false, true), 2000);
        }
        
        // 待机状态
        function idle() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                liteSDK.idle();
                addLog('切换到待机状态', 'info');
            } catch (error) {
                addLog(`状态切换失败: ${error.message}`, 'error');
            }
        }
        
        // 切换到聆听状态
        function listen() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                liteSDK.listen();
                addLog('切换到聆听状态', 'info');
            } catch (error) {
                addLog(`状态切换失败: ${error.message}`, 'error');
            }
        }
        
        // 思考状态
        function think() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                liteSDK.think();
                addLog('切换到思考状态', 'info');
            } catch (error) {
                addLog(`状态切换失败: ${error.message}`, 'error');
            }
        }
        
        // 互动待机(可以打断当前动作)
        function interactiveIdle() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                // 根据文章,方法名是interactiveidle(不是interactive_idle)
                liteSDK.interactiveidle();
                addLog('切换到互动待机状态', 'info');
            } catch (error) {
                addLog(`状态切换失败: ${error.message}`, 'error');
            }
        }
        
        // 在线模式
        function onlineMode() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                liteSDK.onlineMode();
                addLog('切换到在线模式', 'info');
            } catch (error) {
                addLog(`模式切换失败: ${error.message}`, 'error');
            }
        }
        
        // 离线模式(不消耗积分)
        function offlineMode() {
            if (!liteSDK || !isInitialized) {
                alert('请先初始化SDK');
                return;
            }
            
            try {
                liteSDK.offlineMode();
                addLog('切换到离线模式(不消耗积分)', 'info');
            } catch (error) {
                addLog(`模式切换失败: ${error.message}`, 'error');
            }
        }
        
        // 销毁SDK
        function destroySDK() {
            if (liteSDK) {
                try {
                    liteSDK.destroy();
                    liteSDK = null;
                    isInitialized = false;
                    addLog('SDK已销毁', 'info');
                    document.getElementById('status').textContent = '已销毁';
                    document.getElementById('voiceStatus').textContent = '音频状态: 未开始';
                    updateProgress(0);
                    
                    // 恢复加载提示
                    const sdkContainer = document.getElementById('sdk');
                    if (sdkContainer) {
                        sdkContainer.classList.remove('initialized');
                    }
                } catch (error) {
                    addLog(`销毁失败: ${error.message}`, 'error');
                }
            } else {
                addLog('SDK未初始化,无需销毁', 'warning');
            }
        }
        
        // 页面卸载时清理资源
        window.addEventListener('beforeunload', () => {
            if (liteSDK) {
                liteSDK.destroy();
            }
        });
    </script>
</body>
</html>

一个 HTML 文件就可以实现和数字人的交互,快来体验吧!


总结来看,魔珐星云具身智能平台凭借其六大核心能力文生 3D 多模态动作大模型、AI 端渲与结算等技术底座,成功打破了 3D 数字人应用在“质量、成本、延时”上的不可能三角。它以高质量的 3D 数字人、极低的响应延迟和“开箱即用”的纯前端 SDK,极大地降低了具身智能应用的开发门槛。它让 AI 不再是冷冰冰的代码,而是拥有了生动的情感和自然的肢体语言,真正支持了 AI 具身智能的大规模应用。对于希望提升产品交互体验、探索创新场景的开发者来说,魔珐星云无疑是当前市场上最具性价比和易用性的选择。

别再观望了,立即点击我的专属链接,开启你的具身智能开发之旅,亲手创造一个有温度、会互动的 AI 伙伴吧!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值