tutorial5 分钟阅读

用 MiniMax H3 API 搭建自动化图生视频(R2V)流水线

用 MiniMax H3 搭建自动化图生视频流水线的工程教程:首帧输入、素材暂存、有截止时间的任务轮询,以及 ToAPIs 前端当前请求约定。

ToAPIs 研发评测组
TL;DR - 核心要点
  • MiniMax H3 的帧模式 R2V 用 first_frame_image(以及可选的 last_frame_image)锚定成片;这两个字段都是最多一张图的列表。
  • 同一请求中不要把首/尾帧输入与 reference_images、reference_videos 或 reference_audio 混用。
  • 稳健的 worker 会先暂存可访问的素材,再提交 POST /v1/videos/generations,然后以有上限的指数退避轮询任务状态端点。
  • 无人值守运行前,请确认上传格式、响应结构以及当前账户报价;本文不是时延或价格基准测试。

用 MiniMax H3 API 搭建自动化图生视频(R2V)流水线

目标模型: minimax-h3
推理端点: https://api.toapis.com/v1/videos/generations
相关阅读: MiniMax H3 API 指南 · 运镜提示词指南 · H3 与 Turbo 如何选择


1. 核心摘要与性能速览 (TL;DR)

  • 目标:用 MiniMax H3 帧模式把静帧做成短片,并把提交与轮询封装进可无人值守运行的 worker。
  • 输入:first_frame_image 为单元素列表;可选 last_frame_image 为单元素列表;一条描述镜头如何离开或环绕该锚点的提示词;基础 minimax-h3 上整数时长 4–15 秒。
  • 模式:帧输入与参考媒体互斥。Turbo(minimax-h3-max-turbo)不接受参考媒体;不要把参考字段拷进 Turbo 请求体。
  • Worker:暂存可访问的素材,只 POST 一次,持久化任务标识,以退避和硬截止时间轮询,再把结果 URL 存进你自己的系统。
  • 范围:这是针对当前 ToAPIs 前端约定的集成指南,不是时延、可用性或价格基准测试。

2. 流水线蓝图

无人值守的 R2V worker 应把调用方的 HTTP 请求与耗时渲染解耦:

  1. 接收 产品侧的源静帧和运动提示词。
  2. 暂存 图片:走文档中的上传流程,或使用你有权拉取的 URL。优先使用带短时、可访问定位符的对象存储,而不是私有磁盘路径。
  3. 提交 一次带有 model、prompt、duration 和 first_frame_image 的 POST /v1/videos/generations。
  4. 轮询 文档中的任务状态端点,使用有上限的指数退避和总截止时间。
  5. 交付 结果视频 URL:通过你自己的通知路径(队列、邮件或产品 webhook)。在创建第二次计费任务前先查状态。

从静帧经网关和轮询环到输出帧的抽象 R2V 流水线

图 1:静帧先被暂存,再一次性提交到 ToAPIs generations 网关,轮询到终态后由你的服务发出成片。

多数 400 错误可以靠这些提交前检查避免:

  • 使用账户已启用的精确模型 ID(minimax-h3、minimax-h3-max 或 minimax-h3-max-turbo,不要自造别名)。
  • 时长为整数:基础 H3 为 4–15 秒,Max 家族为 5–15 秒。
  • first_frame_image 和 last_frame_image 都是最多一张图的列表。
  • 同一请求中不要同时发送 reference_images、reference_videos 或 reference_audio。
  • 当前前端在帧模式下会把 ratio 强制为 adaptive。让静帧形状贴近目标画布(例如宽屏用 1920×1080,竖屏用 1080×1920),以减少意外裁切。
  • 约定字段名是 ratio,不是 aspect_ratio。

帧模式下仍然可以使用运镜提示词;详见 运镜提示词指南。请把括号标签当作提示词助手,而不是原生命令。


3. 生产级实现:cURL 与 Python

步骤 1:cURL 首帧请求

bash
curl -X POST "https://api.toapis.com/v1/videos/generations" \
  -H "Authorization: Bearer $TOAPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "[Dolly Forward] Rain falling onto neon asphalt, steam rising from grates, cinematic reflections",
    "duration": 6,
    "ratio": "16:9",
    "first_frame_image": ["https://example.com/starting-frame.jpg"]
  }'

请把占位 URL 换成文档上传流程返回的素材标识或 URL。已发布的 H3 约定把 first_frame_image 写成数组,而不是单个字符串。

若还要引导尾帧,在同一帧模式请求中加入 "last_frame_image": ["https://example.com/ending-frame.jpg"]。这是标准帧模式,不是 Turbo 独有的实验开关。

步骤 2:带有界轮询的 Python worker

上线前请将 task_id、status 和 video_url 与账户文档中的响应结构对齐。

python
import os
import time
import requests
from typing import Any

API_KEY = os.environ["TOAPIS_API_KEY"]
BASE_URL = "https://api.toapis.com/v1"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}


class MiniMaxR2VPipeline:
    def trigger_r2v(
        self,
        image_ref: str,
        prompt: str,
        duration: int = 6,
        last_frame_ref: str | None = None,
    ) -> str:
        if not 4 <= duration <= 15:
            raise ValueError("Base minimax-h3 accepts integer durations of 4-15 seconds")
        payload: dict[str, Any] = {
            "model": "minimax-h3",
            "prompt": prompt,
            "duration": duration,
            "ratio": "16:9",
            "first_frame_image": [image_ref],
        }
        if last_frame_ref:
            payload["last_frame_image"] = [last_frame_ref]
        res = requests.post(
            f"{BASE_URL}/videos/generations",
            headers=HEADERS,
            json=payload,
            timeout=30,
        )
        res.raise_for_status()
        data = res.json()
        task_id = data.get("task_id") or data.get("id")
        if not task_id:
            raise RuntimeError(f"Unexpected submission envelope: {data}")
        return task_id

    def poll_until_complete(self, task_id: str, max_timeout: int = 180) -> dict[str, Any]:
        start = time.time()
        interval = 3.0
        poll_url = f"{BASE_URL}/videos/tasks/{task_id}"
        while time.time() - start < max_timeout:
            res = requests.get(poll_url, headers=HEADERS, timeout=15)
            res.raise_for_status()
            data = res.json()
            status = data.get("status")
            if status in {"succeeded", "success"}:
                return {
                    "status": "success",
                    "task_id": task_id,
                    "video_url": data.get("video_url"),
                    "elapsed_seconds": round(time.time() - start, 2),
                }
            if status in {"failed", "error"}:
                return {
                    "status": "error",
                    "task_id": task_id,
                    "error": data.get("error", "Generation failed"),
                }
            time.sleep(interval)
            interval = min(interval * 1.1, 6.0)
        return {
            "status": "timeout",
            "task_id": task_id,
            "error": f"Exceeded {max_timeout}s; check task status before retrying",
        }


if __name__ == "__main__":
    pipeline = MiniMaxR2VPipeline()
    # Replace with an uploaded asset identifier or a URL you are authorized to fetch.
    image_ref = "https://example.com/starting-frame.jpg"
    prompt = "[Dolly Forward] Rain falling onto neon asphalt, steam rising from grates, cinematic reflections"
    task_id = pipeline.trigger_r2v(image_ref, prompt)
    print("Task:", task_id)
    print("Result:", pipeline.poll_until_complete(task_id))

超时并不等于已确认失败。记录任务标识(不要记录 API Key 或私有媒体 URL),先查状态,再决定是否重新提交。


4. 错误处理与状态码对照

下表中的分类只是排查起点,并不保证与 ToAPIs 的精确错误码一一对应。

HTTP 状态码常见分类建议操作
400字段无效、媒体不可达或不受支持,或帧/参考模式混用校验模型 ID、时长、作为单元素列表的 first_frame_image,并确认未携带参考字段
401API Key 缺失或无效在 ToAPIs 控制台轮换密钥
429速率或并发限制带抖动退避,并在本地排队
5xx 或网络超时网关或上游暂时异常再创建任务前先重读任务状态

WaitTime=min⁡(MaxWait,BaseInterval×2attempt)+Uniform(0,1)\text{WaitTime} = \min(\text{MaxWait}, \text{BaseInterval} \times 2^{\text{attempt}}) + \text{Uniform}(0, 1)

上传失败应视为硬停止:没有有效的素材标识就不要提交生成请求。


5. 定价与 FinOps ROI

Estimated cost=successful output seconds×current account rate per second\text{Estimated cost} = \text{successful output seconds} \times \text{current account rate per second}

  • 以有日期的账户报价为准。 不要把规划稿中的每秒单价或 SLA 百分比写进生产预测。费率和失败任务是否计费可能因模型和路由而异。
  • 官方厂商合同 可能要求承诺或预付门槛。请确认你的 ToAPIs 账户是否纯按量计费,以及上游失败如何结算。
  • 流水线纪律 才是实际的 FinOps 杠杆:每个镜头只提交一次,超时先查状态再重试,提示词模板与任务一同保存,并把时长控制在刚好够用的最短成片。
  • 需要 1080P?先确认精确的 canonical minimax-h3-max ID 是否已启用。需要 Turbo?使用 minimax-h3-max-turbo 并省略参考媒体字段。细节见 选型指南。

6. 常见问题

结构化问答见 frontmatter 中的 FAQ。摘要:让静帧贴近目标画布;尾帧引导是标准帧模式(各最多一张图);使用文档中的上传流程而不是私有路径;本指南通过轮询获取状态,并不假定存在 ToAPIs webhook。


7. 行动清单

  • 在 ToAPIs 控制台 领取 API Key。
  • 通过文档中的上传流程暂存一张静帧,并用 cURL 首帧请求做冒烟测试。
  • 接入带 180 秒轮询截止时间的 Python worker,并在超时时禁止重复提交。
  • 批量跑任务前,先复习 H3 请求约定 和 运镜提示词指南。

本文提到的模型与接口

MiniMaxVIDEO

minimax-h3

当前费率:20.8 credits /second
MiniMaxVIDEO

minimax-h3-max

当前费率:8 credits /second
ToAPIsAI Model

minimax-h3-max-turbo

当前费率:查看实时价格

相关技术文章

tutorial3 分钟阅读

Seedance 2.0 Mini API 评测:低成本高吞吐视频生成

面向开发者的 Seedance 2.0 Mini 评测:约 16–20 秒出片、原生 720p/24fps,以及 $0.012/秒的高并发社媒与广告流水线成本结构。

TO
ToAPIs 研发评测组
#Seedance 2.0 Mini