A frame from the 2K clip we kept, a regenerated 768P preview. The leather shop in this test, Bellwick, is fictional.
Most write-ups of a new video model judge it by watching the output. That is the final check, but a Mac can answer several questions first: is the file what you asked for, does it have two real audio channels, does the system say it can decode it, and how much of its size can you remove?
We spent an evening running MiniMax H3 from Terminal on a single Mac and checking everything we could from the command line. MiniMax H3 is a general multimodal video model that MiniMax released on July 31, 2026. It generates clips of 4 to 15 seconds at 768P or 2K, with an audio track, and it has two companion endpoints: Context-IR, which rewrites prompts, and Regeneration, which turns a 768P preview into 2K.
The scenario is a small one. Bellwick is a leather shop we made up for this article, and it wants a handful of short product clips of a plain tan laptop sleeve for its website and social posts.
We ran nine tests on nine generated clips, one prompt rewrite and two still images, for $1.90 in API spend. Every clip was requested at 4 seconds, the minimum; seven were 768P and two were 2K. Sample sizes are small, usually one clip per condition, and we say so where it matters.
The setup
The test machine reported macOS 26.5.1 (sw_vers) and an Apple M5 Pro (sysctl -n machdep.cpu.brand_string). Python drove the API. For inspection we used command-line tools present on that machine: avmediainfo, avconvert, afinfo and mdls in /usr/bin, plus swiftc for two short AVFoundation programs and ffmpeg from Homebrew.
A note on what we did not do. We did not open any of these files in QuickTime Player or Final Cut Pro, and we did not use Shortcuts. “Playable” in this article means only what AVFoundation reported and, where stated, that it decoded a frame for us.
The job runner below is a condensed version of the script we ran, not the exact file: it omits the threading and the JSON log. The host is a placeholder. The one habit worth keeping is writing the task ID to disk before polling, so a dropped connection can never lead you to pay for the same clip twice.
import json, os, time, urllib.request
BASE = os.environ[“VIDEO_API_BASE”] # placeholder host
KEY = os.environ[“VIDEO_API_KEY”]
def call(method, path, body=None):
data = json.dumps(body).encode() if body else None
req = urllib.request.Request(BASE + path, data=data, method=method, headers={
“Authorization”: “Bearer ” + KEY, “Content-Type”: “application/json”})
with urllib.request.urlopen(req, timeout=90) as r:
return json.load(r)
job = {“model”: “MiniMax-H3”, “prompt”: PROMPT, “duration”: 4,
“resolution”: “768P”, “aspect_ratio”: “16:9”}
task_id = call(“POST”, “/v1/videos/generations”, job)[“data”][0][“task_id”]
open(“tasks.log”, “a”).write(task_id + “\n”) # save before polling
while True:
time.sleep(8)
t = call(“GET”, “/v1/tasks/” + task_id)[“data”]
if t[“status”] in (“completed”, “failed”, “cancelled”):
break
print(t[“cost”], t[“actual_time”], t[“result”][“videos”][0][“url”])
Download the MP4 as soon as the task completes, because the result URL is temporary. Prompts below are as sent.
Test 1: asking the file what it is
Close-up on a wooden workbench in a small leather workshop. A craftsperson’s hands stitch a tan leather laptop sleeve with waxed thread. Soft window light from the left, slow push-in. The sleeve is plain with no logos.
Server time was 98 seconds and the cost was $0.2056. We then pointed a 40-line Swift program at the file. It uses AVURLAsset to load isPlayable, isExportable and duration, then reads each track’s format description, natural size, nominal frame rate and estimated data rate. This condensed excerpt shows the idea; the full program also prints the audio fields as JSON:
let asset = AVURLAsset(url: URL(fileURLWithPath: path))
let playable = try await asset.load(.isPlayable)
let duration = try await asset.load(.duration).seconds
for track in try await asset.load(.tracks) where track.mediaType == .video {
let size = try await track.load(.naturalSize)
let fps = try await track.load(.nominalFrameRate)
print(playable, duration, size, fps)
}

The inspection pass. Nothing here needs a video player.
Three details came out of this that you would not get from watching the clip.
- The clip is longer than requested. We asked for 4 seconds and every one of our clips was 4.458 seconds of video, or 107 frames at 24 fps. We were billed for 4. Any timeline that assumes an exact duration should read the real value rather than the request.
- “768P” is 1344 by 768. In 16:9 that is the actual frame size, so it will not line up with a 1280 by 720 slot without scaling. The 9:16 clip came back as 768 by 1344. “2K” was 2560 by 1440.
- The audio is 32 kHz. AAC, two channels, about 128 kbps. That is fine for a social clip. If you are dropping it into a 48 kHz project, you will be resampling.
avmediainfo added a fourth. It printed “System support for decoding this track: Yes”, followed by three warnings that colour primaries, transfer function and YCbCr matrix were not specified. A player then has to guess those values. We tagged them without re-encoding, using ffmpeg’s h264_metadata bitstream filter, and the warnings disappeared from the avmediainfo report while the file changed by about 1 KB:
ffmpeg -i in.mp4 -c copy \
-bsf:v h264_metadata=colour_primaries=1:transfer_characteristics=1:matrix_coefficients=1 \
out.mp4
We chose BT.709 as a reasonable assumption for this kind of footage. The model does not state it, and we did not test how the tag changes the picture on any display.
Test 2: describing sound in the prompt
H3 returns an audio track by default, so we described sound directly:
Static shot of a tan leather laptop sleeve on a wooden workbench beside a window. Audio: steady rain tapping on the window glass, and two slow snips of metal scissors. No music, no voices.
Server time was 107 seconds, cost $0.2056. We did not assess this by ear for the article; we looked at the waveform, because that can be checked. The track has a very low bed, with a median level of -48.7 dB in 20 ms windows, and two main peaks at 2.42 and 3.38 seconds, reaching -17.0 and -15.4 dB. A smaller peak sits just before the first one, at 2.30 seconds. Two prominent transients is the number we requested.

The peaks line up with the scissors being on screen, but only the first is anywhere near the leather.
The picture brought a few problems. The sleeve came out dark brown rather than tan, and it has decorative stitching lines we did not ask for. A large pair of shears arrived on its own initiative, since we had only mentioned the sound of scissors, and at the second peak the blades are in the air with nothing to cut. Rain drops are visible on the glass, which is a sensible reading of the prompt. If you describe a sound, expect the model to show you its source.
The true peak here reached -0.4 dBTP against an integrated loudness of -24.1 LUFS, so a short transient sits very close to full scale. Keep that in mind if you normalize the clip upward.
Test 3: a spoken line, checked with a transcript
Medium shot of a woman in a canvas apron at a leather workbench, looking at the camera. She says clearly in English: “We make every sleeve by hand.” No music.
Server time was 101 seconds, cost $0.2056. We ran the audio through Whisper, which returned “We make every sleeve by hand.” That is a word-for-word match on a single run of a single short sentence, so it is a good result but not an error rate. Her mouth moves while the line plays and her hands stay on the bench. We checked frames only, so we are not making a claim about lip sync accuracy.
Whisper taught us something else. On tracks with no speech, it invented text: a lone “You” on some and a stock sign-off on others. So do not automate a check that treats any non-empty transcript as evidence of dialogue. The test has to compare the transcript against the line you asked for.
We also measured channel similarity for every clip by decoding it to raw samples and correlating left against right.

The speech clip is effectively dual mono. The others carry some real difference between channels.
AVFoundation reports two channels for every clip, and avmediainfo labelled the one we checked “Stereo (L R)”. The correlation adds detail. Ambient clips correlate at 0.80 to 0.97, so the channels do differ. The speech clip scores 1.000, with the side signal at -36.8 dB relative to mid. A centred voice is a normal mix, but there “stereo” describes the container more than the content. Two other findings matter more in practice: loudness varied from -12.9 to -51.5 LUFS across clips, and two clips reached +0.1 dBTP. Plan on a loudness pass before publishing a set of these side by side.
Test 4: letting Context-IR write the prompt
Context-IR takes an idea and returns a longer prompt with no video. We sent 11 words:
A craftsperson finishes a tan leather laptop sleeve at a workbench.
It took 32 seconds and cost $0.004 (5,655 input tokens, 266 output tokens). The prompt came back at 1,245 characters, labelled into three parts: integrated_multimodal_description, overall_soundscape and non_diegetic_music. Here is a shortened excerpt:
[Shot 1] Cinematic, a close-up shot focused on a weathered wooden workbench cluttered with leatherworking tools, as an artisan’s hands – a male craftsperson with calloused fingers – perform the final finishing touches… uses a smooth, dark wooden burnishing tool to rub the edges of the leather…
overall_soundscape: The crisp, rhythmic scraping sound of the wooden burnishing tool…
non_diegetic_music: A low, steady, acoustic guitar melody…

The top row is the Test 1 clip. The bottom row used the Context-IR text, unedited, at the same 768P and 4 seconds.
We passed that text to H3 unedited: 91 seconds, $0.2056. The finished clip is the most complete-looking of our set. It shows a finished sleeve with visible stitching, the burnishing motion is clear, and the lighting has more contrast. This is not a controlled comparison: it sets one clip against one clip, from different scene descriptions.
The catch is authorship. Context-IR made decisions a brand may care about: the maker’s gender, the apron, the lamp, the tool, and a guitar score. In our run the rewrite added a music line to an idea that never mentioned music, so check for that if you want a clean track. At $0.004 it is cheap enough to use every time, as long as someone reads the output and edits it before spending on video.
Test 5: Regeneration against a direct 2K render
This was the most useful result of the session. The Regeneration endpoint takes only a task ID, and that task must be a successful 768P H3 job from your own account:
{“model”: “MiniMax-H3-Regeneration”, “source_task_id”: “task_…”}
We regenerated the Test 1 preview, then separately rendered the identical prompt directly at 2K. Parameters and current per-second rates for all of these modes are listed on the MiniMax H3 API page. That page says the 768P price plus the Regeneration price equals the direct 2K price, and our billed amounts agree exactly: $0.2056 + $0.1236 = $0.3292, and direct 2K was $0.3292.

No seed was set, so a direct render of the same prompt is a new shot. Regeneration is not.
| Measure | 768P preview | Regenerated 2K | Direct 2K |
| Frame size | 1344 x 768 | 2560 x 1440 | 2560 x 1440 |
| Cost | $0.2056 | $0.1236 on top | $0.3292 |
| Server time | 98 s | 84 s | 146 s |
| File size | 1.17 MB | 2.94 MB | 4.01 MB |
| SSIM against preview, whole clip | n/a | 0.917 | 0.556 |
| Audio correlation against preview | n/a | 0.996 | -0.041 |
| Laplacian variance at 2.2 s, scaled to 1344 x 768 | 124.5 | 109.1 | 187.5 |
Regeneration kept the shot, the performance and, by correlation, the soundtrack. That changes review. With direct 2K, approving a draft means nothing, because the next render is a different clip. With previews, you reject at $0.21 each and pay the extra $0.12 only for the one you like.
There is a limit. Laplacian variance is a rough, single-frame sharpness measure. Scaled to the same size, the regenerated frame scored slightly below its own preview, and a crop of the same area looks very similar in both. The direct 2K frame scored higher, but it shows different content, so that is not a clean comparison. Our reading from this one pair: Regeneration gives you a bigger clip of the approved shot, so do not expect much added fine detail.
Test 6: first and last frames that disagree
We made two stills of the sleeve with an image model for $0.003 each, one closed and one open with a thin unbranded laptop half inside. We only noticed afterwards that the two stills do not share a camera position. That made a good stress test, so we kept them and asked for something impossible:
The flap of the leather sleeve folds open and a thin silver laptop slides partly out. The camera does not move.

Test 7: a reference image in a new location
The tan leather sleeve from the reference image sits on a cafe table beside a cup of black coffee. A hand picks it up and lifts it out of frame. Slow, natural light. No logos, no text.
The closed still went in through image_urls, which treats it as a reference and not as a first frame. Server time was 121 seconds, cost $0.2056. This was the best product result of the session. The colour, the flap shape and the single brass snap all match the reference, the hand does exactly what we asked, and by about 3.4 seconds the sleeve has left the frame.
It did not move the scene very far. We asked for a cafe table and got something close to the reference’s dark wood and window, with a coffee cup added. And the audio is close to silent, at -51.5 LUFS, with no peaks more than 15 dB above its median. A nearly silent track will not show up in any format check, so measure it if the clip will play with sound on.
Test 8: vertical, without a reference
Vertical shot looking down at a tan leather laptop sleeve on a dark walnut workbench. A hand slides a brass snap closed with a soft click. Soft window light. No logos, no text.

Left three: the reference holds the product. Right two: “tan leather” alone produced a redder sleeve and a different flap.
Server time was 178 seconds, cost $0.2056. The frame is a true 768 by 1344 and preferredTransform is the identity, so nothing relies on a rotation flag. But “tan” became a saturated orange-brown, and the flap has a new shape. The hand touches the snap and then covers it, without a clear closing action. The strongest audio peak, at 3.2 seconds, comes as the hand lies flat on the sleeve with the snap hidden. We can’t say from the waveform whether it sounds like a click. Compared with Test 7, this is the case for using a reference wherever the product has to look like the product.
Test 9: getting the file size down on the Mac
No generation here. We took the 2.94 MB regenerated clip and encoded it seven ways with avconvert and ffmpeg. All seven kept 107 frames. SSIM was measured against the source at 1280 by 720.

The avconvert presets we tried produced larger files than the source, even at lower resolution.
| Encode | Output | Size | SSIM | Wall time |
| avconvert Preset1920x1080 | H.264 1080p | 5.42 MB | 0.992 | 2.04 s |
| avconvert Preset1280x720 | H.264 720p | 3.71 MB | 0.991 | 2.03 s |
| avconvert PresetHEVC1920x1080 | HEVC 1080p | 3.73 MB | 0.992 | 2.03 s |
| avconvert PresetHEVCHighestQuality | HEVC 1440p | 4.79 MB | 0.994 | 2.03 s |
| ffmpeg libx264 CRF 23 | H.264 1080p | 1.63 MB | 0.992 | 0.67 s |
| ffmpeg hevc_videotoolbox q 55 | HEVC 1080p | 0.84 MB | 0.983 | 0.61 s |
| ffmpeg libx265 CRF 26 | HEVC 1080p | 0.79 MB | 0.989 | 1.22 s |
The surprise is that the avconvert presets made the file bigger. Preset1920x1080 returned 5.42 MB from a 2.94 MB source while reducing its resolution. Those presets appear to favour quality over size, so they suit an intermediate file better than a web upload. For delivery, ffmpeg with a quality target gave us a third of that size at the same measured SSIM, using libx264 at CRF 23.
The fastest route to a small file was hevc_videotoolbox, at 0.84 MB in 0.61 seconds, though its SSIM was the lowest of the set. For HEVC in an MP4, we set -tag:v hvc1. AVFoundation reported that file as hvc1 and playable, and AVAssetImageGenerator decoded a 1920 by 1080 frame from it. That is the extent of our playback testing.
Narrated walkthrough of the nine tests, including the spoken-line clip with its original audio.
What it all cost, and how long it took
| Item | Clips or calls | Server time | Billed |
| Stills for frame and reference tests | 2 | 22 to 53 s | $0.006 |
| 768P, 4 s clips | 7 | 91 to 178 s, median 107 s | $1.4394 |
| Context-IR rewrite | 1 | 32 s | $0.0040 |
| Regeneration to 2K, 4 s | 1 | 84 s | $0.1236 |
| Direct 2K, 4 s | 1 | 146 s | $0.3292 |
| Total | $1.9022 |
Our account was billed $0.0514 per second at 768P and $0.0823 at 2K, the rates shown for the page’s top discount tier. The standard member rates listed are $0.0571 and $0.0914, so the same set would cost you roughly 11% more. Most jobs were submitted together, so server times reflect one evening’s queue and are not a service level. Every job succeeded on its first submission. Video narration was extra.
A checklist for a Mac-based H3 workflow
- Write the task ID to disk before you poll, and download results straight away.
- Draft at 768P and 4 seconds, and read Context-IR’s rewrite before you use it. Check what it added, including music.
- Regenerate only the preview you approved. Do not expect a direct 2K call with the same prompt to reproduce it.
- Use a reference image when the product must look right. “Tan leather” alone produced three different browns in our set.
- Generate first and last frames from the same camera position, or accept that the model will move the view.
- Run avmediainfo on each result. Read real duration and size from the file, and tag colour if your pipeline needs it.
- Measure loudness and true peak across the batch. We saw a 38.6 LU spread and clips at +0.1 dBTP.
- Encode for delivery with a quality target. Check the size that the avconvert preset gives you before uploading it.
The bottom line
For a small shop working from a Mac, H3 fits a command-line routine well. Its files passed every format check we ran, and a short Swift program can catch most surprises before anyone reviews a clip. The model got a spoken line right in our one attempt, held a product from a reference image, and hit both ends of a first-and-last-frame request. The weak points were colour words without a reference, uninvited props, uneven audio levels, and a prompt rewriter with opinions of its own.
The decision we would carry forward is the review pattern from Test 5: reject cheaply at 768P, regenerate only the approved shot, then encode outside the presets. A finished 4-second clip came to $0.33 at our rates, and under 1 MB after encoding. We ran all of these jobs through APIMart, using one API key for the image, video and speech models involved.




