H3 Max Recast request rejected: every field Sume refuses

Sume refuses H3 Max Recast bodies with aspect_ratio, generate_audio, bitrate_mode, frame or audio references, or a duration outside 5-30 s. The full list.

5 min readSume
All posts

If a Sume H3 Max Recast request fails before it starts, the cause is almost always one of the fields or values the model row refuses: a missing or non-public video_url, zero or more than four photos, resolution other than 768p or 1080p, a duration outside 5 to 30 seconds, a prompt over 2000 characters, or any of the frame, audio, aspect and bitrate fields that belong to other models.

The refusals come from Sume's request builder before the request goes to fal. That is the point of the narrow contract: Recast keeps the source video's framing, cuts and soundtrack, so there is nothing for an aspect ratio or an audio switch to control. fal's H3 Max Recast page (read 2026-10-02) lists a video, reference images and a 768p or 1080p output; Sume's Video Router docs add the 1 to 4 photo cap and the 5 to 30 second range.

Which fields are always refused?

The table groups what the request builder in the Sume API checks. The messages quoted are the ones the code raises, so you can match them in a client log.

A pattern worth noticing: most refusals are fields that are normal on other Sume video models. If you built a client around minimax-h3-max or seedance-2.5 and swapped only the model id, that is exactly how you will hit them.

What h3-max-recast refuses on Sume (read 2026-10-02)
Field or valueRuleMessage theme
video_url missing, not https, localhost or with credentialsOne public source URL requiredrequires one source video URL
reference_image_urls empty, more than 4, or a non-public URL1 to 4 photos, one per new personrequires 1-4 reference image URLs
resolution 480p, 720p, 2KOnly 768p (default) or 1080presolution must be 768p or 1080p
duration missing, under 5 or over 30Inspected source length, 5 to 30 srequires the inspected source duration
prompt over 2000 charactersOptional, cappedprompt must be at most 2000 characters
aspect_ratio, generate_audio, bitrate_modeNot supporteddoes not support <field>
image_url, first_frame_url, end_image_url, last_frame_urlNot supporteddoes not support <field>
reference_video_urls, reference_audio_urlsNot supporteddoes not support <field>

Why is generate_audio refused instead of ignored?

Because the audio is the source's. Per fal's page the model preserves the source audio, and Sume's Video generation docs say h3-max-recast accepts video references but not audio. Silently accepting generate_audio: true would suggest a new soundtrack that never arrives, so the request fails instead.

The same logic covers aspect_ratio: the output follows the source frame. If you need a different shape, change the source first, then recast.

Why does duration trip people up?

On other models duration is what you want. On Recast it is a fact about the source, 5 to 30 seconds, used to price and reserve the job and never forwarded to fal. Sume's API reference also notes a shot rule: the person swap works on sources with no shot over 15 seconds, so a single unbroken 25 second take is within the duration range but outside that shot rule.

Probe the clip before you submit. Video inspect is unbilled for probe and stills, and it returns the facts that tell you the length and whether the clip has audio.

Can you check a body before you send it?

Yes, and it is cheap. This preflight mirrors the rules above and runs as is. It does not call Sume; it only tells you which rule a body would break, so a bad body never costs a round trip.

It cannot know whether your URLs are reachable or whether a clip has a shot over 15 seconds. Those need the inspect step.

BANNED = {"aspect_ratio", "generate_audio", "bitrate_mode", "image_url",
          "first_frame_url", "end_image_url", "last_frame_url",
          "reference_video_urls", "reference_audio_urls"}

def recast_problems(body):
    out = [f"{k} is not supported" for k in BANNED if k in body]
    if not str(body.get("video_url", "")).startswith("https://"):
        out.append("video_url must be public https")
    photos = body.get("reference_image_urls") or []
    if not 1 <= len(photos) <= 4:
        out.append("1 to 4 reference_image_urls")
    if body.get("resolution", "768p") not in ("768p", "1080p"):
        out.append("resolution must be 768p or 1080p")
    d = body.get("duration")
    if not isinstance(d, (int, float)) or not 5 <= d <= 30:
        out.append("duration must be 5 to 30")
    if len((body.get("prompt") or "").strip()) > 2000:
        out.append("prompt over 2000 characters")
    return out

print(recast_problems({"video_url": "https://a.test/v.mp4", "duration": 4,
                       "aspect_ratio": "16:9"}))

How should a client guard against these?

Build the Recast body from a small allowlist rather than copying a generic video body. Keep exactly model, video_url, reference_image_urls, duration, resolution, optional prompt, plus the communication fields (mode, Idempotency-Key). Everything else goes through a different model row.

If a refusal still appears, read the message first: each one names the field. Do not retry the same body; a refused request will be refused again. Once the body is clean, submit async and follow the jobs flow in Jobs and results. The prompt post covers the one field that is optional.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume