---
name: sophnet-infinite-talk
description: 当用户需要生成数字人视频（照片 + 音频驱动说话）时使用。接收人物形象图片 URL 和驱动音频 URL，在主会话中创建任务，然后在子会话中轮询查询任务进度，任务完成或失败后将结果报回主会话。
---

# Sophnet Infinite Talk（数字人）

## 概述

使用 `scripts/gen.py` 调用 Sophnet InfiniteTalk 接口，通过图片 + 音频驱动生成数字人说话视频。

脚本路径：`{baseDir}/scripts/gen.py`

## 何时使用

- 用户要求"生成数字人视频"、"让照片说话"、"图片 + 音频合成视频"
- 用户提供了人物照片和音频，希望生成说话视频
- 用户想要数字人、虚拟人、照片驱动等功能

## 输入参数

| 参数 | 必填 | 说明 |
|------|------|------|
| `--image-url` | 是 | 人物形象图片 URL 或本地文件路径（本地文件会自动上传 OSS 转为 URL） |
| `--audio-url` | 是 | 驱动音频 URL 或本地文件路径（本地文件会自动上传 OSS 转为 URL） |
| `--prompt` | 否 | 动作/表情提示词（默认: "自信的面对镜头"） |

## 提取本地文件路径（如适用）

当用户在聊天中上传图片或音频时，文件通常保存在工作区的 `media/inbound/images/` 或 `media/inbound/audio/` 目录下。可通过 Media Understanding 日志获取确切的绝对路径。

典型日志格式：

```
[Media Understanding] Resolved relative path: "media/inbound/images/xxx.jpg" -> "/absolute/path/to/workspace/media/inbound/images/xxx.jpg"
```

使用解析后的绝对路径作为 `--image-url` 或 `--audio-url` 参数（脚本会自动上传 OSS 转为 URL）。

## 处理流程（必须遵循）

### 第一步：主会话 — 创建任务

在主会话中调用 `create` 子命令提交任务：

```bash
# 使用 URL
uv run {baseDir}/scripts/gen.py create \
  --image-url "https://example.com/photo.png" \
  --audio-url "https://example.com/audio.mp3" \
  --prompt "自信的面对镜头"

# 使用本地文件（自动上传 OSS）
uv run {baseDir}/scripts/gen.py create \
  --image-url "/path/to/photo.png" \
  --audio-url "/path/to/audio.mp3"
```

成功输出示例：

```json
{"task_id": "7iOckhZZjgx6gzbESAqL1n"}
```

- 记录 `task_id`，向用户回复：**任务创建成功，已经创建子会话进行任务监控，完成后会通知您**
- 如果返回 `error` 字段，直接告知用户失败原因。

### 第二步：创建子会话 — 轮询查询任务

脚本的 `query` 子命令执行**单次查询**并返回结果，**轮询循环由调用方（子会话）负责实现**。每 10 秒调用一次 `query`，最多轮询 360 次（约 1 小时超时）：

```bash
uv run {baseDir}/scripts/gen.py query --task-id "<task_id>"
```

可能的返回值：

- 进行中：`{"status": "processing", "video_url": null}`
- 成功：`{"status": "succeeded", "video_url": "https://..."}`
- 失败：`{"status": "failed", "error": "失败原因"}`

轮询规则：
- `status` 为 `succeeded` 且 `video_url` 非空 → 停止轮询，获取 `video_url`
- `status` 为 `failed` 或包含 `error` → 停止轮询，获取错误信息
- 单次查询网络错误（返回 `{"error": "..."}` 无 `status` 字段）→ 视为临时失败，继续轮询（连续 3 次网络错误再终止）
- 其他状态（如 `processing`、`queued`）→ 等待 10 秒后继续查询

### 第三步：报告结果到主会话

将子会话获取的最终结果报回主会话：

- **成功**：将 `video_url` 展示给用户
- **失败**：将错误信息展示给用户，引导重试

### 第四步：自动清理子会话（必须执行）

在子会话完成结果回传后，**必须立即自动删除该子会话**，避免会话资源残留。

清理规则：
- 成功回传主会话后，立即删除子会话。
- 失败回传主会话后，立即删除子会话。
- 超时回传主会话后，立即删除子会话。
- 删除失败时，向主会话报告清理失败原因，并重试 1 次。

## 输出格式

成功：

```text
🎬 数字人视频生成成功！
📸 使用图片: ![image](image_url)
🎵 使用音频: <audio controls src="audio_url"></audio>
🎭 动作提示: [prompt]
✅ 生成视频: <video controls width="100%" src="video_url"></video>
⚠️ 提示: 本内容由AI生成，视频保存24小时，请及时下载保存!
```

失败：

```text
❌ 数字人视频生成失败
原因: [error]
💡 建议: 请检查图片和音频链接是否有效，或稍后重试
```

## 失败处理

- 若创建任务失败，直接告知用户失败原因。
- 若轮询超时（1 小时），告知用户任务仍在处理中，可稍后重试。
- 若单次查询网络错误，继续重试；连续 3 次网络错误再终止轮询并告知用户。
- 引导用户检查图片和音频链接是否有效。

## 注意事项

- `--image-url` 和 `--audio-url` 必填，缺少任何一个都无法创建任务。
- `--prompt` 可选，有默认值 "自信的面对镜头"，用于控制数字人的动作和表情。
- 任务创建（主会话）和轮询查询（子会话）分两步执行，避免主会话长时间阻塞。
- 子会话在最终结果回传主会话后必须自动删除，不能保留空闲子会话。
- 脚本所有输出均为 JSON 格式（包括错误），便于程序化解析。
- 视频生成可能需要较长时间，轮询超时上限为 1 小时，链接有效期 24 小时。
