> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/how-convai-embody-works.md).

# Convai Embody 的工作原理

了解 Convai Embody 如何将角色 ID 转换为会说话的 3D 身体，以及它为何共用一个连接并按固定顺序运行动作。

本页说明 Convai Embody 如何从角色 ID 获取到一个会说话的身体，以及其背后的设计选择。有关将角色添加到页面的步骤，请参见 [将 3D 角色添加到 React 应用](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/add-a-3d-character-to-a-react-app.md).

### 一个凭证，一条连接

一个会说话的角色有两部分：一个用于渲染的身体，以及一个负责倾听和回复的头脑。Convai Web SDK 已经提供了头脑，即一个 `ConvaiClient` 用于流式传输对话和角色声音的部分。Convai Embody 添加了身体并将二者连接起来。

Convai Embody 之所以自行打开连接，而不是向应用请求一个客户端，是因为口型同步必须来自生成声音的同一会话。两个客户端就意味着两个会话：一个负责发声，另一个驱动嘴部，因此角色要么对着空气动嘴，要么在说话时保持不动。打开一条连接并将其作为 `character.client` 消除了这种故障。这也是聊天组件通过 `useWidgetClient` 而不是 `useConvaiClient`，否则会构造第二个客户端。

该连接默认向 Convai 请求 MetaHuman blendshape 帧。如果没有这项请求，Convai 就不会发送口型同步数据，角色说话时就会面无表情。

### 从角色 ID 到身体

```mermaid
graph LR
    A["角色 ID 和凭证"] --> B["Convai 解析身体清单"]
    B --> C["选择受支持的骨架"]
    C --> D["加载并规范化模型"]
    D --> E["播放待机动画片段"]
    A --> F["打开 Convai Web SDK 连接"]
    F --> G["语音和口型同步帧"]
    E --> H["逐帧更新"]
    G --> H
```

Convai 会将角色 ID 解析为身体清单：要加载的模型、其动画片段，以及它所构建的骨架。角色的头像可以有自己发布的网页身体。如果没有，Convai 会提供为该头像性别配置的默认身体，或者为没有头像的角色提供中性默认身体。如果两者都不存在，请求会失败并返回 `角色未配置 3D 身体。`

清单可以为多个骨架提供相同的身体。Convai Embody 会选择它能识别的第一个骨架。受支持的骨架是 `convai-mha-1`，即 Unreal Engine 的 MetaHuman 骨架；其骨骼和 morph target 名称作为骨架配置文件中的数据，而不是代码，因此支持另一种骨架只意味着添加一个配置文件。

模型经过 Draco 压缩，因此加载器需要 Draco 解码器。随后模型会按站立人类的高度缩放并放置到脚踩地面的位置，然后开始待机动画片段，因此角色不会停留在其绑定姿势。

### 帧处理管线

每一帧，驱动角色移动的系统都会按固定顺序运行。这个顺序是设计的一部分：每个系统都会写入后续系统读取或覆盖的骨骼或 morph target。

| 顺序 | 系统               | 它为何在此运行                             |
| -- | ---------------- | ----------------------------------- |
| 1  | 单位规范化            | 在任何内容读取场景中的位置之前，模型的缩放必须先稳定下来。       |
| 2  | 动画片段             | 这些片段为骨架设置姿势。                        |
| 3  | Gaze             | 凝视会替换片段的头部旋转，而不是与之混合，因此它在这些片段之后运行。  |
| 4  | 呼吸               | 呼吸是在片段写入的姿势之上叠加的，因此它在片段之后运行，并且不会累积。 |
| 5  | 先口型同步，再眼球运动，然后眨眼 | 眨眼在口型同步之后运行，因此它会控制两者都会触及的眼睑通道。      |

凝视会用头部和颈部跟随摄像机，在静止时轻微漂移，并偶尔看向别处。呼吸会先带动胸部，再带动腰部。眨眼在时机和完整度上各不相同，而眼睑会跟随向下的视线。

### 减少动态效果

当用户的系统通过 `prefers-reduced-motion` 媒体查询请求减少动态效果时，Convai Embody 会衰减叠加的动作层，例如呼吸和待机漂移，并抑制移开视线的变化。口型同步和动画片段不会被衰减，因为它们承载着含义：如果把嘴部动作弱化，会让角色更难理解，却不会让它看起来更平静。

### 环境

每个版本的 `@convai/embody` 都会连接到一个 Convai 环境，由其默认值设置 `baseUrl`。角色 ID 只属于一个环境，不会继承到另一个环境。来自不同环境的 ID 会失败，并返回一个 not-found 错误，看起来像权限问题，但其实是环境错误。

### 相关概念

{% content-ref url="/pages/29f9aac19fcc2f8cd08338eeb8c9340da2c133cf" %}
[使用 blendshape 驱动面部动画](/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-web-sdk/lipsync-and-blendshape.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/web-plugins/convai-embody/how-convai-embody-works.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
