Invite & Earn

How invite rewards work

Share your invite link. When a friend registers through it and tops up, you receive the displayed reward on their subsequent top-ups.

Qwen Image 2.1 + MiniMax H3: A Local First/Last-Frame Video Pipeline

Learn when to choose fully local 768p, when hybrid 2K is justified, and how to generate Qwen frames, run H3-Base locally, compare hosted H3 with identical inputs, and diagnose failures.

Contents
Qwen Image 2.1 + MiniMax H3: A Local First/Last-Frame Video Pipeline

You may already be able to generate convincing first and last frames with Qwen. The real problem is whether H3 can connect them as one continuous shot—without changing the subject, inserting an unwanted cut, or calling an API-dependent 2K path “local.” This guide gives you a default route: prove the fully local 768p chain first, then switch to hybrid 2K only when the delivery requirement justifies it, and compare local and hosted H3 with identical inputs.

Start here: use local 768p unless you truly need 2K

If your goal is to validate the handoff, keep assets on your machine, or debug unwanted cuts, start with fully local 768p. Choose hybrid 2K only when 2K delivery is mandatory and you accept remote H3-Context-IR and H3-Regenerate-2K API calls.

Your goalStart withWhyWhat changes the recommendation
Prove the end-to-end chain worksFully local 768pIt has fewer variables, so Qwen image issues and H3 video issues are easier to separateMove on only after 768p is stable and delivery truly requires 2K
Keep assets on your own machineFully local 768pThe Qwen frames and H3-Base run can remain localIf 2K is mandatory but remote APIs are forbidden, the documented full 2K route does not meet the requirement; use another local 2K solution
Deliver a final 2K videoHybrid 2KThe official full 2K route still depends on two hosted modulesFall back to 768p or another solution if assets cannot be sent remotely
Decide whether local or hosted H3 fits betterProve local 768p first, then run a paired testOtherwise deployment errors get mixed with model qualityLock in a long-term route only after repeated tests across several shot types

Do not promise compatibility from the GPU name alone. MiniMax’s SGLang example uses four GPUs, while the public run used a DGX Spark; neither provides a minimum VRAM figure or proves that an ordinary consumer GPU will work.

What can actually stay on your machine?

Qwen frame generation and H3-Base 768p can stay local; the official end-to-end 2K route cannot.

StageCan it run locally?Documented boundary
Generate and edit first/last frames with Qwen Image 2.1YesThe official repository provides QwenImage21Pipeline, local Diffusers examples, native 2K sizes, and support for up to 10 reference images
Convert first/last frames to audio-video with MiniMax H3-BaseYesThe open FL2VA checkpoint accepts zero, one, or two images; two images select first-and-last-frame mode, with local validation at 768p
H3-Context-IRNot as the complete official local implementationMiniMax describes it as a hosted preprocessing and orchestration system that is not part of the open release; use the API or build your own preprocessing from the prompting guidance
H3-Regenerate-2KNot from the currently open componentsThe module is not open-sourced; the official full 2K workflow calls it through an API
Hosted H3 comparisonNoA web or API run is remote by definition and serves only as the paired comparison

MiniMax also documents 4–15-second output, 24 FPS, 32 kHz stereo audio, and a default short side of 768 pixels; 2K is produced through H3-Regenerate-2K. Those are model boundaries, not a promise that every setting will fit your hardware.

One public test proves feasibility, not a universal winner

Use the example as a test design, not as a verdict that local H3 is always better.

Filmmaker Sam Wasserman posted one local idea-to-image-to-video run on a DGX Spark using Qwen Image 2.1 and MiniMax H3. The attached result is roughly eight seconds long. In a follow-up, he says he reused the same prompt, specifications, and first/last frames with paid Web H3. He reported that the web result inserted an unwanted cut while the local result preserved the intended sequence.

That is useful as an existence proof and as a comparison design. It is not evidence that local H3 is generally better. The posts disclose no installation commands, peak memory, generation time, audio treatment, seeds, or failed attempts. The follow-up is also the same author judging one input, not an independent replication.

Step 1: reduce the idea to one continuous shot

Ask for one setting, one action chain, and one end state. Write those constraints as a shot contract—a short specification that both you and the model can be checked against.

FieldWhat to define
Subject and settingPeople, objects, clothing, background, and identity features that must remain stable
Start statePosition, pose, gaze, camera distance, composition, and lighting in the first frame
End stateOnly the change allowed in the last frame; avoid changing subject, location, and camera position at once
Motion pathHow the subject moves, whether the camera moves, and the order of actions
Continuity constraintsExplicit instructions such as “one continuous shot,” “no cuts,” and “no teleporting”
Output specificationDuration, aspect ratio, and whether dialogue, ambience, or music is required
Negative constraintsUnwanted characters, captions, scene changes, background replacement, or extra actions

When the test is meant to detect unwanted cuts, do not ask for multiple locations, time periods, or a montage in the same prompt. Otherwise, a cut may be a reasonable interpretation of the instruction rather than a model failure.

For example, “walk from the doorway to the table, pick up the cup, no cuts” is a useful first/last-frame test. “Move from a street to an office, then flash back to childhood” naturally needs multiple scenes, so it cannot cleanly test unwanted cuts.

Step 2: generate the first frame, then edit it into the last frame

Create the last frame by editing the first one instead of generating two unrelated images. This makes it easier to preserve identity, clothing, composition, and background before H3 even starts.

The official model ID is Qwen/Qwen-Image-2.1. Qwen documents a 7B visual generation component, local Diffusers support, generation and editing, native 2K output, and up to 10 reference images.

pip install "torch>=2.4.0" "transformers>=5.17" accelerate pillow
pip install git+https://github.com/huggingface/diffusers
from pathlib import Path

import torch
from diffusers import QwenImage21Pipeline

first_prompt = Path("first_prompt.txt").read_text(encoding="utf-8").strip()
last_edit_prompt = Path("last_edit_prompt.txt").read_text(encoding="utf-8").strip()

pipe = QwenImage21Pipeline.from_pretrained(
    "Qwen/Qwen-Image-2.1",
    torch_dtype=torch.bfloat16,
).to("cuda")

first = pipe(
    prompt=first_prompt,
    width=2752,
    height=1536,
    num_inference_steps=40,
    generator=torch.Generator("cuda").manual_seed(42),
).images[0]
first.convert("RGB").save("first.png")

last = pipe(
    prompt=last_edit_prompt,
    image=first,
    width=2752,
    height=1536,
    num_inference_steps=40,
    generator=torch.Generator("cuda").manual_seed(43),
).images[0]
last.convert("RGB").save("last.png")

This code combines the official generation and single-image editing interfaces; you provide first_prompt and last_edit_prompt. It uses Qwen’s documented 16:9 2K size of 2752 × 1536, 40 steps, and opaque RGB PNG files. Public H3 documentation does not specify alpha-channel behavior for this handoff, so opaque frames remove one variable unless you have separately validated RGBA.

After generation, record more than the filenames:

  • model ID, framework version, first-frame prompt, and last-frame edit prompt;
  • both seeds, width, height, inference steps, and reference-image list;
  • SHA-256, pixel dimensions, and color mode for both files;
  • whether identity, wardrobe, composition, lighting, and background remain consistent;
  • whether the last frame shows only the desired end state rather than the whole motion sequence.

Qwen also documents enable_model_cpu_offload() for limited-memory GPUs. That proves an offload path exists; it does not establish a minimum VRAM figure or a speed guarantee for this combined pipeline.

Step 3: make local and hosted H3 read the same inputs

Do not re-enter parameters from memory in two interfaces. Put the images, prompt, and output settings in one manifest; a different seed, duration, or rewritten prompt can invalidate the entire comparison.

experiment_id: "qwen-h3-001"
qwen_model: "Qwen/Qwen-Image-2.1"
h3_model: "MiniMaxAI/MiniMax-H3"
h3_variant: "fl2va"
prompt_file: "prompt.txt"
first_frame: "first.png"
last_frame: "last.png"
prompt_sha256: "<sha256>"
first_frame_sha256: "<sha256>"
last_frame_sha256: "<sha256>"
duration_seconds: "<same value>"
aspect_ratio: "<same value>"
local_seed: "<record if exposed>"
hosted_seed: "<record or not_exposed>"

Both local and hosted runs should read from this record. When the hosted UI hides the seed, rewrites the prompt, or restricts duration, write not_exposed or save the rewritten prompt. Do not pretend the parameters are identical. A result difference is interpretable only after visible inputs have been controlled.

Step 4: make the local H3-Base 768p result work first

Accept the 768p result before thinking about 2K. Qwen’s still frames may be 2K, but that does not make the local H3-Base video 2K.

MiniMax publishes two task-specific checkpoints. This workflow uses MiniMax-H3 Base FL2VA, which supports text, first-frame, last-frame, or first-and-last-frame-to-audio-video generation in BF16. The official download and SGLang serving example are:

hf download MiniMaxAI/MiniMax-H3 \
  --include "FL2VA/*" \
  --local-dir MiniMax-H3

sglang serve \
  --model-path MiniMaxAI/MiniMax-H3 \
  --num-gpus 4 \
  --ulysses-degree 4 \
  --performance-mode speed \
  --host 0.0.0.0 \
  --port 30010 \
  --model-variant fl2va

The second command is MiniMax’s four-GPU example. It is not Wasserman’s disclosed DGX Spark configuration and it is not a minimum requirement. Adjust it only with the relevant framework documentation and record every change; do not present this example as proof that all machines can run H3.

Make both frames visible to the SGLang process

FL2VA accepts one or two image conditions with role: "keyframe". The official SGLang H3 guide defines frame_index: 0 as the first frame, frame_index: -1 as the last frame, and [0, -1] as the first-and-last-frame set. MiniMax’s reproducible script shows the first-frame form; the request below uses the same fields with both endpoint images.

A file:// URI is resolved by the SGLang server process, not by the terminal running curl. When both run on the same host, the default realpath values work. If SGLang runs in a container or on another machine, mount or copy both images there and override FIRST_URI and LAST_URI with paths that the server can actually read.

Save the shot contract as prompt.txt. For fully local 768p, it can contain your own structured prompt. In the hybrid 2K route, put the H3-Context-IR result in the same prompt field, then send the H3-Base result to H3-Regenerate-2K.

Submit FL2VA, wait for completion, and save the MP4

The script follows the documented asynchronous lifecycle: create the job with POST /v1/videos and read .id, poll GET /v1/videos/{id}, and call GET /v1/videos/{id}/content only after status becomes completed. The official cookbook treats failed as terminal; every other non-empty status remains in the wait loop.

set -euo pipefail

BASE_URL="${BASE_URL:-http://127.0.0.1:30010}"
FIRST_URI="${FIRST_URI:-file://$(realpath first.png)}"
LAST_URI="${LAST_URI:-file://$(realpath last.png)}"
PROMPT_FILE="${PROMPT_FILE:-prompt.txt}"
OUTPUT_FILE="${OUTPUT_FILE:-fl2va.mp4}"

payload=$(
  jq -n \
    --rawfile prompt "$PROMPT_FILE" \
    --arg first "$FIRST_URI" \
    --arg last "$LAST_URI" \
    '{
      model: "MiniMaxAI/MiniMax-H3",
      task: "fl2va",
      prompt: $prompt,
      seconds: 8,
      conditions: [
        {
          type: "image",
          uri: $first,
          role: "keyframe",
          frame_index: 0
        },
        {
          type: "image",
          uri: $last,
          role: "keyframe",
          frame_index: -1
        }
      ],
      target: {
        short_edge: 768,
        aspect_ratio: "auto",
        duration_seconds: 8
      },
      seed: 0
    }'
)

response=$(
  curl --fail-with-body --silent --show-error \
    --request POST \
    --url "$BASE_URL/v1/videos" \
    --header 'Content-Type: application/json' \
    --data-binary "$payload"
)

video_id=$(printf '%s\n' "$response" | jq -er '.id')
printf 'video_id=%s\n' "$video_id"

while true; do
  task_json=$(
    curl --fail-with-body --silent --show-error \
      --request GET \
      --url "$BASE_URL/v1/videos/$video_id"
  )
  status=$(printf '%s\n' "$task_json" | jq -er '.status')
  printf 'status=%s\n' "$status"

  case "$status" in
    completed)
      break
      ;;
    failed)
      printf '%s\n' "$task_json" | jq .
      exit 1
      ;;
    *)
      sleep 1
      ;;
  esac
done

curl --fail-with-body --silent --show-error --location \
  --request GET \
  --url "$BASE_URL/v1/videos/$video_id/content" \
  --output "$OUTPUT_FILE"

test -s "$OUTPUT_FILE"

if command -v ffprobe >/dev/null 2>&1; then
  ffprobe -v error \
    -show_entries stream=codec_type,codec_name,r_frame_rate,sample_rate,channels \
    -of default=noprint_wrappers=1 \
    "$OUTPUT_FILE"
fi

printf 'saved=%s\n' "$OUTPUT_FILE"

curl --fail-with-body stops on a non-2xx response, and jq -e stops if .id or .status is missing. On failed, the script prints the complete job JSON and exits nonzero; the success path also requires the content request to succeed and the MP4 to be non-empty.

When ffprobe is installed, the script reports the media streams. SGLang’s documented output contract is an MP4 with H.264 video at 24 fps and one AAC stereo stream at 32 kHz. If the job says completed but the file is empty, undecodable, or has unexpected media properties, do not move to the hosted comparison; inspect the SGLang log, server-visible image URIs, and request JSON first.

The fields and endpoints come from MiniMax’s reproducible FL2VA script, the SGLang MiniMax-H3 cookbook, and the SGLang video API guide. The fully local path now ends with an H3-Base 768p MP4; full 2K still follows the hybrid route described earlier.

Step 5: run the hosted comparison only after the local chain is stable

Do not compare quality while the local chain is still failing. Otherwise deployment errors, input differences, and model behavior become impossible to separate. Change only the execution location:

  1. Upload byte-identical first and last frames and verify their hashes.
  2. Reuse the same prompt, duration, aspect ratio, language, and audio intent.
  3. Record whether the web/API path rewrites the prompt, exposes a seed, or invokes H3-Context-IR.
  4. Keep the original outputs; do not edit, re-encode, or add music before comparison.
  5. Hide the origin labels and review blindly to reduce the expectation that “local must be better” or “paid must be better.”

To compare cost, record your own API charge, machine time, and power use. The labels “local” and “paid web” alone do not show which route is cheaper for your workload.

Step 6: use one scorecard to choose the better route for your shots

Check whether the clip completes the creative task before comparing runtime or hardware. A higher-resolution result that keeps inserting cuts may still be the worse production choice.

CriterionHow to inspect itWhat to record
First-frame fidelityDoes the opening retain the subject, composition, and key objects instead of immediately replacing them?Deviation and timestamp
Arrival at the last frameDoes the clip naturally reach the specified final state rather than abruptly switching to the last image?Final state and transition quality
Single-shot continuityAre there unrequested cuts, teleports, scene replacements, or time jumps?Cut timestamps and before/after captures
Identity and background stabilityDo face, clothing, hands, props, and background geometry remain stable?Affected object and duration
Motion pathDo subject and camera move in the agreed order and direction?Direction errors, speed jumps, or stalls
AudioWhen requested, is a track present, synchronized, and free of pops or unrelated content?Media properties, sync offset, abnormal segment
Output specificationDo duration, aspect ratio, frame rate, and resolution match the configured values?Actual media metadata
Runtime resourcesWall-clock generation time, peak accelerator memory, system memory, and retriesRaw logs for every run, not estimates
RepeatabilityDoes the same issue recur when the controlled input is rerun?Repeated results and exposed random settings

MiniMax says H3 can generate 32 kHz stereo audio. Wasserman’s posts do not say whether audio was enabled, preserved, or post-processed. You can inspect your own result, but you cannot cite that example as an audio-quality validation.

Fix the upstream layer instead of rerunning everything

A wrong first frame belongs in Qwen, a continuity problem belongs in H3, and a resolution mismatch starts with checking whether you chose local 768p or hybrid 2K. Layered diagnosis saves more time than changing every parameter at once.

SymptomCheck firstCorrective action
The first frame is already wrongQwen image stageFix the first prompt, references, and seed instead of trying to repair a bad composition inside H3
Identity or background changes in the last frameQwen handoff assetEdit from the first frame rather than generating independently; reduce changes and reuse stable references
An unexpected cut appearsH3 prompt and motion constraintsRequire one continuous shot, remove montage or multi-scene language, and rerun with the same image hashes
The clip never reaches the last frameDuration or motion planShorten the action chain and define a clear start–process–finish sequence
Audio is missing or mismatchedH3 variant, client, and containerConfirm an audio-video checkpoint and request path; mark runs without comparable audio as not comparable
Qwen runs out of memoryImage deploymentTry the documented CPU offload and measure the speed impact; do not infer a universal minimum VRAM
H3 will not start on current hardwareH3 deploymentFollow the framework deployment guide; the official sample uses four GPUs, but consumer hardware is not guaranteed
Local output stops at 768p and 2K requires an APIWorkflow boundaryThis is the documented architecture, not a local service defect; accept 768p or choose the hybrid 2K path
Local and hosted results diverge sharplyInput and preprocessingCheck prompt rewriting, Context-IR, seed visibility, duration, aspect ratio, and re-encoding before attributing the difference to the model

How to choose local or hosted H3 for long-term use

Base the decision on your shot set, not on the single best-looking sample. Cover static camera work, human action, object transformation, dialogue, and ambience, and preserve both successes and failures; keep these measurements separate:

  • clip duration, such as the roughly eight-second community example;
  • generation time, the wall-clock interval from submission to completed file, which the example does not disclose;
  • model specifications, which come from the vendor documentation;
  • actual hardware use, measured on your system rather than guessed from the device name;
  • one visual judgment, which describes that run and cannot be converted directly into an overall win rate.

If assets must stay on your machine, keep the local 768p route by default. If final delivery must be 2K and remote APIs are acceptable, use hybrid 2K. If continuity matters most, blind-review local and hosted H3 on the same shot set and prefer the route that passes your scorecard more consistently. The public example shows that the local route can run and avoided one unwanted cut in one same-input test; it cannot replace your own repeated evaluation.

Check these eight items before you run

  • The run is labeled either “fully local 768p” or “hybrid 2K,” without mixing the terms.
  • Qwen model, prompts, seeds, dimensions, and references are recorded for both frames.
  • Images and prompt are hashed, and both H3 runs consume the same inputs.
  • The local run uses fl2va and is first accepted as an H3-Base 768p result.
  • Hosted prompt rewrites and hidden parameters are recorded honestly.
  • Original videos remain unedited and use the same continuity, cut, audio, and specification rubric.
  • Wall time, peak memory, retries, and failures come from logs.
  • Conclusions are limited to the tested samples, hardware, and verification date.

Bottom line

The default recommendation is clear: generate the first and last frames locally with Qwen Image 2.1, then prove local 768p with MiniMax H3-Base fl2va. Switch to H3-Context-IR → local H3-Base → H3-Regenerate-2K only when 2K delivery is mandatory and remote APIs are acceptable.

Whichever route you choose, freeze the frames, prompt, duration, and aspect ratio, then compare continuity, unwanted cuts, audio, wall time, and hardware use with identical inputs. That turns a good-looking demo into a workflow you can audit, compare, and adopt deliberately.

References

Facts checked: September 26, 2026.

Ready to optimize your LLM workflow?

Join thousands of developers building faster, smarter, and more cost-effective AI applications with BetterToken.

Get Started for Free