# 数字人视频生成 — 研究与验证记录

> 本文档记录了从零开始探索「单图 + 音频 → 说话视频」的完整过程，
> 包括工具选型、环境踩坑、最终跑通的完整流程，以及对产品化的建议。
>
> 日期：2026-03-25
> 硬件：RTX 5090 (Blackwell, sm_120), CUDA 12.9, WSL2

---

## 一、目标

给定一张人物图片和一段音频，生成该人物"说话"的视频：
- 嘴型与音频内容同步
- 头部有自然动作（非僵硬的照片）
- 可扩展至实时/直播场景

---

## 二、工具选型过程

### 2.1 最初方向：LivePortrait

- **项目**：https://github.com/KlingTeam/LivePortrait（快手）
- **本质**：视频驱动的人脸动画，需要一个"驱动视频"来控制人物表情和头部运动
- **误区澄清**：网上有描述称 LivePortrait 支持"音频驱动"，这是**不准确的**。它只能从驱动视频中提取音频附加到输出，无法用音频生成嘴型
- **结论**：LivePortrait 适合生成头部动作底片，不能单独完成任务

### 2.2 调研其他工具

| 工具 | 厂商 | 核心能力 | 实时性 | 结论 |
|------|------|---------|--------|------|
| LatentSync 1.6 | 字节跳动 | 扩散模型唇形同步，512x512 | ❌ 约4fps | 质量好，但太慢 |
| MuseTalk 1.5 | 腾讯 | 单步推理唇形同步 | ⚠️ 约7fps | 速度可接受，质量好 |
| Live Avatar | 阿里 | 140B 扩散模型 | ❌ 需集群 | 单卡不可行 |
| SadTalker | 开源 | 音频驱动全脸动画 | ❌ | 未测试 |
| Sonic | 腾讯 | 音频驱动 | 未知 | 项目在 `/home/xsl/work/Sonic`，未测试 |

### 2.3 最终方案

**两阶段流水线：**

```
hairstyle-result.jpg
        ↓
  [LivePortrait]  ←  驱动视频 (d3.mp4, 自然头部动作)
        ↓
  头动底片视频 (hairstyle-result--d3.mp4, 11.8s)
        ↓
   [MuseTalk]  ←  音频 (test_speech_10s.wav)
        ↓
  最终视频 (嘴型同步 + 头部运动)
```

---

## 三、环境配置（重要踩坑记录）

### 3.1 RTX 5090 的核心问题

RTX 5090 是 Blackwell 架构（sm_120），**PyTorch 稳定版（2.6 及以下）不支持**。
所有项目都必须使用 PyTorch nightly cu128：

```bash
pip install --pre torch torchvision torchaudio \
  --index-url https://download.pytorch.org/whl/nightly/cu128
# 已验证版本：torch-2.12.0.dev20260324+cu128
```

**这是最先要做的事，否则所有 CUDA 推理都会报错：**
```
CUDA error: no kernel image is available for execution on the device
```

### 3.2 HuggingFace CLI 命令名

在某些 conda 环境中，命令名是 `hf` 而不是 `huggingface-cli`：

```bash
which hf          # /home/xsl/miniconda3/envs/MuseTalk/bin/hf
hf --version      # 1.7.2
```

下载需要 Token：
```bash
export HF_TOKEN=<your_token>
hf download <repo> <file> --local-dir <dir>
```

---

## 四、LivePortrait 部署

### 4.1 环境

```bash
conda create -n LivePortrait python=3.10 -y
conda activate LivePortrait
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128
cd /home/xsl/work/LivePortrait
pip install -r requirements.txt
```

### 4.2 权重

```bash
# 约 1.1GB
huggingface-cli download KlingTeam/LivePortrait \
  --local-dir pretrained_weights \
  --exclude "*.git*" "README.md" "docs"
```

目录结构：
```
pretrained_weights/
├── insightface/        (~21MB)
├── liveportrait/       (~608MB)
└── liveportrait_animals/ (~500MB)
```

### 4.3 生成头动底片

```bash
conda activate LivePortrait
cd /home/xsl/work/LivePortrait

python inference.py \
  -s /path/to/portrait.jpg \
  -d assets/examples/driving/d3.mp4 \
  --flag_crop_driving_video \
  -o /home/xsl/work/head_motion_base
```

**驱动视频参考**（位于 `assets/examples/driving/`）：

| 文件 | 时长 | 特点 |
|------|------|------|
| d3.mp4 | 11.8s | 自然说话动作，与10s音频匹配 |
| d6.mp4 | 33.6s | 长片段，适合循环 |
| d10.mp4 | 15.0s | 较长 |

**技巧**：选择时长接近音频时长的驱动视频；`--flag_crop_driving_video` 会自动裁剪驱动视频。

### 4.4 已知警告（可忽略）

```
[E:onnxruntime] Failed to load library libonnxruntime_providers_cuda.so
```
onnxruntime-gpu 依赖 CUDA 11.x，与系统 CUDA 12.9 不兼容，人脸检测自动回退 CPU，不影响结果。

---

## 五、LatentSync 部署（已验证，非推荐方案）

> **结论**：质量好，但速度太慢（4fps），不适合产品化。作为备选方案保留。

### 5.1 环境

```bash
conda create -y -n latentsync python=3.10.13
conda activate latentsync
conda install -y -c conda-forge ffmpeg

pip install -r /home/xsl/work/LatentSync/requirements.txt

# RTX 5090 必须卸载稳定版再装 nightly
pip uninstall torch torchvision torchaudio -y
pip install --pre torch torchvision torchaudio \
  --index-url https://download.pytorch.org/whl/nightly/cu128
```

### 5.2 权重（约 4.9GB）

```bash
cd /home/xsl/work/LatentSync
huggingface-cli download ByteDance/LatentSync-1.6 whisper/tiny.pt --local-dir checkpoints
huggingface-cli download ByteDance/LatentSync-1.6 latentsync_unet.pt --local-dir checkpoints
```

### 5.3 输入准备

LatentSync 需要**视频**（非图片）+ **WAV 音频**：

```bash
# 图片 → 视频
ffmpeg -loop 1 -i portrait.jpg \
  -t <duration> \
  -vf "scale=512:512:force_original_aspect_ratio=decrease,pad=512:512:(ow-iw)/2:(oh-ih)/2" \
  -r 25 -c:v libx264 -pix_fmt yuv420p input_video.mp4 -y

# mp3 → wav
ffmpeg -i audio.mp3 -ar 16000 -ac 1 input_audio.wav -y
```

### 5.4 推理

```bash
conda activate latentsync
cd /home/xsl/work/LatentSync
python -m scripts.inference \
    --unet_config_path "configs/unet/stage2_512.yaml" \
    --inference_ckpt_path "checkpoints/latentsync_unet.pt" \
    --inference_steps 20 \
    --guidance_scale 1.5 \
    --enable_deepcache \
    --video_path "assets/input_video.mp4" \
    --audio_path "assets/input_audio.wav" \
    --video_out_path "video_out.mp4"
```

---

## 六、MuseTalk 部署（推荐方案）

### 6.1 项目路径

```
/home/xsl/work/MuseTalk
```

### 6.2 环境搭建（完整步骤，含所有踩坑修复）

```bash
conda create -y -n MuseTalk python=3.10
conda activate MuseTalk
conda install -y -c conda-forge ffmpeg

# 1. PyTorch nightly（RTX 5090 必须）
pip install --pre torch torchvision torchaudio \
  --index-url https://download.pytorch.org/whl/nightly/cu128

# 2. 项目依赖
cd /home/xsl/work/MuseTalk
pip install -r requirements.txt

# 3. 修复 chumpy 构建问题
pip install --no-build-isolation chumpy

# 4. MMLab（版本必须严格匹配，不可随意升降）
pip install mmengine
MMCV_WITH_OPS=1 pip install mmcv==2.1.0 --no-build-isolation  # 需要系统 nvcc
pip install "mmdet>=3.3.0"        # ≥3.3.0 才兼容 mmcv 2.1.0
pip install "mmpose>=1.3.0"       # ≥1.3.0 才兼容 mmcv 2.1.0
pip install xtcocotools json-tricks munkres

# 5. 更新 transformers（旧版与 huggingface-hub 1.x 冲突）
pip install "transformers>=4.45.0"
```

### 6.3 MMLab 版本兼容矩阵（关键）

```
mmcv 2.1.0  ←→  mmdet ≥3.3.0  ←→  mmpose ≥1.3.0
```

| 踩坑 | 原因 | 修复 |
|------|------|------|
| mmcv 构建失败 | nightly PyTorch 没有预编译轮子 | `MMCV_WITH_OPS=1 pip install mmcv==2.1.0 --no-build-isolation`（需系统 nvcc） |
| `MMCV==2.1.0 is used but incompatible` | mmdet 3.1.0 要求 mmcv < 2.1.0 | 升级到 mmdet ≥3.3.0 |
| `mmpose 1.1.0 incompatible` | 同上 | 升级到 mmpose ≥1.3.0 |
| `transformers ImportError` | huggingface-hub 1.x 与旧 transformers 冲突 | 升级 transformers ≥4.45.0 |

### 6.4 权重下载

```bash
cd /home/xsl/work/MuseTalk
export HF_TOKEN=<your_token>

# 注意：此环境中命令是 hf，不是 huggingface-cli
hf download TMElyralab/MuseTalk \
  "musetalkV15/musetalk.json" "musetalkV15/unet.pth" \
  --local-dir models

hf download stabilityai/sd-vae-ft-mse \
  config.json diffusion_pytorch_model.bin \
  --local-dir models/sd-vae

hf download yzd-v/DWPose \
  dw-ll_ucoco_384.pth \
  --local-dir models/dwpose

hf download openai/whisper-tiny \
  config.json pytorch_model.bin preprocessor_config.json \
  --local-dir models/whisper

hf download ByteDance/LatentSync \
  latentsync_syncnet.pt \
  --local-dir models/syncnet

# face-parse 权重（不在 HuggingFace）
pip install gdown
gdown --id 154JgKpzCPW82qINcVieuPH3fZ2e0P812 -O models/face-parse-bisent/79999_iter.pth
curl -L https://download.pytorch.org/models/resnet18-5c106cde.pth \
  -o models/face-parse-bisent/resnet18-5c106cde.pth
```

权重总大小约 **5GB**：
```
models/
├── musetalkV15/
│   ├── unet.pth         (3.2GB)
│   └── musetalk.json
├── sd-vae/
│   ├── diffusion_pytorch_model.bin  (320MB)
│   └── config.json
├── dwpose/
│   └── dw-ll_ucoco_384.pth  (389MB)
├── whisper/
│   └── pytorch_model.bin    (145MB)
├── syncnet/
│   └── latentsync_syncnet.pt  (1.4GB)
└── face-parse-bisent/
    ├── 79999_iter.pth     (51MB)
    └── resnet18-5c106cde.pth  (45MB)
```

### 6.5 PyTorch 2.6+ 兼容性补丁（必须）

PyTorch 2.6+ 将 `torch.load` 的 `weights_only` 默认值改为 `True`，导致 MuseTalk 加载旧格式权重失败。
已在 `scripts/inference.py` 中加入 monkey-patch：

```python
# 在 inference.py 开头的 import torch 后面加入：
_orig_torch_load = torch.load
def _patched_torch_load(f, *args, **kwargs):
    kwargs.setdefault('weights_only', False)
    return _orig_torch_load(f, *args, **kwargs)
torch.load = _patched_torch_load
```

同样的补丁也需要加到 `scripts/realtime_inference.py`（如果使用实时模式）。

### 6.6 推理配置文件

创建 YAML 配置文件（`configs/inference/my_task.yaml`）：

```yaml
task_0:
 video_path: "/path/to/head_motion_video.mp4"
 audio_path: "/path/to/audio.wav"
 bbox_shift: 0   # 可选：调整嘴部区域位置，负值下移，正值上移
```

### 6.7 运行推理

```bash
conda activate MuseTalk
cd /home/xsl/work/MuseTalk

python -m scripts.inference \
  --inference_config configs/inference/my_task.yaml \
  --result_dir results/output \
  --unet_model_path models/musetalkV15/unet.pth \
  --unet_config models/musetalkV15/musetalk.json \
  --version v15
```

输出路径：`results/output/v15/<video_name>.mp4`

---

## 七、完整流水线（已验证示例）

### 输入

- 图片：`/home/xsl/work/LivePortrait/hairstyle-result.jpg`（1080x1920，正面人像）
- 音频：`/home/xsl/work/LivePortrait/test_speech_10s.mp3`（11.8秒，中文语音）

### Step 1：生成头动底片

```bash
conda activate LivePortrait
cd /home/xsl/work/LivePortrait

python inference.py \
  -s /home/xsl/work/LivePortrait/hairstyle-result.jpg \
  -d assets/examples/driving/d3.mp4 \
  --flag_crop_driving_video \
  -o /home/xsl/work/head_motion_base
```

输出：`/home/xsl/work/head_motion_base/hairstyle-result--d3.mp4`（11.8s, 2.1MB）

### Step 2：音频转 WAV

```bash
ffmpeg -i /home/xsl/work/LivePortrait/test_speech_10s.mp3 \
  -ar 16000 -ac 1 /tmp/input_audio.wav -y
```

### Step 3：MuseTalk 嘴型同步

```bash
conda activate MuseTalk
cd /home/xsl/work/MuseTalk

cat > configs/inference/hairstyle.yaml << 'EOF'
task_0:
 video_path: "/home/xsl/work/head_motion_base/hairstyle-result--d3.mp4"
 audio_path: "/tmp/input_audio.wav"
EOF

python -m scripts.inference \
  --inference_config configs/inference/hairstyle.yaml \
  --result_dir results/hairstyle \
  --unet_model_path models/musetalkV15/unet.pth \
  --unet_config models/musetalkV15/musetalk.json \
  --version v15
```

输出：`/home/xsl/work/MuseTalk/results/hairstyle/v15/hairstyle-result--d3_input_audio.mp4`

### 性能数据

| 阶段 | 耗时 | 帧数 | 等效速度 |
|------|------|------|---------|
| LivePortrait 头动生成 | ~30s | 295帧 | ~10fps |
| MuseTalk 嘴型合成 | ~50s | 354帧 | ~7fps |
| 总计 | ~80s | — | 生成12s视频 |

---

## 八、产品化建议

### 8.1 当前方案的局限

1. **非实时**：总体约 7fps 生成速度，12秒视频需要 80 秒处理
2. **两套环境**：LivePortrait 和 MuseTalk 分别用不同 conda 环境，pipeline 不够整洁
3. **头动单调**：驱动视频固定，长时间使用会重复
4. **图片分辨率**：MuseTalk 处理区域限定在 256x256 嘴部区域

### 8.2 提速方向

- **MuseTalk 实时模式**：`scripts/realtime_inference.py` 支持流式处理，延迟更低
- **头动循环库**：预先用 LivePortrait 生成多种头动视频（点头、摇头、思考等），运行时随机选取
- **TensorRT 量化**：对 MuseTalk UNet 做 TRT 优化，预计可提速 2-3x

### 8.3 架构建议（产品级）

```
音频输入
   ↓
[ASR/VAD]  →  静音检测、分段
   ↓
[MuseTalk 实时流]  ←  头动视频循环
   ↓
[后处理：美颜/超分]（可选）
   ↓
视频输出流
```

### 8.4 替代方案调研建议

在正式产品开发前，建议调研以下工具：
- **Sonic**（`/home/xsl/work/Sonic`）：已有项目，未测试，可能支持更好的实时性
- **EchoMimic**：阿里的音频驱动方案，支持半身动作
- **AniPortrait**：同时驱动头部和嘴型

---

## 九、目录结构总览

```
/home/xsl/work/
├── LivePortrait/          # 头部动作驱动
│   ├── pretrained_weights/  (~1.1GB)
│   ├── hairstyle-result.jpg # 测试图片
│   ├── test_speech_10s.mp3  # 测试音频
│   └── DEPLOYMENT.md        # 详细部署笔记
│
├── LatentSync/            # 扩散模型唇形同步（备用）
│   ├── checkpoints/         (~4.9GB)
│   └── video_out.mp4        # 测试输出
│
├── MuseTalk/              # 单步推理唇形同步（推荐）
│   ├── models/              (~5GB)
│   └── results/hairstyle/v15/hairstyle-result--d3_input_audio.mp4
│
├── head_motion_base/      # LivePortrait 生成的头动底片
│   └── hairstyle-result--d3.mp4
│
└── Sonic/                 # 待调研
```

### Conda 环境

```bash
conda env list
# LivePortrait   /home/xsl/miniconda3/envs/LivePortrait
# latentsync     /home/xsl/miniconda3/envs/latentsync
# MuseTalk       /home/xsl/miniconda3/envs/MuseTalk
```

---

## 十、快速复现命令（Cheat Sheet）

```bash
# === 生成一个说话视频（完整流程）===

# 1. 生成头动底片
conda activate LivePortrait && cd /home/xsl/work/LivePortrait
python inference.py -s portrait.jpg -d assets/examples/driving/d3.mp4 \
  --flag_crop_driving_video -o /tmp/head_motion

# 2. 音频转 WAV
ffmpeg -i input.mp3 -ar 16000 -ac 1 /tmp/audio.wav -y

# 3. 嘴型同步
conda activate MuseTalk && cd /home/xsl/work/MuseTalk
python -m scripts.inference \
  --inference_config <(echo "task_0:\n video_path: /tmp/head_motion/*.mp4\n audio_path: /tmp/audio.wav") \
  --result_dir /tmp/output \
  --unet_model_path models/musetalkV15/unet.pth \
  --unet_config models/musetalkV15/musetalk.json \
  --version v15
```
