HiAPI
博客

教程

通过 hiapi API 使用 minimax-h3-max 进行多角度图生视频提示词编写

没有镜头角度参数——下面这套提示词写法可以把一张照片变成多镜头片段。

2026年11月3日
通过 hiapi API 使用 minimax-h3-max 进行多角度图生视频提示词编写

minimax-h3-max 能把一张照片变成 5–15 秒的视频,但其端点根本没有“镜头角度”“多视角”或“镜头数量”参数——参数参考列出的受支持输入字段为 prompt、first_frame_image、last_frame_image、duration、resolution 和 aspect_ratio。请把镜头指令写进 prompt,该字段最多接受 7,000 个字符。

所以,一个“多角度”片段——从一个广角建立镜头切到特写,再切到跟拍镜头——并不是你设置的参数,而是你写出来的提示词。本教程涵盖请求结构、在一个生成片段内要求多个镜头角度的提示词模式,以及围绕它的生产级流程。

用这段提示词生成 → 选择 10 秒和 768P。若做图生视频,请添加你的帧图像并省略 aspect_ratio。

前置条件

从你的 hiapi 控制台获取 API 密钥。下面每次调用都使用 Authorization: Bearer YOUR_API_KEY 对共享异步任务端点 POST https://api.hiapi.ai/v1/tasks 进行认证。

最小示例:一张照片,三个镜头角度

first_frame_image 锚定主体和场景,让模型有具体内容可以切走再切回。提示词把每个镜头描述为明确的编号切镜。这个摩托车提示词是代码示例,未附带渲染样例。

一辆红色复古摩托车停在黄昏时分潮湿的城市街道上,霓虹灯招牌映在路面上。镜头 1 - 低角度广角:摄像机保持静止广角镜头,拍摄整辆摩托车,细雨轻轻落下。切到镜头 2 - 特写:摄像机向镀铬前灯和前轮紧密推进,缓慢向右跟拍。切到镜头 3 - 俯视顶拍:摄像机从上方垂直向下俯拍摩托车,缓慢旋转。无文字或字幕。

用这段提示词生成 → 添加你自己的可公开访问的摩托车图像,选择 10 秒和 768P,并省略 aspect_ratio。

import os
import requests
import time

API_KEY = os.environ["HIAPI_API_KEY"]
BASE = "https://api.hiapi.ai/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

payload = {
    "model": "minimax-h3-max",
    "input": {
        "prompt": (
            "A red vintage motorcycle parked on a wet city street at dusk, neon signs reflecting on the pavement. "
            "Shot 1 - low wide angle: the camera holds a static wide shot of the full motorcycle, rain lightly falling. "
            "Cut to Shot 2 - close-up: the camera pushes in tight on the chrome headlight and front wheel, tracking slowly right. "
            "Cut to Shot 3 - overhead top-down: the camera looks straight down at the motorcycle from above, slowly rotating. "
            "No text or subtitles."
        ),
        "first_frame_image": "https://your-cdn.example.com/motorcycle-source.jpg",
        "duration": 10,
        "resolution": "768P",
    },
}

# Frame images and aspect_ratio are mutually exclusive.
def response_data(response):
    response.raise_for_status()
    body = response.json()
    if not isinstance(body, dict) or body.get("code") != 200:
        raise ValueError("Expected a JSON object with code=200")
    data = body.get("data")
    if not isinstance(data, dict):
        raise ValueError("Expected data to be an object")
    return data

# Submit once. An uncertain POST response is not a reason to submit again.
try:
    resp = requests.post(
        f"{BASE}/tasks", headers=HEADERS, json=payload, timeout=(10, 60)
    )
    created = response_data(resp)
    task_id = created.get("taskId")
    if not isinstance(task_id, str) or not task_id.strip():
        raise ValueError("Missing data.taskId")
except (requests.RequestException, ValueError) as exc:
    raise RuntimeError(
        "Could not confirm task creation. Check task records before resubmitting."
    ) from exc

print("taskId:", task_id, flush=True)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
    try:
        resp = requests.get(
            f"{BASE}/tasks/{task_id}", headers=HEADERS, timeout=(10, 60)
        )
        task = response_data(resp)
    except (requests.RequestException, ValueError) as exc:
        raise RuntimeError(
            f"Query failed; retain taskId={task_id} and resume GET for this ID."
        ) from exc

    state = task.get("status")
    if state == "fail":
        raise RuntimeError(f"Task {task_id} failed: {task.get('error')}")
    if state == "success":
        outputs = task.get("output")
        if not isinstance(outputs, list):
            raise RuntimeError(f"Task {task_id}: missing output array")
        video = next(
            (item for item in outputs
             if isinstance(item, dict) and item.get("type") == "video"
             and isinstance(item.get("url"), str) and item["url"]),
            None,
        )
        if video is None:
            raise RuntimeError(f"Task {task_id}: no video URL in output")
        print(video["url"])
        print("expireAt (Unix seconds):", video.get("expireAt"))
        break
    if state not in {"queued", "handling", "archiving"}:
        raise RuntimeError(f"Task {task_id}: unexpected status {state!r}")
    time.sleep(min(3, max(0, deadline - time.monotonic())))
else:
    raise TimeoutError(f"Polling timed out; continue GET with taskId={task_id}")

把 first_frame_image 换成真实、可公开访问的 HTTPS 图像 URL,或者完全去掉它,仅凭文本生成同样的多角度序列——minimax-h3-max 通过同一个 prompt 字段同时处理文生视频和图生视频。

编写提示词:编号镜头模式

三个选择能让你的目标镜头序列清晰明确:

  1. 一句建立场景的话,然后是编号镜头。先描述一次主体和场景,再把每个镜头角度作为各自标注的节拍列出:镜头 1 - [构图]:[动作]。切到镜头 2 - [构图]:[动作]。“切到镜头 N”会明确要求改变镜头角度。
  2. 使用标准电影摄影词汇。低角度广角镜头、俯视顶拍镜头、特写、缓慢推镜、侧向跟拍镜头、手持——这些词能指明你想要的构图和运动。像“另一个酷炫角度”这样含糊的措辞会产生不一致的结果。
  3. 按时长规划镜头数量。duration 是 5 到 15 秒的整数。两到三个镜头比较现实;把五个不同角度塞进 5 秒片段里,每个镜头不到一秒,往往看起来像故障而不是切镜。

first_frame_image 和 last_frame_image 都是可选的,并且彼此独立——可以设置一个、两个或都不设置。提供其中任意一个时,请跳过 aspect_ratio:这些字段互斥,帧图像决定输出的宽高比。另请注意,跨角度并不能保证严格的三维或几何一致性——这是生成式视频模型,不是摄影测量管线,所以即使有首帧锚定,也要预期主体细节在切镜之间会有轻微漂移。

让它适合生产环境

  • 一旦超出脚本规模,优先使用回调而不是轮询。在请求体中加入 "callback": {"url": "https://your-domain.com/hiapi/callback", "when": "final"},当任务到达终态时 hiapi 会 POST 通知,而不是由你在循环中轮询 GET /v1/tasks/{taskId}。
  • 按 taskId 去重。轮询响应和回调都以同一个 taskId 为键——把同一 ID 的重复终态通知视为幂等,而不是多个独立任务。
  • 立即下载输出。成功的任务会返回 data.output[].url 用于临时存储。选择 type 为 video 的输出项,并检查其 expireAt Unix 时间戳(秒)。在处理终态的同一个处理程序中,将其重新上传到你自己的存储。
  • 处理两种失败形态。错误的请求体(不支持的字段、超出范围的 duration、格式错误的图像 URL)会在提交时快速失败并返回 400 INVALID_REQUEST。认证问题返回 401,并带有 error.code: "permission_denied"。生成过程中失败的任务则会在轮询/回调响应中报告 "status": "fail"——在信任 output 之前先检查 status。

相关阅读

常见问题

minimax-h3-max 有专门的多角度或多机位参数吗? 没有。文档中的输入字段是 prompt、first_frame_image、last_frame_image、duration、resolution 和 aspect_ratio。请在 prompt 内描述多个镜头,而不是添加镜头角度字段。

可以把 aspect_ratio 与 first_frame_image 或 last_frame_image 一起设置吗? 不可以。aspect_ratio 与任一帧图像字段互斥。提供的图像决定输出比例。只要传入任一帧图像,就省略 aspect_ratio。

多角度片段可以多长? duration 接受 5 到 15 的整数秒。两到三个不同镜头角度可以较从容地容纳在这个窗口内;超过这个数量往往会把每个镜头压缩到几分之一秒。

主体会在不同角度之间保持完美一致吗? 不保证。minimax-h3-max 是生成式视频模型,所以即使 first_frame_image 锚定了开场帧,细节(精确纹理、细微比例)也可能在切镜之间漂移。请把它视为强创作一致性,而不是像素级精确的多视角重建。

我可以仅凭文本、没有源图像生成多角度片段吗? 可以——省略 first_frame_image 和 last_frame_image,并在 prompt 中描述场景和镜头。纯文本生成使用默认横向画布。若要纵向构图,请提供纵向帧图像且不设置 aspect_ratio,或在编辑器中裁剪/填充保存的视频。

认证失败是什么样子? HTTP 401,响应体类似 {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}。请仔细检查 Authorization: Bearer 请求头,以及密钥是否已从控制台撤销。

复制摩托车镜头序列,并用这段提示词生成 → 选择 10 秒和 768P;添加你的帧图像以引导开场构图。

立即开始构建持久 AI 产物

获取 API 密钥,通过一个基于任务(task)的 API 调用图像、视频和音频模型。

阅读 API 文档