Initial lip-sync service with command backend

This commit is contained in:
cat-shark
2026-06-20 17:16:11 +08:00
commit 8c6a222c38
25 changed files with 1226 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
# aIzhinengti 接入说明
## 1. 主项目调用点
主项目会通过 `scripts/digital_human_process.py` 调用 Gradio
```python
client = Client(api_url)
result = client.predict(
audio_file=handle_file(audio_file),
video_file={"video": handle_file(video_file)},
api_name="/process_single",
)
```
所以本服务必须保持 `/process_single` 接口可用。
## 2. 主项目中如何填写
`aIzhinengti` 数字人页面:
1. 打开设置。
2. `数字人模型` 选择 `自主算力机`
3. `数字人API地址` 填本服务地址,例如 `http://127.0.0.1:7860/`
4. 如果不用 CompShare 启停机器,服务器 ID 可以先填占位值用于通过界面校验。
5. 手动启动本服务,不依赖主项目启动按钮。
## 3. 本项目侧验证
先启动服务:
```powershell
cd D:\WYF-project\digital-human-lipsync-service
.\scripts\start.ps1
```
再用测试客户端:
```powershell
.\scripts\test-client.ps1 -Audio C:\test\audio.wav -Video C:\test\avatar.mp4
```
## 4. 主项目脚本验证
也可以直接用主项目脚本验证:
```powershell
cd D:\WYF-project\aIzhinengti
python .\scripts\digital_human_process.py http://127.0.0.1:7860/ C:\test\audio.wav C:\test\avatar.mp4
```
期望返回:
```json
{
"success": true,
"videoPath": "..."
}
```
## 5. 接口不要随意改
不要把 `/process_single` 改成其它名字;不要改输入参数名;不要改成多个输出组件。主项目脚本当前按固定协议解析。
+35
View File
@@ -0,0 +1,35 @@
# 架构说明
## 数据流
```mermaid
flowchart LR
A["aIzhinengti 数字人任务"] --> B["scripts/digital_human_process.py"]
B --> C["Gradio Client"]
C --> D["本项目 /process_single"]
D --> E{"LIPSYNC_BACKEND"}
E --> F["ffmpeg_mux 链路验证"]
E --> G["command 外部模型命令"]
E --> H["未来专用模型后端"]
F --> I["outputs/*.mp4"]
G --> I
H --> I
I --> B
B --> A
```
## 模块职责
- `config.py`:从环境变量读取配置,创建输出/临时目录。
- `app.py`:创建 Gradio UI 和 `/process_single` API。
- `backends.py`:规范化输入文件,调用不同后端,返回输出视频路径。
- `scripts/start.ps1`Windows 启动入口。
- `scripts/test-client.ps1`:模拟主项目 Gradio client 调用。
## 当前实现状态
当前已经具备最小可运行服务骨架,但真实口型同步能力还没有接入。默认后端只做音频封装,便于先验证主项目能不能访问服务。
## 推荐演进
第一阶段不要急着改 Gradio 接口,先保持 `/process_single` 稳定。真实模型接入优先放到 `command` 后端,跑通后再封装专用 Python 后端。
+120
View File
@@ -0,0 +1,120 @@
# 后端适配指南
## 1. 后端必须满足的条件
无论接入哪个模型,最终都要满足:
- 输入:一个音频文件路径、一个视频文件路径。
- 输出:一个 mp4 文件路径。
- 失败:抛出异常或返回非零退出码,错误信息要能定位原因。
## 2. `command` 后端接入方式
`command` 后端是最推荐的第一步,因为它不要求立刻改 Python 代码。只要你的模型有命令行推理脚本,就可以接入。
示例:
```powershell
$env:LIPSYNC_BACKEND = "command"
$env:LIPSYNC_COMMAND_CWD = "D:\models\Wav2Lip"
$env:LIPSYNC_COMMAND_TIMEOUT_SECONDS = "1800"
$env:LIPSYNC_COMMAND_TEMPLATE = 'python inference.py --checkpoint_path D:\models\Wav2Lip\checkpoints\wav2lip_gan.pth --face {video_q} --audio {audio_q} --outfile {output_q}'
.\scripts\start.ps1 -Backend command
```
模板变量:
- `{audio}`:音频路径
- `{video}`:视频路径
- `{output}`:输出路径,模型必须写到这里
- `{workdir}`:临时工作目录
- `{cwd}`:命令执行目录,来自 `LIPSYNC_COMMAND_CWD`
- `{audio_q}` / `{video_q}` / `{output_q}` / `{workdir_q}` / `{cwd_q}`:已按当前系统 shell 转义的路径,推荐在命令模板中使用
## 3. Wav2Lip 接入提示
适合快速验证,生态资料多。
典型命令形态:
```powershell
python D:\models\Wav2Lip\inference.py `
--checkpoint_path D:\models\Wav2Lip\checkpoints\wav2lip_gan.pth `
--face {video_q} `
--audio {audio_q} `
--outfile {output_q}
```
注意点:
- 原始 Wav2Lip 对高清视频和复杂脸部姿态效果有限。
- 需要确认 ffmpeg 可用。
- 输出路径必须是 `{output}`,否则服务会认为失败。
- 如果模型脚本依赖相对路径资源,把 `LIPSYNC_COMMAND_CWD` 设为模型仓库根目录。
- 真实推理耗时较长时,设置 `LIPSYNC_COMMAND_TIMEOUT_SECONDS``0` 表示不限时。
## 3.1 命令后端失败诊断
`command` 后端会检查:
- 模板变量是否存在。
- `LIPSYNC_COMMAND_CWD` 是否是有效目录。
- 命令退出码是否为 0。
- `{output}` 指向的 mp4 是否存在且非空。
失败时会返回命令、退出码、耗时、stdout 尾部和 stderr 尾部。错误信息会隐藏常见 token、secret、password 字段,但不要把密钥写进命令模板;需要密钥时优先让模型脚本自己从环境变量读取。
## 4. MuseTalk 接入提示
效果通常比传统 Wav2Lip 更好,但环境更重。
你需要先在模型仓库中跑通官方 demo,再把官方命令改造成模板。重点确认:
- 是否支持直接传入任意视频。
- 是否需要预处理 avatar。
- 输出是否能指定到 `{output}`
- 是否需要长驻服务或预热。
## 5. LstmSync 接入提示
主项目已有 `resources/lstmsync` 配置,说明它是项目期望的本地数字人口型同步方案之一。可选路线:
- 直接复用主项目 LstmSync 资源包作为独立服务后端。
- 或把 LstmSync 封成命令行脚本,再通过 `command` 后端调用。
需要确认:
- 模型权重位置。
- Python/CUDA/PyTorch 版本。
- 输入参数名和输出路径参数。
- 是否支持 `256m``256o``384m` 等权重选择。
## 6. 新增专用后端建议
`command` 后端跑通后,可以把逻辑固化成专用后端:
```python
class Backend:
name = "wav2lip"
def process(self, audio_path, video_path, output_path, settings):
...
return output_path
```
专用后端需要补充:
- 环境变量配置。
- 模型路径检查。
- 预热逻辑。
- 明确的异常类型。
- 最小单元测试。
## 7. 常见失败原因
- CUDA / PyTorch 版本不匹配。
- ffmpeg 不在 PATH。
- 视频里没有可检测的人脸。
- 输入视频分辨率过高导致显存不足。
- 模型脚本输出到了其它路径,没有写入 `{output}`
- Gradio 端口被占用。
+47
View File
@@ -0,0 +1,47 @@
# 模型选型备忘
## 1. 数字人模型是什么
这里的“数字人”不是大语言模型,也不是单纯图片处理模型。它属于:
- 音频驱动人脸动画
- 口型同步
- 视频生成 / 视频重绘
- 计算机视觉 + 音频特征处理
输入是人物视频和语音,输出是口型跟随语音的新视频。
## 2. 推荐路线
### 快速验证:Wav2Lip / Wav2Lip-HQ
优点:资料多、命令行方式成熟、适合先跑通。
缺点:高清和复杂动作效果有限。
### 效果优先:MuseTalk
优点:现代方案,效果潜力更好。
缺点:部署更重,需要更认真处理依赖和预处理。
### 项目一致性:LstmSync
优点:主项目已有 `resources/lstmsync` 配置,功能定位最贴近。
缺点:需要确认权重、环境和推理脚本是否完整可迁移。
## 3. 硬件建议
- 最低尝试:RTX 3060 12GB。
- 更稳妥:16GB+ 显存。
- 长视频或高清:建议 24GB+ 显存,或做切片处理。
## 4. 不建议第一版做的事
- 不要一开始就训练模型。
- 不要一开始就做多模型动态切换 UI。
- 不要一开始就接公网鉴权和计费。
- 不要把模型权重放进 Git。
先跑通一个真实模型,再做工程化。
+21
View File
@@ -0,0 +1,21 @@
# Protocol
## Gradio endpoint
- API name: `/process_single`
- Audio input parameter: `audio_file`
- Video input parameter: `video_file`
- Output component: single `gr.Video`
The function returns a video object compatible with Gradio client responses:
```json
{
"video": "D:/path/to/result.mp4",
"subtitles": null
}
```
## Notes
The upstream desktop app reads `result["video"]` from `scripts/digital_human_process.py`, so this service intentionally exposes one video output instead of multiple outputs. Adding extra Gradio outputs would change `client.predict` into a tuple and break compatibility.
+75
View File
@@ -0,0 +1,75 @@
# 测试与验收清单
## 1. 本地语法检查
```powershell
uv run python -m compileall src
```
## 1.1 单元测试
```powershell
uv run python -m unittest discover -s tests
```
## 2. 服务启动检查
```powershell
.\scripts\start.ps1
```
浏览器打开:`http://127.0.0.1:7860/`
验收:页面能打开,上传音频和视频后能产出视频。
## 3. Gradio Client 检查
```powershell
.\scripts\test-client.ps1 -Audio C:\test\audio.wav -Video C:\test\avatar.mp4
```
验收:输出包含 `video` 字段,并且路径对应文件存在。
## 4. 主项目兼容检查
```powershell
cd D:\WYF-project\aIzhinengti
python .\scripts\digital_human_process.py http://127.0.0.1:7860/ C:\test\audio.wav C:\test\avatar.mp4
```
验收:返回 `success: true`
## 5. 真实模型效果验收
真实模型接入后,至少用三组样例:
- 正脸短视频 + 10 秒音频。
- 半身人物视频 + 30 秒音频。
- 有轻微转头的视频 + 15 秒音频。
检查项:
- 口型与音频基本同步。
- 输出视频时长接近音频时长或按预期截断。
- 输出画面无明显崩脸、黑屏、花屏。
- 失败时错误能定位到模型、依赖、显存或输入素材问题。
## 6. 性能记录
每次更换模型或参数,记录:
- GPU 型号和显存。
- 输入视频分辨率和时长。
- 音频时长。
- 推理耗时。
- 峰值显存。
- 输出文件大小。
## 7. 发布前检查
- [ ] README 已更新。
- [ ] `.env.example` 已更新。
- [ ] 没有提交模型权重。
- [ ] 没有提交大测试视频。
- [ ] 新增环境变量有说明。
- [ ] 主项目脚本验证通过。