Files
digital_human_backend/readme.md
2025-09-05 00:49:48 +08:00

216 lines
6.5 KiB
Markdown

# 数字人生成服务
本项目提供一个后端服务,用于根据文本和样本媒体(视频、音频)生成数字人。它利用后台线程处理视频和音频处理等资源密集型操作,以实现异步任务处理。
-----
## 系统架构
该服务基于 **Flask** Web 框架,并遵循 **RESTful API** 设计。主要组件包括:
- **API 端点**: 用于文件上传、数字人生成、音频提取和任务状态查询的路由。
- **异步任务处理**: 像视频处理 (`api_extract_audio`) 和数字人生成 (`api_generate_digital_human`) 这样的繁重任务使用 **Python 的 `threading` 模块**在后台非阻塞地处理。这可以防止主 Flask 应用被阻塞,确保 API 保持响应。
- **任务管理**: 一个全局字典 (`TASKS`) 用于存储每个异步任务的状态、进度和结果,并通过一个唯一的 `task_id` 进行访问。
- **文件管理**: 服务使用 `FileManager` 类处理文件上传和存储,将文件组织到 `video``audio` 子目录中。
- **错误处理**: 自定义的 `APIException``404 Not Found``500 Internal Server Error` 错误处理器提供了统一且信息丰富的响应。
整体流程如下:
1. 客户端向生成端点(例如,`/api/digital_human/generate`)发送请求。
2. 服务器验证请求并创建一个带有唯一 `task_id` 的新任务。
3. 服务器生成一个新的后台线程来执行生成逻辑。
4. 服务器立即返回一个 `submitted` 状态和 `task_id` 给客户端。
5. 客户端随后可以轮询 `/api/task/status/<task_id>` 端点,以检查进度并在任务完成时获取最终结果。
-----
## 运行环境
要运行此服务,你需要设置一个包含所需库的 Python 环境。
### 运行要求
- **Python 3.6+**: 代码使用了 f-string 和类型提示,这些都是现代 Python 的标准特性。
- **`moviepy`**: 用于视频和音频处理,特别是从视频文件中提取音频。
- **`Flask`**: 核心 Web 框架。
- **`Flask-CORS`**: 处理跨域资源共享,允许来自不同域的请求。
### 安装
1. 克隆此仓库(或将提供的代码保存为 `app.py`)。
2. 使用 `pip` 安装所需的 Python 包:
```bash
pip install Flask Flask-Cors moviepy
```
3. 确保你的系统已安装 `moviepy` 的必要依赖项,例如 **FFmpeg**。`moviepy` 通常会自动处理,但在某些系统上你可能需要手动安装。
-----
## 部署方法
### 本地开发
1. 确保你已安装所有先决条件。
2. 直接从命令行运行应用程序:
```bash
python app.py
```
3. 服务将在 `http://0.0.0.0:5001` 上可用。
### Docker 部署(推荐)
为了确保一个一致且隔离的环境,强烈推荐使用 Docker 进行部署。
1. **创建 `Dockerfile`**:
```dockerfile
# 使用官方 Python 运行时作为父镜像
FROM python:3.9-slim
# 设置容器中的工作目录
WORKDIR /app
# 将当前目录内容复制到容器的 /app 目录中
COPY . .
# 安装 requirements.txt 中指定的所需包
RUN pip install --no-cache-dir Flask Flask-Cors moviepy
# 暴露应用程序运行的端口
EXPOSE 5001
# 定义环境变量
ENV FLASK_APP=app.py
# 运行应用程序
CMD ["flask", "run", "--host=0.0.0.0", "--port=5001"]
```
2. **创建 `requirements.txt` 文件**:
```txt
Flask
Flask-Cors
moviepy
```
这有助于 Docker 更有效地构建镜像。
3. **构建并运行 Docker 容器**:
```bash
docker build -t digital-human-service .
docker run -p 5001:5001 digital-human-service
```
`-p 5001:5001` 标志将主机上的 5001 端口映射到容器中的 5001 端口。
-----
## API 文档
所有 API 端点都以 `/api` 为前缀。
### 1\. 生成数字人
- **端点**: `POST /api/digital_human/generate`
- **描述**: 启动一个后台任务,根据提供的文本、视频和音频生成数字人视频。
- **请求体**:
```json
{
"speech_text": "Hello, this is a test.",
"sample_video": "my-video-file.mp4",
"sample_voice": "my-voice-file.wav"
}
```
- **成功响应**:
```json
{
"status": "submitted",
"task_id": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890",
"query_url": "/api/task/status/a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890"
}
```
### 2\. 从视频中提取音频
- **端点**: `POST /api/video/extract_audio`
- **描述**: 启动一个后台任务,从视频文件中提取音轨。
- **请求体**:
```json
{
"video_path": "/path/to/my-video.mp4"
}
```
- **成功响应**:
```json
{
"status": "submitted",
"task_id": "f6e5d4c3-b2a1-0987-6543-210fedcba987",
"query_url": "/api/task/status/f6e5d4c3-b2a1-0987-6543-210fedcba987"
}
```
### 3\. 查询任务状态
- **端点**: `GET /api/task/status/<task_id>`
- **描述**: 获取正在运行任务的当前状态。
- **成功响应(待处理/运行中)**:
```json
{
"status": "running",
"progress": 50,
"type": "digital_human",
"params": { ... },
"result": null
}
```
- **成功响应(已完成)**:
```json
{
"status": "completed",
"progress": 100,
"type": "digital_human",
"params": { ... },
"result": {
"uuid": "my-video-uuid",
"download_url": "/download/generated/video/my-video-uuid?task_id=200"
}
}
```
### 4\. 文件上传
- **端点**: `POST /api/upload/video`
- **描述**: 上传视频文件。
- **表单数据**: `file`(视频文件)、`custom_name`(可选)。
- **端点**: `POST /api/upload/audio`
- **描述**: 上传音频文件。
- **表单数据**: `file`(音频文件)、`custom_name`(可选)。
- **成功响应**:
```json
{
"success": true,
"message": "视频上传成功",
"file_info": { ... }
}
```
### 5\. 下载生成的视频
- **端点**: `GET /download/generated/video/<uuid>`
- **描述**: 提供之前生成的视频文件下载。
- **参数**:
- `uuid`: 视频文件的唯一 ID。
- `task_id`(可选): 生成该视频的任务 ID。
### 6\. 文件列表与查找
- **端点**: `GET /api/files/list`
- **描述**: 列出指定目录中可用的文件。
- **查询参数**:
- `directory`: 目录路径。
- `file_type`: `video`、`audio` 或 `all`(默认)。
- **端点**: `GET /api/files/find/<uuid>`
- **描述**: 按 UUID 查找生成的文件。