# minimax-h3/reference-to-video

> MiniMax H3 (Official) supports reference-to-video generation: provide reference images, videos, and audio clips to guide video creation. Combines multimodal references with text prompts to produce 2K video with native stereo audio up to 15 seconds.

- **Provider:** AirCube
- **Category:** reference-to-video
- **Price:** $0.4500 per run

## Key Features

- Reference-guided video generation — use images, videos, and audio as style/content references.
- Up to 9 reference images, 3 reference videos, and 3 reference audio clips per generation.
- Combine multimodal references to guide both visual style and audio characteristics.
- 2K resolution output with native stereo audio, up to 15 seconds.
- Ideal for character-consistent content, style transfer, and audio-guided generation.

## Parameters

| Parameter | Required | Description |
| --- | --- | --- |
| `prompt` | Yes | Text description to guide video generation alongside reference materials (max 7,000 characters). Use <Picture N>, <Video N>, <Audio N> tags to reference uploaded media. |
| `reference_images` | No | Array of reference image URLs to guide visual style (max 9). Formats: JPG, JPEG, PNG, WEBP, HEIC, HEIF. Max 30 MB each. |
| `reference_videos` | No | Array of reference video URLs for motion/style guidance (max 3). H.264/H.265 in MP4/MOV, 2-15 seconds each, total duration ≤ 15s. Max 50 MB each. |
| `reference_audios` | No | Array of reference audio URLs for audio guidance (max 3). WAV or MP3, 2-15 seconds each. Max 15 MB each. Requires at least one reference image or video. |
| `duration` | No | Video length in seconds: 4-15, integer only (default: 5). |
| `aspect_ratio` | No | Output ratio (default: adaptive). |
| `resolution` | No | Output resolution: 768P or 2K (default: 2K). |

## How to Use

1. Upload reference materials: images for visual style, videos for motion, audio for sound.
2. Write a prompt describing how to combine the references into the output video.
3. Select duration and resolution.
4. Click Generate — the model blends your references with the text prompt.

## Code Examples

### Python

```python
import os
import requests

response = requests.post(
    "https://aircube.ai/api/v3/minimax-h3/reference-to-video",
    headers={
        "Authorization": "Bearer " + os.environ["AIRCUBE_API_KEY"],
        "Content-Type": "application/json",
    },
    json={
    "prompt": "Character speaks naturally, following the reference voice and visual style",
    "reference_images": [
        "https://example.com/character-ref.jpg"
    ],
    "reference_audios": [
        "https://example.com/voice-ref.mp3"
    ],
    "duration": "5s",
    "resolution": "2K"
},
    timeout=300,
)
data = response.json()

if data["success"]:
    print("ID:", data["data"]["id"], "Status:", data["data"]["status"])
else:
    print("Error:", data["error"]["message"])
```

### Node.js

```javascript
const response = await fetch("https://aircube.ai/api/v3/minimax-h3/reference-to-video", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.AIRCUBE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "prompt": "Character speaks naturally, following the reference voice and visual style",
  "reference_images": [
    "https://example.com/character-ref.jpg"
  ],
  "reference_audios": [
    "https://example.com/voice-ref.mp3"
  ],
  "duration": "5s",
  "resolution": "2K"
}),
});

const data = await response.json();

if (data.success) {
  console.log("ID:", data.data.id, "Status:", data.data.status);
} else {
  console.error("Error:", data.error.message);
}
```

### cURL

```curl
curl -X POST "https://aircube.ai/api/v3/minimax-h3/reference-to-video" \
  -H "Authorization: Bearer $AIRCUBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Character speaks naturally, following the reference voice and visual style",
  "reference_images": [
    "https://example.com/character-ref.jpg"
  ],
  "reference_audios": [
    "https://example.com/voice-ref.mp3"
  ],
  "duration": "5s",
  "resolution": "2K"
}'
```

### Python (Async)

```python
import os
import time
import requests

# 1. Submit
response = requests.post(
    "https://aircube.ai/api/v3/minimax-h3/reference-to-video",
    headers={
        "Authorization": "Bearer " + os.environ["AIRCUBE_API_KEY"],
        "Content-Type": "application/json",
    },
    json={
    "prompt": "Character speaks naturally, following the reference voice and visual style",
    "reference_images": [
        "https://example.com/character-ref.jpg"
    ],
    "reference_audios": [
        "https://example.com/voice-ref.mp3"
    ],
    "duration": "5s",
    "resolution": "2K"
},
    timeout=300,
)
data = response.json()

if not data["success"]:
    print("Error:", data["error"]["message"])
    exit(1)

generation_id = data["data"]["id"]
print(f"Submitted: {generation_id}")

# 2. Poll until completed
while True:
    time.sleep(5)
    r = requests.get(
        f"https://aircube.ai/api/v3/status/{generation_id}",
        headers={"Authorization": "Bearer " + os.environ["AIRCUBE_API_KEY"]},
    )
    result = r.json()["data"]

    if result["status"] == "completed":
        print(result["output_url"])
        break
    elif result["status"] == "failed":
        print("Generation failed")
        break
```

### Node.js (Async)

```javascript
// 1. Submit
const response = await fetch("https://aircube.ai/api/v3/minimax-h3/reference-to-video", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + process.env.AIRCUBE_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "prompt": "Character speaks naturally, following the reference voice and visual style",
  "reference_images": [
    "https://example.com/character-ref.jpg"
  ],
  "reference_audios": [
    "https://example.com/voice-ref.mp3"
  ],
  "duration": "5s",
  "resolution": "2K"
}),
});
const data = await response.json();

if (!data.success) {
  console.error("Error:", data.error.message);
  process.exit(1);
}

const generationId = data.data.id;
console.log("Submitted:", generationId);

// 2. Poll until completed
while (true) {
  await new Promise((r) => setTimeout(r, 5000));
  const res = await fetch(
    `https://aircube.ai/api/v3/status/${generationId}`,
    { headers: { "Authorization": "Bearer " + process.env.AIRCUBE_API_KEY } },
  );
  const result = (await res.json()).data;

  if (result.status === "completed") {
    console.log(result.output_url);
    break;
  } else if (result.status === "failed") {
    console.error("Generation failed");
    break;
  }
}
```

### cURL (Async)

```curl
# 1. Submit
RESPONSE=$(curl -s -X POST "https://aircube.ai/api/v3/minimax-h3/reference-to-video" \
  -H "Authorization: Bearer $AIRCUBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "prompt": "Character speaks naturally, following the reference voice and visual style",
  "reference_images": [
    "https://example.com/character-ref.jpg"
  ],
  "reference_audios": [
    "https://example.com/voice-ref.mp3"
  ],
  "duration": "5s",
  "resolution": "2K"
}')

ID=$(echo "$RESPONSE" | jq -r '.data.id')
echo "Submitted: $ID"

# 2. Poll until completed
while true; do
  sleep 5
  STATUS_RES=$(curl -s "https://aircube.ai/api/v3/status/$ID" \
    -H "Authorization: Bearer $AIRCUBE_API_KEY")
  STATUS=$(echo "$STATUS_RES" | jq -r '.data.status')

  if [ "$STATUS" = "completed" ]; then
    echo "$STATUS_RES" | jq -r '.data.output_url'
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "Generation failed"; break
  fi
done
```

## Pricing

| Resolution | Duration | Cost |
| --- | --- | --- |
| 768p | 4s | $0.36 |
| 768p | 5s | $0.45 |
| 768p | 6s | $0.54 |
| 768p | 8s | $0.72 |
| 768p | 10s | $0.90 |
| 768p | 12s | $1.08 |
| 768p | 15s | $1.35 |
| 2k | 4s | $0.52 |
| 2k | 5s | $0.65 |
| 2k | 6s | $0.78 |
| 2k | 8s | $1.04 |
| 2k | 10s | $1.30 |
| 2k | 12s | $1.56 |
| 2k | 15s | $1.95 |

### Billing Rules

- 768p / 4s: $0.36.
- 2k / 4s: $0.52.
- Longer durations scale proportionally.
- Failed generations are not charged.

## Best Use Cases

- Character-consistent video generation across multiple scenes.
- Style transfer from reference images to video content.
- Voice/audio-guided generation using reference audio clips.
- Creating variations of existing content with consistent visual identity.

## Pro Tips

- Combine multiple reference types for best results — e.g., reference images for visual style + reference audio for voice.
- Reference audio requires at least one reference image or video in the same request.
- Total reference files across all types cannot exceed 12.
- Reference videos: H.264/H.265 in MP4/MOV, 2-15 seconds per clip, total duration ≤ 15s, max 50 MB each.

## Notes

- Reference-to-video and image-to-video (first_frame/last_frame) modes are mutually exclusive.
- Audio references must be WAV or MP3, 2-15 seconds, max 15 MB each.

## FAQ

**Q: How many references can I provide?**

Up to 9 reference images, 3 reference videos, and 3 reference audio clips — maximum 12 total reference files.

**Q: Can I use reference audio alone?**

No — reference audio must be accompanied by at least one reference image or video.

**Q: What video formats are accepted as references?**

H.264/H.265 video codecs in MP4/MOV containers, 2-15 seconds per clip, max 50 MB.
