角色替换 – 视频生成

namifusion/character-swap/generate

用 Wan2.2-Animate 将视频中选定人物替换为参考图人物,保留原始音轨。

参数

名称类型默认约束说明
track_manifest_url *Track manifest URLtext——analyze 模型返回的 track_manifest_url
mappings *人物映射array<object>——{obj_id, img_urls} 数组。obj_id 来自 analyze 输出;每个人物 1-3 张参考图 URL。
↳obj_id *人物 obj_idnumber——对应 analyze 请求返回的对象标识。
↳img_urls *参考图image_upload—1–3 items与该检测对象关联的参考图片 URL。
resolution分辨率select720p480p | 720p选择输出分辨率或供应商生成模式;较高设置可能需要更长处理时间。
seed随机种子number——用于复现结果的可选随机种子;留空时使用随机值。

输出字段

字段类型说明
videosarray

API

通过统一 REST API 调用本模型;在 API Keys 页获取密钥。

cURL
# 1) Submit — returns { "task_uuid": "..." }
curl -X POST "https://www.namifusion.com/api/v1/marketplace/run/namifusion/character-swap/generate" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "input": {
    "track_manifest_url": "ANALYZE_OUTPUT.track_manifest_url",
    "mappings": [
      {
        "obj_id": 0,
        "img_urls": [
          "https://assets-public.namifusion.com/marketplace/images/2026-06-12/638e1ee18ac7.jpeg"
        ]
      }
    ],
    "resolution": "720p"
  }
}'

# 2) Poll until status is "completed", then read the output URLs
curl "https://www.namifusion.com/api/v1/marketplace/run/tasks/TASK_UUID" \
  -H "Authorization: Bearer YOUR_API_KEY"
Python
import time, requests

API_KEY = "YOUR_API_KEY"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 1) Submit
resp = requests.post(
    "https://www.namifusion.com/api/v1/marketplace/run/namifusion/character-swap/generate",
    headers=HEADERS,
    json={
        "input": {
            "track_manifest_url": "ANALYZE_OUTPUT.track_manifest_url",
            "mappings": [
                {
                    "obj_id": 0,
                    "img_urls": [
                        "https://assets-public.namifusion.com/marketplace/images/2026-06-12/638e1ee18ac7.jpeg"
                    ]
                }
            ],
            "resolution": "720p"
        }
    },
)
resp.raise_for_status()  # 401/402/429/5xx stop here instead of polling a bad task
task = resp.json()

# 2) Poll until a terminal state (completed / failed / cancelled).
#    This model is allowed up to 7200s server-side.
deadline = time.time() + 7260
while task.get("status") not in ("completed", "failed", "cancelled"):
    if time.time() > deadline:
        raise TimeoutError(f"still {task.get('status')} — keep the task_uuid and poll later")
    time.sleep(3)
    poll = requests.get(f"https://www.namifusion.com/api/v1/marketplace/run/tasks/{task['task_uuid']}", headers=HEADERS)
    poll.raise_for_status()
    task = poll.json()

print(task["status"], task.get("output"))
JavaScript
const API_KEY = "YOUR_API_KEY";
const HEADERS = { Authorization: `Bearer ${API_KEY}` };

// 1) Submit
const resp = await fetch("https://www.namifusion.com/api/v1/marketplace/run/namifusion/character-swap/generate", {
  method: "POST",
  headers: { ...HEADERS, "Content-Type": "application/json" },
  body: JSON.stringify({
    "input": {
      "track_manifest_url": "ANALYZE_OUTPUT.track_manifest_url",
      "mappings": [
        {
          "obj_id": 0,
          "img_urls": [
            "https://assets-public.namifusion.com/marketplace/images/2026-06-12/638e1ee18ac7.jpeg"
          ]
        }
      ],
      "resolution": "720p"
    }
  }),
});
if (!resp.ok) throw new Error(`submit failed: ${resp.status} ${await resp.text()}`);
let task = await resp.json();

// 2) Poll until a terminal state (completed / failed / cancelled).
//    This model is allowed up to 7200s server-side.
const deadline = Date.now() + 7260 * 1000;
while (!["completed", "failed", "cancelled"].includes(task.status)) {
  if (Date.now() > deadline) throw new Error(`still ${task.status} — keep the task_uuid and poll later`);
  await new Promise((r) => setTimeout(r, 3000));
  const poll = await fetch(`https://www.namifusion.com/api/v1/marketplace/run/tasks/${task.task_uuid}`, { headers: HEADERS });
  if (!poll.ok) throw new Error(`poll failed: ${poll.status}`);
  task = await poll.json();
}

console.log(task.status, task.output);

文档

Character Swap - Generate

将分析后视频中的指定人物替换为参考角色,并保留原始音轨。

Character Swap Generate 是两阶段工作流的第二步。它使用 Analyze 返回的 track_manifest_url 和 obj_id,再通过 mappings 为每个选定人物分配 1 至 3 张参考图片。video_url 必须与分析阶段使用的视频完全相同,并且两个阶段的分辨率必须保持一致。

核心特性

  • 按人物精确替换:使用 Analyze 返回的 obj_id 明确选择每个替换目标。
  • 支持多人物映射:在 mappings 中添加多个项目,分别配置视频中的不同人物。
  • 每人 1 至 3 张参考图:可提供多个外观参考,补充不同角度和人物细节。
  • 保留原始音频:生成结果会维持输入视频的原始音轨。
  • 480p / 720p 输出:可按目标质量和现有价格档位选择分辨率。

技术规格

项目说明
工作流Character Swap 第 2 步
必填输入video_url、track_manifest_url、mappings
mappings 格式{obj_id, img_urls} 对象数组
参考图片每个人物 1 至 3 个 URL
分辨率480p、720p(默认)
视频上限30 秒
可选输入seed
输出保留原始音频的视频 URL

基本流程

  1. 使用 Character Swap Analyze 处理源视频。
  2. 从返回的 objects 中选择需要替换的 obj_id。
  3. 在 mappings 中为每个 ID 配置对应的参考图片 URL。
  4. 提交同一视频和 Analyze 返回的清单,并轮询到生成完成。

价格

现有 Marketplace 定价为 480p 每 5 秒 40 积分、720p 每 5 秒 75 积分,视频最长 30 秒。本次文档更新不会修改价格。

使用建议

建议为每个人物使用清晰、主体完整的参考图片,并尽可能补充略有差异的角度。obj_id、视频和清单必须来自同一次 Analyze 结果。不要在两个阶段之间切换分辨率,也不要复用其他视频生成的清单。