1.3 安装与集成
本节说明 XingyunAvatarAgent 的安装与引入方式,以及原生 JS、Vue、React 三类项目的集成示例。
安装
使用包管理器安装:
# npm
npm install @xmov/avatar@latest
# pnpm
pnpm add @xmov/avatar@latest
# yarn
yarn add @xmov/avatar@latest
ESM 引入
安装后在代码中按需导入:
import XingyunAvatarAgent from "@xmov/avatar/agent";
CDN / UMD 引入
端到端对话页面也可通过 <script> 加载自包含构建,直接使用全局构造器 XingyunAvatarAgent,无需预先加载其它 SDK 文件:
<script src="https://media.xingyun3d.com/xingyun3d/general/litesdk/xmovAvatar_e2e@latest.js"></script>
<script>
const agent = new window.XingyunAvatarAgent({
// 配置项见 3.1 构造参数
});
</script>
注意:上述 CDN 地址为固定地址,
@latest为浮动标签。生产环境建议加载锁定版本的文件(如xmovAvatar_e2e.<version>.js)。
无论 ESM 还是 UMD 方式,具身智能体容器都必须有明确宽高,否则画布可能折叠为零尺寸。
集成示例
原生 JS(Vanilla)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>具身智能体集成</title>
<style>
#agent-avatar {
width: min(100%, 405px);
aspect-ratio: 9 / 16;
overflow: hidden;
background: #000;
}
</style>
</head>
<body>
<div id="agent-avatar"></div>
<script type="module">
import XingyunAvatarAgent from "@xmov/avatar/agent";
const agent = new XingyunAvatarAgent({
container: document.getElementById("agent-avatar"),
appId: "your-app-id",
appSecret: "your-app-secret",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa_v2/session",
onMessage(error) {
console.error(error.code, error.message);
},
agentCallbacks: {
onError(error) {
console.error(error.code, error.message);
},
},
});
agent.init({
onDownloadProgress(progress) {
console.log("加载进度", progress.toFixed(0) + "%");
},
});
window.addEventListener("beforeunload", () => {
void agent.destroy("page_unload");
});
</script>
</body>
</html>
Vue 3
<script setup>
import { ref, onBeforeUnmount } from "vue";
import XingyunAvatarAgent from "@xmov/avatar/agent";
const container = ref(null);
const agent = ref(null);
onBeforeUnmount(async () => {
await agent.value?.destroy("component_unmount");
});
async function init() {
agent.value = new XingyunAvatarAgent({
container: container.value,
appId: "your-app-id",
appSecret: "your-app-secret",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa_v2/session",
onMessage(error) {
console.error(error.code, error.message);
},
agentCallbacks: {
onError(error) {
console.error(error.code, error.message);
},
},
});
await agent.value.init({
onDownloadProgress(progress) {
console.log("加载进度", progress.toFixed(0) + "%");
},
});
}
init();
</script>
<template>
<div
ref="container"
style="width: min(100%, 405px); aspect-ratio: 9 / 16; overflow: hidden; background: #000;"
></div>
</template>
注意:Vue 中建议使用
container(DOM 元素)而非containerId,避免组件多实例复用同一 id;卸载时务必调用destroy(),仅移除容器不会释放麦克风与连接资源。
React
import { useEffect, useRef } from "react";
import XingyunAvatarAgent from "@xmov/avatar/agent";
function AvatarComponent() {
const containerRef = useRef(null);
const agentRef = useRef(null);
useEffect(() => {
let destroyed = false;
async function init() {
const agent = new XingyunAvatarAgent({
container: containerRef.current,
appId: "your-app-id",
appSecret: "your-app-secret",
gatewayServer: "https://nebula-agent.xingyun3d.com/user/v1/ttsa_v2/session",
onMessage(error) {
console.error(error.code, error.message);
},
agentCallbacks: {
onError(error) {
console.error(error.code, error.message);
},
},
});
agentRef.current = agent;
await agent.init({
onDownloadProgress(progress) {
console.log("加载进度", progress.toFixed(0) + "%");
},
});
if (destroyed) {
await agent.destroy("component_unmounted");
}
}
init();
return () => {
destroyed = true;
void agentRef.current?.destroy("component_unmounted");
};
}, []);
return (
<div
ref={containerRef}
style={{
width: "min(100%, 405px)",
aspectRatio: "9 / 16",
overflow: "hidden",
background: "#000",
}}
/>
);
}
export default AvatarComponent;
注意:React 18+ 开发环境(Strict Mode)会双调用
useEffect,示例通过destroyed标记保证只销毁一次并避免泄漏;请用container挂载到ref,不要在多个组件实例间共享同一个containerId。