> 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/convai-unreal-engine-plugin/features/lip-sync/record-and-replay-lip-sync.md).

# 录制并回放口型同步

在 Convai 对话期间捕获实时口型同步序列，并在之后的过场动画、缓存响应或离线预览中回放，无需重新流式传输。

该 `UConvaiFaceSyncComponent` 录制 API 让你捕获在实时对话期间到达的 blendshape 帧，并在不从 Convai 重新流式传输的情况下按需回放它们。可用于同一段口型同步序列会重复播放的过场动画、在响应被触发前预热响应，或用于面部动画的调试和离线预览。

{% hint style="warning" %}
录制 API —— `StartRecordingLipSync`, `FinishRecordingLipSync`, `PlayRecordedLipSync`, `IsPlaying`，以及 `GetCurrentFrame` —— 仅限 C++。这些方法没有 `UFUNCTION` 注解，且无法从蓝图访问。
{% endhint %}

### 何时使用录制 API

| 使用场景          | Approach                             |
| ------------- | ------------------------------------ |
| 包含固定角色台词的过场动画 | 在开发期间录制一次，保存该序列，并在过场动画中回放            |
| 预热的响应缓存       | 首次播放时录制响应，随后对相同响应进行回放                |
| 离线面部动画预览      | 在 PIE 会话期间录制，并使用 `GetCurrentFrame()` |
| 实时流式传输（实时对话）  | 不要使用录制 API——AnimGraph 节点会自动处理实时帧     |

### 前提条件

* Actor 具有一个 `Convai Face Sync` 组件以及一个可工作的 `Convai Chatbot` 组件。
* 角色在对话期间已经会生成口型同步（参见 [口型同步快速入门](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/lip-sync/lip-sync-quick-start.md) 如果还没有的话）。

### 录制一个序列

{% stepper %}
{% step %}

#### 在发言轮次开始前开始录制

调用 `StartRecordingLipSync()` 在 `UConvaiFaceSyncComponent` 实例。从这一刻起，Convai 传入的每个 blendshape 帧都会在应用到面部的同时被内部缓冲。

```cpp
// 伪代码
UConvaiFaceSyncComponent* FaceSync = MyCharacter->FindComponentByClass<UConvaiFaceSyncComponent>();
if (FaceSync)
{
    FaceSync->StartRecordingLipSync();
}
```

{% endstep %}

{% step %}

#### 让角色说话

像平常一样触发一段对话。角色会说话并且面部会动起来。录制期间，组件会在后台捕获传入的帧——无需额外调用。
{% endstep %}

{% step %}

#### 停止录制并保存结果

当发言轮次结束时，调用 `FinishRecordingLipSync()`。该方法停止捕获并返回一个 `FAnimationSequenceBP` 其中包含完整的按帧索引的 blendshape 帧列表、总时长和帧率。

```cpp
// 伪代码
FAnimationSequenceBP CachedSequence = FaceSync->FinishRecordingLipSync();
```

将此值存为 Actor 或组件上的成员变量，以便之后回放。此时你就拥有了在该对话轮次中播放的完整面部动画。
{% endstep %}
{% endstepper %}

### 回放录制的序列

调用 `PlayRecordedLipSync` 在 `UConvaiFaceSyncComponent` 实例来回放已保存的序列。组件会像在实时流中一样将录制的帧送入 AnimGraph 节点，且无需任何正在进行的 Convai 对话流。

#### PlayRecordedLipSync 参数

| 参数                  | 类型                     | 说明                                 |
| ------------------- | ---------------------- | ---------------------------------- |
| `RecordedLipSync`   | `FAnimationSequenceBP` | 由 `FinishRecordingLipSync`.        |
| `StartFrame`        | `int32`                | 要回放的第一帧索引。传入 `0` 即可从开头开始。          |
| `EndFrame`          | `int32`                | 要回放的最后一帧索引。传入 `-1` 即可播放到序列末尾。      |
| `OverwriteDuration` | `float`                | 覆盖序列中保存的播放时长（秒）。传入 `0.0` 即可使用原始时长。 |

`PlayRecordedLipSync` 返回 `bool` — `true` 如果序列成功启动，则返回 `false` 如果序列为空或无效、录制仍处于活动状态， `StartFrame` 大于最后一帧索引，或者 `EndFrame` 大于 `0` 且小于 `StartFrame`.

```cpp
// 伪代码
bool bStarted = FaceSync->PlayRecordedLipSync(CachedSequence, 0, -1, 0.0f);
```

### 监控播放状态

在录制序列播放时，可使用这些 C++ 方法来观察组件：

| 方法                  | 返回                   | 说明                                           |
| ------------------- | -------------------- | -------------------------------------------- |
| `IsPlaying() const` | `bool`               | `true` 当组件正在积极回放来自录制或实时序列的帧时。                |
| `GetCurrentFrame()` | `TMap<FName, float>` | 当前正在应用的帧的 blendshape 名称到权重映射。适合基于同一数据驱动次级系统。 |

### C++ 示例流程

典型的过场动画用法如下：

```cpp
// 伪代码
// 1. 在发言轮次开始前或开始时：
FaceSync->StartRecordingLipSync();

// 2. 角色说话——录制会在后台自动进行。

// 3. 当发言轮次结束时：
FAnimationSequenceBP CachedSequence = FaceSync->FinishRecordingLipSync();

// 4. 当你想回放该序列时（例如在过场动画触发时）：
FaceSync->PlayRecordedLipSync(CachedSequence, 0, -1, 0.0f);
```

{% hint style="info" %}
回放序列不会重新触发音频。请单独播放匹配的音频片段，并对齐播放开始时间，以保持面部与语音同步。
{% endhint %}

### 下一步

{% content-ref url="/pages/8b7003d8fdf40c7b56b0fd2a54376bfc5105903c" %}
[Face Sync 组件参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/lip-sync/face-sync-component-reference.md)
{% endcontent-ref %}

{% content-ref url="/pages/1d4e6a68b8b0634dd00381e03cb9447a556b758c" %}
[口型同步使用示例](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unreal-engine-plugin/features/lip-sync/lip-sync-usage-examples.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/convai-unreal-engine-plugin/features/lip-sync/record-and-replay-lip-sync.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.
