0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MiniMax H3 Normal API を最短で動かす:送信 → 状態確認 → 保存(8秒 $0.14 から)

0
Posted at

W45-Qiita-01.png

この記事では、BeatAPI 経由で MiniMax H3 Normal の動画タスクを1本送り、状態を確認して、完成した動画を保存するまでの最小構成をまとめます。

動画生成 API でよくある失敗は、「送信が成功した」と「動画ができた」を同じものとして扱うことです。MiniMax H3 Normal も非同期 API なので、送信した瞬間に動画は返ってきません。タスクIDを先に保存し、終わるまで確認する流れを最初に作っておくと、タイムアウトのたびに同じ動画をもう1本作ってしまう事故を防げます。

前提

  • BeatAPI の API キー(サーバー側の環境変数 BEATAPI_API_KEY に置く。ブラウザの JavaScript には入れない)
  • curl、Node.js 18 以上
  • 料金は 2026年11月5日時点の beatapi.io の表示価格です。まとめて生成する前に料金ページで再確認してください。

料金(8秒・1回あたり)

解像度 料金
480p $0.14
768p $0.16
1080p $0.20

モデルIDは minimax-h3-normal で、指定できる解像度は 480p / 768p / 1080p の3つです。2K や 4K はありません。何も指定しないと 768p になります。

おすすめは「下書きは 480p で回し、採用するカットだけ 1080p で作り直す」です。

1. タスクを送信して ID を保存する

curl --fail-with-body -X POST https://api.beatapi.io/v1/videos/tasks \
  -H "Authorization: Bearer $BEATAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: product-0001-h3n-draft-v1" \
  -d '{
    "model": "minimax-h3-normal",
    "prompt": "A white serum bottle on a wet black stone. Soft side light, slow push-in, no text overlay.",
    "duration": 8,
    "aspect_ratio": "16:9",
    "resolution": "480p"
  }'

指定できる値(公開 OpenAPI の MinimaxH3NormalVideoRequest より):

パラメータ 値
duration 5〜15 の整数(秒)。省略すると 5
aspect_ratio 16:9 / 9:16 / 1:1 / 4:3 / 3:4 / 21:9
resolution 480p / 768p / 1080p(小文字の p)
images 開始フレーム1枚、または開始・終了フレーム2枚
reference_images / reference_videos 参照入力。images とは同時に使えない

音声のオン・オフを切り替えるパラメータはありません。生成される動画には音声が付きます。尺を省略すると 5秒になるので、8秒で見積もるなら duration: 8 を明示します。

作成に成功すると、data にタスクが返ります。

{
  "data": {
    "id": "task_8K2qA",
    "object": "task",
    "task_kind": "video",
    "model": "minimax-h3-normal",
    "status": "queued",
    "output": null,
    "request_id": "req_abc123",
    "error_code": null,
    "error_message": null
  }
}

ここで大事なのは2つです。

  • data.id は、画面を更新するより先に保存する。自社のジョブID、Idempotency-Key、送った設定も一緒に残す。
  • 応答を受け取る前に通信が切れたら、同じ本文・同じ Idempotency-Key で再送する。キーを変えると別のタスクになり、同じ動画を二重に作ってしまうことがあります。

2. 状態を確認する

curl --fail-with-body https://api.beatapi.io/v1/tasks/task_8K2qA \
  -H "Authorization: Bearer $BEATAPI_API_KEY"

status は queued → processing → succeeded または failed と進みます。前の2つの間は待ち、後ろの2つで止めます。

Node.js で、送信から保存までを1ファイルにまとめるとこうなります。

// h3n.ts  — 実行例: npx tsx h3n.ts
import { writeFile } from "node:fs/promises";

const baseUrl = "https://api.beatapi.io";
const headers = {
  Authorization: `Bearer ${process.env.BEATAPI_API_KEY}`,
  "Content-Type": "application/json",
};
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

async function submit(prompt: string, key: string): Promise<string> {
  const res = await fetch(`${baseUrl}/v1/videos/tasks`, {
    method: "POST",
    headers: { ...headers, "Idempotency-Key": key },
    body: JSON.stringify({
      model: "minimax-h3-normal",
      prompt,
      duration: 8,
      aspect_ratio: "16:9",
      resolution: "480p",
    }),
  });
  if (!res.ok) throw new Error(`submit failed: ${res.status} ${await res.text()}`);
  const { data } = await res.json();
  return data.id; // まず保存する
}

async function waitForTask(taskId: string) {
  let delayMs = 5_000;
  const deadline = Date.now() + 12 * 60_000;

  while (Date.now() < deadline) {
    const res = await fetch(`${baseUrl}/v1/tasks/${taskId}`, { headers });
    if (res.status === 429) {
      // Retry-After を秒で読む。読めなければ 10 秒待つ
      const ra = Number(res.headers.get("retry-after"));
      await sleep((Number.isFinite(ra) && ra > 0 ? ra : 10) * 1_000);
      continue;
    }
    if (res.ok) {
      const { data } = await res.json();
      if (data.status === "succeeded" || data.status === "failed") return data;
    } else if (res.status < 500) {
      throw new Error(`task query failed: ${res.status}`);
    }
    await sleep(delayMs + Math.floor(Math.random() * 1_000));
    delayMs = Math.min(Math.round(delayMs * 1.35), 15_000);
  }
  // 待つのをやめるだけ。タスクIDは残して、あとで照合する
  throw new Error(`client deadline reached; keep the task id: ${taskId}`);
}

async function main() {
  const id = await submit(
    "A white serum bottle on a wet black stone. Soft side light, slow push-in, no text overlay.",
    "product-0001-h3n-draft-v1",
  );
  console.log("task id:", id);

  const task = await waitForTask(id);
  if (task.status === "failed") {
    console.error("failed:", task.error_code, task.error_message);
    return;
  }

  const media = task.output?.media?.find((m: any) => m.type === "video");
  if (!media?.url) throw new Error("no video in output");

  const file = await fetch(media.url);
  if (!file.ok) throw new Error(`download failed: ${file.status}`);
  await writeFile(`${id}.mp4`, Buffer.from(await file.arrayBuffer()));
  console.log("saved:", `${id}.mp4`);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});

期限に達しても、それは「こちらが待つのをやめた」というだけで、タスクが失敗したわけではありません。新しく送り直す前に、保存したIDでもう一度確認してください。

3. 動画を保存する

成功すると data.output.media[] に動画が入ります。

{
  "data": {
    "id": "task_8K2qA",
    "status": "succeeded",
    "output": {
      "media": [
        {
          "type": "video",
          "url": "https://media.beatapi.io/outputs/task_8K2qA/video.mp4",
          "mime_type": "video/mp4"
        }
      ]
    }
  }
}

type: "video"、mime_type、URL に実際に届くかを確認してから「完成」にします。URL は永久保存ではないので、長く使う動画は自社のストレージにコピーし、タスクIDと紐づけておきます。

4. 予算の目安

商品動画を1本採用するまでの例です(いずれも8秒)。

工程 設定 本数 金額
下書き minimax-h3-normal・480p 5本 $0.70
仕上げ minimax-h3-normal・1080p 1本 $0.20
合計 $0.90

これは生成費の試算です。採用までに何本かかるかはプロンプトと用途によって変わるので、最初の数商品で実際の本数を記録してから見積もりを固めます。

5. うまくいかないとき

現象 やること
queued のまま長い 同じIDで確認を続ける。代わりのタスクを送らない
こちらの通信がタイムアウト 新規送信の前に、保存したIDを確認する
ID を受け取る前に切れた 同じ本文・同じ Idempotency-Key で再送する
400 が返る resolution の表記(720p は不可、768p)と images / reference_* の併用を確認する
failed で終わった error_code と error_message を保存し、入力を直すか判断する

まとめ

  • モデルIDは minimax-h3-normal、解像度は 480p / 768p / 1080p
  • duration は省略すると5秒。8秒で見積もるなら明示する
  • 「IDを保存 → 状態確認 → 出力を検証して保存」の順を崩さない

出典・確認日

  • BeatAPI 公開 API ドキュメント(openapi.json の MinimaxH3NormalVideoRequest、タスク取得):2026年11月5日確認
  • 料金:api.beatapi.io/v1/pricing と beatapi.io 料金ページ(8秒):2026年11月5日確認
  • 記事中のレスポンス例は公開スキーマに沿った例で、実際の請求額と照合したものではありません

モデルの仕様と料金:https://beatapi.io/minimax-h3-api?variant=minimax-h3-normal

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?