MiniMax H3 Output Acceptance: MP4 Duration and Stereo Audio

After a MiniMax H3 task completes, verify the downloaded media before admitting it to your application. A useful file check records the MP4 container, video and audio durations, audio channel layout, and whether the streams decode without errors.
The MiniMax H3 model page describes MP4 output with native stereo audio. This tutorial turns those properties into a local acceptance policy. Its test clips are synthetic; it does not report a new MiniMax generation or measured model output.
Start with the completed task and original request
Keep the input.duration you submitted, the task ID, the terminal response, and the downloaded file together. In the documented MiniMax H3 response, the asset URL is data.output.video. Check data.status == "completed" before downloading it.
MiniMax H3 requests use model: "Qubico/minimax-h3" with task_type: "txt2video" or "img2video". The current documentation specifies integer durations from 5 through 15 seconds. For the full submit-and-poll flow, use the existing MiniMax H3 API guide; this article starts at output acceptance.
A task marked failed has not passed this gate. A polling timeout leaves its outcome unresolved. Continue reading the original task instead of creating a replacement simply to obtain a downloadable URL.
Define the file policy
| Check | This example's acceptance rule |
|---|---|
| File | Present and nonempty |
| Container | MP4-family demuxer plus an explicitly allowed MP4 major brand |
| Video | A video stream that is not merely attached cover art |
| Audio | First audio stream has two channels and a stereo layout |
| Duration | Container, video, and audio durations are finite, positive, and within the chosen tolerance |
| Decode | Selected video and audio streams decode without an FFmpeg error |
The default duration tolerance below is one second. That is an application choice, not an API guarantee. For a stricter delivery format, set an appropriate tolerance and document it with the result.
The MP4 brand allowlist avoids treating a QuickTime MOV as MP4 merely because FFprobe reports a shared mov,mp4,... demuxer. This small allowlist may reject other valid container brands; review those explicitly before extending it.
Run the acceptance check
Install Python 3.10 or later and an FFmpeg distribution that provides both ffprobe and ffmpeg on PATH. Save the following as accept_minimax_h3.py:
"""Inspect a downloaded clip. No API calls; a pass concerns only this file."""
import argparse
import hashlib
import json
import math
import subprocess
from pathlib import Path
MP4_BRANDS = {"isom", "iso2", "iso4", "iso5", "iso6", "mp41", "mp42", "avc1", "M4V ", "dash"}
def accept(path, requested, tolerance=1.0):
requested, tolerance = float(requested), float(tolerance)
if not math.isfinite(requested) or not 5 <= requested <= 15 or not requested.is_integer():
raise ValueError("Requested duration must be an integer from 5 through 15")
if not math.isfinite(tolerance) or tolerance < 0:
raise ValueError("Tolerance must be finite and nonnegative")
file = Path(path).resolve()
if not file.is_file() or file.stat().st_size == 0:
raise ValueError("Missing or empty file")
probe = subprocess.run([
"ffprobe", "-v", "error", "-show_format", "-show_streams", "-of", "json", str(file)
], check=True, capture_output=True, text=True, timeout=60)
data = json.loads(probe.stdout)
format_data = data.get("format") or {}
brand = (format_data.get("tags") or {}).get("major_brand")
if "mp4" not in format_data.get("format_name", "").split(",") or brand not in MP4_BRANDS:
raise ValueError(f"Container is outside this example's MP4 allowlist: brand={brand!r}")
video = next((s for s in data.get("streams", []) if s.get("codec_type") == "video"
and not s.get("disposition", {}).get("attached_pic")), None)
audio = next((s for s in data.get("streams", []) if s.get("codec_type") == "audio"), None)
if video is None:
raise ValueError("No video stream")
if audio is None:
raise ValueError("No audio stream")
if audio.get("channels") != 2 or audio.get("channel_layout") != "stereo":
raise ValueError("Expected a two-channel stereo layout on the first audio stream")
durations = {"container": float(format_data.get("duration", "nan")),
"video": float(video.get("duration", "nan")),
"audio": float(audio.get("duration", "nan"))}
for name, actual in durations.items():
if not math.isfinite(actual) or actual <= 0 or abs(actual - requested) > tolerance:
raise ValueError(f"{name} duration invalid or outside tolerance: {actual}")
# Metadata alone cannot detect every truncated or corrupt encoded frame.
subprocess.run([
"ffmpeg", "-v", "error", "-xerror", "-i", str(file),
"-map", f"0:{video['index']}", "-map", f"0:{audio['index']}", "-f", "null", "-"
], check=True, capture_output=True, timeout=120)
return {"status": "pass", "file": file.name,
"sha256": hashlib.sha256(file.read_bytes()).hexdigest(),
"major_brand": brand, "requested_seconds": requested,
"tolerance_seconds": tolerance, "measured_seconds": durations,
"audio_channels": audio["channels"], "channel_layout": audio["channel_layout"],
"decode": "passed"}
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("file")
parser.add_argument("requested", type=float)
parser.add_argument("--tolerance", type=float, default=1.0)
args = parser.parse_args()
print(json.dumps(accept(args.file, args.requested, args.tolerance), indent=2))For a request that asked for five seconds:
python3 accept_minimax_h3.py minimax-h3-result.mp4 5 --tolerance 1 > acceptance.jsonA successful exit prints a JSON record containing the local SHA-256, requested duration, all three measured durations, audio channel layout, and decode result. A missing stream, mismatched duration, unreadable file, or decode error exits unsuccessfully. Do not use the existence of acceptance.json alone as success: shell redirection can create an empty file before the check runs.
Interpret a rejection
| Finding | Follow-up |
|---|---|
| Empty or unreadable file | Check download HTTP status and retry fetching the existing output |
| Duration mismatch | Compare against the original submitted duration and selected tolerance |
| No audio stream | Preserve the original clip and task record; check whether the product can accept a silent clip |
| Mono or unknown layout | Keep it outside a workflow that explicitly requires stereo |
| Decode failure | Investigate incomplete transfer or corruption before reusing the file |
| Unrecognized MP4 brand | Inspect the container and destination requirements before changing the allowlist |
Do not hide a source rejection by silently padding duration, adding a silent audio stream, or transcoding before recording the original. If your application accepts other outputs, define a separate policy and retain the original inspection record.
What a pass establishes
A pass establishes properties of the local bytes inspected at that time: allowed container brand, video stream, two-channel stereo layout, duration within the selected tolerance, and successful decoding. It does not establish that the channels contain distinct audible information, that speech matches lip movements, that the prompt was followed, or that the clip is cleared for publication. Review those separately.
Keep the source MP4 hash, request, task response, and acceptance JSON together. If you transcode the clip, inspect the new file separately so the original and transformed result are distinguishable.
FAQ
Why check all three durations?
The container duration can hide a shorter audio or video stream. Recording each stream's duration exposes that mismatch.
Does two-channel stereo metadata prove stereo sound?
No. It establishes the declared layout and channel count. Silent tracks or duplicated mono content can still have two channels; use listening or signal analysis if that distinction matters.
Does this test guarantee visual quality?
No. Decoding and metadata checks establish technical properties. Visual review and application-specific checks remain separate.
Sources checked September 17, 2026: MiniMax H3 generate-video documentation, MiniMax H3 model guide, and FFprobe documentation.


